futex机制介绍

Futex系统调用,Futex机制,及具体案例分析 Futex1、背景1.1 自己实现锁1.1.1 自旋锁1.1.2 sleep+自旋1.1.3 小结1.2 futex1.2.1 什么是Futex1.2.2 futex诞生之前1.2.3 futex诞生之后2、Futex系统调用3、Futex机制4、具体案例分析4.1 在Bionic中的实现4.2 C语言实现5、参考及扩展阅读 首先要区分一下futex系统调用和futex机制futex系统调用是操作系统提供给上层的系统调用接口。而futex机制是使用futex接口实现的一种锁。 1、背景 线程同步可以说 阅读详情

1、概念
futex: a sort of fast, user-space mutual exclusion primitive. 
Futex是一种用户态和内核态混合的同步机制。首先,同步的进程间通过mmap共享一段内存,futex变量就位于这段共享的内存中且操作是原子的,当进程尝试进入互斥区或者退出互斥区的时候,先去查看共享内存中的futex变量,如果没有竞争发生,则只修改futex,而不用再执行系统调用了。当通过访问futex变量告诉进程有竞争发生,则还是得执行系统调用去完成相应的处理(wait 或者 wake up)。简单的说,futex就是通过在用户态的检查,(motivation)如果了解到没有竞争就不用陷入内核了,大大提高了low-contention时候的效率。
https://lwn.net/Articles/172149/
https://lwn.net/Articles/360699/
2、futex的由来
为什么要有futex,他解决什么问题?何时加入内核的?我们来看下
经研究发现,很多同步是无竞争的,即某个进程进入互斥区,到再从某个互斥区出来这段时间,常常是没有进程也要进这个互斥区或者请求同一同步变量的。但是在这种情况下,这个进程也要陷入内核去看看有没有人和它竞争,退出的时侯还要陷入内核去看看有没有进程等待在同一同步变量上。这些不必要的系统调用(或者说内核陷入)造成了大量的性能开销。为了解决这个问题,Futex就应运而生。
前面的概念已经说了,futex是一种用户态和内核态混合同步机制,为什么会是用户态+内核态,听起来有点复杂,由于我们应用程序很多场景下多线程都是非竞争的,也就是说多任务在同一时刻同时操作临界区的概率是比较小的,大多数情况是没有竞争的,在早期内核同步互斥操作必须要进入内核态,由内核来提供同步机制,这就导致在非竞争的情况下,互斥操作扔要通过系统调用进入内核态。
我们来看一下程序
程序1:
pthread_mutex_t lock;
int count = 0;
void thread1()
{
    while(1)
    {
        pthread_mutex_lock(&lock);
        /* do something */
        count++;
        pthread_mutex_unlock(&lock);
    }
}
void thread2()
{
    while(1)
    {
        sleep(60);
        pthread_mutex_lock(&lock);
        count = 0;
        pthread_mutex_unlock(&lock);
    }
}
pthread_create(&tid1, NULL, thread1, NULL);
pthread_create(&tid2, NULL, thread1, NULL);

假设系统中有2个程序,一个线程在滴答自增,一个线程周期性清除计数器。显然两个线程同时进入临界区的几率相当小,在未实现futex机制之前,每次调用pthread_mutex_lock和unlock都要通过syscall进入内核,内核检查该锁的拥有者,发现没有人持则返回到用户态,因为大部分时间2个线程并没有争抢互斥锁。显然大部分时间在做无用功,时间浪费在user->kernel和kernel→usr的切换,显然这个锁的性能不太好,因为存在大量user→kernel、kernel→usr的切换,例子可能不太恰当,get到点就好。

那么如何解决这个问题?
就像前面说的,采用用户态+内核态混合机制,在用户态使用原子操作,对持有锁的持有情况进行判断,如果锁可以占用,那么更新锁的状态并直接占用,不需要进入内核态,如果锁已经占用,则进入内核态挂起当前任务,事实上这些操作对程序员不可见的,一般都是由C库提实现好了。
Glibc中常用的线程同步方式举例:
Semaphore
变量定义:    sem_t sem;
初始化:      sem_init(&sem,0,1);
进入加锁:     sem_wait(&sem);
退出解锁:     sem_post(&sem);
Mutex
变量定义:    pthread_mutex_t mut;
初始化:      pthread_mutex_init(&mut,NULL);
进入加锁:     pthread_mutex_lock(&mut);
退出解锁:     pthread_mutex_unlock(&mut);
这些用于同步的函数和futex有什么关系?下面让我们来看一看:
以Semaphores为例,
进入互斥区的时候,会执行sem_wait(sem_t *sem),sem_wait的实现如下:
int sem_wait (sem_t *sem)
{
int *futex = (int *) sem;
if (atomic_decrement_if_positive (futex) > 0)
return 0;
int   err = lll_futex_wait (futex, 0);
return -1;
)
atomic_decrement_if_positive()的语义就是如果传入参数是正数就将其原子性的减一并立即返回。如果信号量为正,在Semaphores的语义中意味着没有竞争发生,如果没有竞争,就给信号量减一后直接返回了。
如果传入参数不是正数,即意味着有竞争,调用lll_futex_wait(futex,0),lll_futex_wait是个宏,展开后为:
#define lll_futex_wait(futex, val) \
({                                          \

__asm __volatile (LLL_EBX_LOAD                          \
LLL_ENTER_KERNEL                          \
LLL_EBX_LOAD                          \
: “=a” (__status)                          \
: “0″ (SYS_futex), LLL_EBX_REG (futex), “S” (0),          \
“c” (FUTEX_WAIT), “d” (_val),                  \
“i” (offsetof (tcbhead_t, sysinfo))              \
: “memory”);                          \
…                                      \
})
可以看到当发生竞争的时候,sem_wait会调用SYS_futex系统调用,并在val=0的时候执行FUTEX_WAIT,让当前线程休眠。
2002年的ols文档,在linux-2.5.7引入了futex。
https://www.kernel.org/doc/ols/2002/ols2002-pages-479-495.pdf

2、内核配置:
在内核配置选项中可以看到,默认是勾选的。 CONFIG_FUTEX=Y
 [*] Enable futex support
CONFIG_FUTEX: │
│ │
│ Disabling this option will cause the kernel to be built without │
│ support for "fast userspace mutexes". The resulting kernel may not │
│ run glibc-based applications correctly.
从CONFIG_FUTEX的注释中我们可以发现,我们会发现一个问题,注释说如果CONFIG_FUTEX=N,则生成的内核可能不能正常运行glibc应用程序。为什么会这样?
从上面futex例子我们可以看出,在Semaphores和mutex的实现过程中使用了futex,说明glibc库使用了futex,而其他的常用的同步手段也是建立在futex机制上,包括用户态下的操作和核心态下的操作。
未完--待续

Linux进程同步机制-Futex 引子 在编译2.6内核的时候,你会在编译选项中看到[*] Enable futex support这一项,上网查,有的资料会告诉你"不选这个内核不一定能正确的运行使用glibc的程序",那futex是什么?和glibc又有什么关系呢? futex诞生之前 在futex诞生之前,linux下的同步机制可以归为两类:用户态的同步机制 和 内核同步机制。 用户态的同步机制基本上就是利用原子指令实现的sp... 阅读详情

相关推荐

linux内核级同步机制--futex

我们知道glibc的底层是用linux futex机制实现理想的同步机制应该是没有锁冲突时在用户态利用原子指令就解决问题,而需要挂起等待时再使用内核提供的系统调用进行睡眠与唤醒。换句话说,在用户态的自旋失败时,能不能让进程挂起,由持有锁的线程释放锁时将其唤醒?上述代码的问题是trylock和wait两个调用之间存在一个窗口:如果一个线程trylock失败,在调用wait时持有锁的线程释放了锁,当前线程还是会调用wait进行等待,但之后就没有人再唤醒该线程了。futex_wait和。

m0_74282605的博客 494

futex简介

找到一篇很好的文章,讲得深入浅出;貌似原网站也很不错。 转载自 http://linuxperf.com/?p=23 futex (fast userspace mutex) 是Linux的一个基础构件,可以用来构建各种更高级别的同步机制,比如锁或者信号量等等,POSIX信号量就是基于futex构建的。大多数时候编写应用程序并不需要直接使用futex,一般用基于它所实现的系统库就够了。 futex的性能非常优异,它是怎样做到的呢?这要从它的设计思想谈起。传统的SystemV IPC(inter proces

FinixLei的专栏 (https://github.com/FinixLei) 3940

[Pthread] Linux中的线程同步机制(一) -- Futex

引子在编译2.6内核的时候,你会在编译选项中看到[*] Enable futex support这一项,上网查,有的资料会告诉你"不选这个内核不一定能正确的运行使用glibc的程序",那futex是什么?和glibc又有什么关系呢?1. 什么是FutexFutex是Fast Userspace muTexes的缩写,由Hubertus Franke, Matthew Kirkwood, Ingo

Javadino的专栏 6507

Linux内核 -- 进程间通讯之futex

Futex(Fast Userspace Mutex) 是一种用于实现高效同步的机制,允许在用户态完成大部分锁操作,仅在必要时才进入内核态。Futex 最常见的使用场景是互斥锁、条件变量和读写锁。

sz66cm 学习随笔 2388

Linux Futex学习笔记

简要介绍linux中的futex的功能,原理以及示例程序

weixin_73622063的博客 1467

深度讲解futex问答(上)

futex是Fast Userspace muTEX的缩写,该机制是由Rusty Russell、Hubertus Franke和Mathew Kirkwood在2.5.7版本的内核中引入,虽然名字中有互斥锁(mutex)的含义,但实际它是一种用于用户空间应用程序的通用同步工具(基于futex可以在userspace实现互斥锁、读写锁、condition variable等同步机制)。Futex组成包括:内核空间的等待队列。

youzhangjing_的博客 3559

Linux futex

下面的代码是我学习Linux futex时写的实验代码,存在大量谬误和不规范的地方,有许多认识上的错误。 这只是实验代码,实际工作中不会如此编程。 futex_t::wake 实际是一个计数器,防止在调用futex_wait函数前调用futex_wake而出现的死等现象, 函数futex只在满足(*addr1 == val)时等待。 futex_wait函数futex_wake函数配合使用,前者等待后者唤醒。 futex_lock函数futex_unlock函数配合使用,前者加锁后者解锁。

leeshuheng的专栏 4847

Futex同步机制

引子在编译2.6内核的时候,你会在编译选项中看到[*] Enable futex support这一项,上网查,有的资料会告诉你"不选这个内核不一定能正确的运行使用glibc的程序",那futex是什么?和glibc又有什么关系呢?1. 什么是FutexFutex 是Fast U

vivi的技术博客 1525

Linux进程同步机制Futex

引子 在编译2.6内核的时候,你会在编译选项中看到[*] Enable futex support这一项,上网查,有的资料会告诉你"不选这个内核不一定能正确的运行使用glibc的程序",那futex是什么?和glibc又有什么关系呢? 1. 什么是Futex Futex 是Fast Userspace muTexes的缩写,由Hubertus Franke, Matthew Kirk

交叉编译的博客 1362

linux内核futex快速用户空间互斥体简介

futex是一种用户态和内核态混合的同步机制。通过在用户态检查,没有竞争就不陷入内核执行系统调用了。访问futex变量通知进程有竞争发生,则执行系统调用去完成相应的操作。 进程、线程可以利用futex来进行同步。 futex同步操作都应该从用户空间开始,创建一个futex整形同步变量。

focus on security 2483

linux进阶40——futex

1. 概念 Futex 是Fast Userspace muTexes的缩写,由Hubertus Franke, Matthew Kirkwood, Ingo Molnar and Rusty Russell共同设计完成。 Futex按英文翻译过来就是快速用户空间互斥体。其设计思想其实 不难理解,在传统的Unix系统中,System V IPC(inter process communication),如 semaphores, msgqueues, sockets还有文件锁机制(flock())等进程

www_dong的博客 3795

linux快速用户空间互斥锁:futex浅析

Futex,Fast Userspace muTEXes,作为linux下的一种快速同步(互斥)机制,已经存在了很长一段时间了(since linux 2.5.7)。它有什么优势?又提供了怎样一些功能,本文就简单探讨一下。

flynetcn的专栏 828

futex同步机制分析之一应用

futex同步机制分析之一应用 一、多线程(进程)的同步机制 c++编程中最难的部分有哪些,估计绝大多数人都会首先提出来是多线程(进程)编程。为什么多线程编程难呢?一个主要的原因就是多线程的同步。在多线程同步中,(Linux平台Posix NPTL)中主要有三个同步手段:Semaphore(信号灯)、Mutex(互斥体)和Condition Variables(条件变量)。在c++11的标准中,同...

fpcc的专栏 2791

futex同步机制分析之三内核实现

一、源码引入 前两篇从应用分析到了库,本篇到内核中看看,futex到底何方神圣?(Linux3.1.1) 先看一下futex.c和futex.h(kennel/futex.c linux/futex.h): /** * struct futex_q - The hashed futex queue entry, one per waiting task * @list: priori...

fpcc的专栏 3966

Futex详解:用户态锁、内核态等待、pthread_mutex实现

Futex是现代锁机制的基石。为什么pthread_mutex比传统信号量快?用户态和内核态如何协作实现锁?无竞争时为什么不需要系统调用?Futex如何避免惊群效应?理解Futex的混合设计、用户态原子操作、内核态等待队列、pthread_mutex的底层实现、条件变量的Futex机制,才能掌握高性能同步原语的本质。从"系统调用开销影响锁性能"问题出发,剖析Futex的核心原理。

比较是偷走幸福的小偷 2569

【C/C++】Linux的futex

futex

YZJincsdn的博客 1510
上一篇: ltp测试套件-pthread_rwlock_rdlock_2-1分析记录
下一篇: ltp测试套件-pthread_rwlock_unlock_3-1分析记录
y33988979
博客等级 码龄17年 70粉丝 34原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值