- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
引子
在编译 2.6 内核的时候,你会在编译选项中看到[*] Enable futex support 这一项,上网查,有
的资料会告诉你不选这个内核不一定能正确的运行使用 glibc 的程序,那 futex 是什么?和
glibc 又有什么关系呢?
1. 什么是 Futex
Futex 是 Fast Userspace muTexes 的缩写,由 Hubertus Franke, Matthew Kirkwood, Ingo Molnar
and Rusty Russell 共同设计完成。几位都是 linux 领域的专家,其中可能 Ingo Molnar 大家更
熟悉一些,毕竟是 O(1)调度器和 CFS 的实现者。
Futex 按英文翻译过来就是快速用户空间互斥体。其设计思想其实 不难理解,在传统的 Unix
系统中,System V IPC(inter process communication),如 semaphores, msgqueues, sockets 还有
文件锁机制(flock())等进程间同步机制都是对一个内核对象操作来完成的,这个内核对象对
要同步的进程都是可见的,其提供了共享 的状态信息和原子操作。当进程间要同步的时候
必须要通过系统调用(如 semop())在内核中完成。可是经研究发现,很多同步是无竞争的,
即某个进程进入 互斥区,到再从某个互斥区出来这段时间,常常是没有进程也要进这个互
斥区或者请求同一同步变量的。但是在这种情况下,这个进程也要陷入内核去看看有没有人
和它竞争,退出的时侯还要陷入内核去看看有没有进程等待在同一同步变量上。这些不必要
的系统调用(或者说内核陷入)造成了大量的性能开销。为了解决这个问 题,Futex 就应运而
生,Futex 是一种用户态和内核态混合的同步机制。首先,同步的进程间通过 mmap 共享一
段内存,futex 变量就位于这段共享 的内存中且操作是原子的,当进程尝试进入互斥区或者
退出互斥区的时候,先去查看共享内存中的 futex 变量,如果没有竞争发生,则只修改 futex,
而不 用再执行系统调用了。当通过访问 futex 变量告诉进程有竞争发生,则还是得执行系
统调用去完成相应的处理(wait 或者 wake up)。简单的说,futex 就是通过在用户态的检查,
如果了解到没有竞争就不用陷入内核了,大大提高了 low-contention 时候的效率。 Linux 从
2.5.7 开始支持 Futex。
2. Futex 系统调用
Futex 是一种用户态和内核态混合机制,所以需要两个部分合作完成,linux 上提供了 sys_futex
系统调用,对进程竞争情况下的同步处理提供支持。
其原型和系统调用号为
#include linux/futex.h
#include sys/time.h
int futex (int *uaddr, int op, int val, const struct timespec *timeout,int *uaddr2, int val3);
#define __NR_futex 240
虽然参数有点长,其实常用的就是前面三个,后面的 timeout 大家都能理解,其他的也常
被 ignore。
uaddr 就是用户态下共享内存的地址,里面存放的是一个对齐的整型计数器。
op 存放着操作类型。定义的有 5 中,这里我简单的介绍一下两种,剩下的感兴趣的自己
去 man futex
FUTEX_WAIT: 原子性的检查 uaddr 中计数器的值是否为 val,如果是则让进程休眠,直到
FUTEX_WAKE 或者超时(time-out)。也就是把进程挂到 uaddr 相对应的等待队列上去。
FUTEX_WAKE: 最多唤醒 val 个等待在 uaddr 上进程。
可见 FUTEX_WAIT 和 FUTEX_WAKE 只是用来挂起或者唤醒进程,当然这部分工作也只能在
内核态下完成。有些人尝试着直接使用 futex 系统调 用来实现进程同步,并寄希望获得 futex
的性能优势,这是有问题的。应该区分 futex 同步机制和 futex 系统调用。futex 同步机制还
包括用户态 下的操作,我们将在下节提到。
3. Futex 同步机制
所有的 futex 同步操作都应该从用户空间开始,首先创建一个 futex 同步变量,也就是位于
共享内存的一个整型计数器。
当 进程尝试持有锁或者要进入互斥区的时候,对 fute
原创力文档


文档评论(0)