futex

Futex是fast userspace mutex的缩写,Futex按英文翻译过来就是快速用户空间互斥体。其设计思想其实 不难理解,在传统的Unix系统中,System V IPC(inter process communication),如 semaphores, msgqueues, sockets还有文件锁机制(flock())等进程间同步机制都是对一个内核对象操作来完成的,这个内核对象对要同步的进程都是可见的,其提供了共享 的状态信息和原子操作。当进程间要同步的时候必须要通过系统调用(如semop())在内核中完成。可是经研究发现,很多同步是无竞争的,即某个进程进入 互斥区,到再从某个互斥区出来这段时间,常常是没有进程也要进这个互斥区或者请求同一同步变量的。但是在这种情况下,这个进程也要陷入内核去看看有没有人 和它竞争,退出的时侯还要陷入内核去看看有没有进程等待在同一同步变量上。这些不必要的系统调用(或者说内核陷入)造成了大量的性能开销。为了解决这个问 题,Futex就应运而生,Futex是一种用户态和内核态混合的同步机制。首先,同步的进程间通过mmap共享一段内存,futex变量就位于这段共享 的内存中且操作是原子的,当进程尝试进入互斥区或者退出互斥区的时候,先去查看共享内存中的futex变量,如果没有竞争发生,则只修改futex,而不 用再执行系统调用了。当通过访问futex变量告诉进程有竞争发生,则还是得执行系统调用去完成相应的处理(wait 或者 wake up)。简单的说,futex就是通过在用户态的检查,(motivation)如果了解到没有竞争就不用陷入内核了,大大提高了low-contention时候的效率。 Linux从2.5.7开始支持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上进程。

在Bionc中,提供了两个函数来包装Futex系统调用。
extern int __futex_wait(volatile void *ftx, int val, const struct timespec *timeout);
extern int __futex_wake(volatile void *ftx, int count);
Bionc中还有两个类似的函数,它们的原型如下:
extern int  __futex_wake_ex(volatile void *ftx, int pshared, int val);
extern int  __futex_wait_ex(volatile void *ftx, int pshared, int val,
const struct timespec *timeout);
这两个函数比前面的多了一个参数pshared。pshared的值为true表示wake和wait操作是用于进程间的挂进和唤醒;值为false表示操作用于进程内线程的挂进和唤醒。当pshared的值为false时,执行Futex系统调用的操作码为:
FUTEX_WAIT|FUTEX_PRIVATE_FLAG,
FUTEX_WAKE|FUTEX_PRIVATE_FLAG
这样内核如果检测到操作有FUTEX_PRIVATE_FLAG标记,能以更快的速度执行挂起和唤醒操作。
__futex_wait和__futex_wake函数相当于pshared等于true的情况。

Android中有些模块还会使用下面的Futex函数:
extern int __futex_syscall3(volatile void *ftx, int op, int val);
extern int __futex_syscall4(volatile void *ftx, int op, int val,
const struct timespec *timeout);
__futex_syscall3()相当于__futex_wake(),而__futex_syscall4()相当于__futex_wait()。这两个函数与前面的区别是能指定操作码op做为参数。操作码可以是FUTEX_WAIT,FUTEX_WAKE或者它们和FUTEX_PRIVATE_FLAG的组合。
Android中操作码的定义如下:
#define FUTEX_WAIT         0
#define FUTEX_WAKE         1 
#ifndef FUTEX_PRIVATE_FLAG
#define FUTEX_PRIVATE_FLAG  128
#endif 
#ifndef FUTEX_WAIT_PRIVATE
#define FUTEX_WAIT_PRIVATE  (FUTEX_WAIT|FUTEX_PRIVATE_FLAG)
#endif 
#ifndef FUTEX_WAKE_PRIVATE
#define FUTEX_WAKE_PRIVATE  (FUTEX_WAKE|FUTEX_PRIVATE_FLAG)
#endif
FastMixer中使用syscall(__NR_futex, &mFastCaptureFutex, FUTEX_WAKE_PRIVATE, 1)
<think>嗯,用户问到了“futex_wait”,这个问题看起来和Linux系统编程相关。首先,我需要确认用户的使用场景。可能用户是开发人员,遇到了多线程同步的问题,或者在调试程序时遇到了与futex相关的错误。 用户之前问过关于设备指纹识别的错误,现在转向系统级的futex,这可能意味着他们在开发底层应用或驱动时遇到了线程同步的问题。或者,可能是在进行性能优化时,发现futex的使用影响了程序行为。 接下来,我需要解释清楚futex_wait的基本概念,但用户可能需要更深入的理解,比如它的工作原理、常见使用场景以及可能的问题。用户可能想知道为什么他们的程序会卡在futex_wait,或者如何正确使用futex来避免竞争条件。 还要注意用户的技术水平,可能需要用比较易懂的语言,避免过于晦涩的内核术语。同时,结合之前的回答风格,用户可能希望结构清晰,分步骤说明,并给出实际案例或解决方案。 需要检查是否有常见的错误,比如死锁、优先级反转,或者不正确的futex操作导致的问题。还要考虑用户是否需要调试建议,比如使用strace或gdb来跟踪futex调用。 另外,用户可能没有直接说出他们遇到的错误,但遇到futex_wait相关的问题,比如程序挂起或性能下降,这时候需要提供排查方法,比如检查锁的竞争情况,或者分析系统调用。 最后,确保回答符合之前的格式,分点明确,有原因分析、解决步骤和案例参考,帮助用户逐步解决问题。可能还需要提醒用户注意线程安全和资源管理,避免常见陷阱。</think>以下是关于 `futex_wait` 的系统级解析及常见问题解决方案: --- ### **1. 基础概念** **futex(Fast Userspace Mutex)** 是 Linux 内核提供的一种高效线程同步机制,用于实现用户态锁。 - **核心功能**: - 在无竞争时完全在用户空间操作(无需陷入内核),性能极高。 - 在竞争时通过系统调用(如 `futex_wait` 和 `futex_wake`)挂起或唤醒线程。 **`futex_wait`** 是 futex 的核心系统调用之一,作用如下: - 当线程尝试获取锁失败时,调用 `futex_wait` 主动阻塞,让出 CPU 资源。 - 需配合 `futex_wake` 唤醒等待线程。 --- ### **2. 工作原理** ```c #include <linux/futex.h> // 系统调用原型 long futex_wait(void *uaddr, int val,
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值