内核态:运行内核程序代码,比如 open 系统调用
早期内核同步互斥操作必须要进入内核态,由内核来提供同步机制。但很多同步是无竞争的,即某个进程进入互斥区,到再从某个互斥区出来这段时间,常常是没有进程也要进这个互斥区或者请求同一同步变量的。于是大部分时间浪费在 user→kernel 和 kernel→usr 的切换。futex就是为了减少这种浪费而产生的。
首先,同步的进程间通过 mmap 共享一段内存,futex 变量就位于这段共享的内存中且操作是原子的,当进程尝试进入互斥区或者退出互斥区的时候,先去查看共享内存中的 futex 变量,如果没有竞争发生,则只修改futex,不再进行系统调用。当通过访问 futex 变量告知进程有竞争发生,则需要进行系统调用去完成相应的处理(wait、wake up...etc)。简单的说,futex 就是通过在用户态的检查判断是否需要进一步陷入内核。
/**
* futex - 快速用户空间锁定
* @uaddr 指向计数器的对齐整数,要执行的操作通过op参数和值val传递
* @op 为 FUTEX_WAIT 表示等待锁
* 为 FUTEX_WAKE 表示释放锁
* @val 为期望的计数器值
* @timeout 表示等待多久超时
* @uaddr2 ...
* @val3 ...
*/
int futex(int *uaddr, int op, int val, const struct timespec *timeout, int *uaddr2, int val3);