futex 手册摘要

#include <linux/futex.h>

#include <sys/time.h>

int futex(int *uaddr, int futex_op, int val,

      const struct timespec *timeout, /* or: uint32_t val2 */

      int *uaddr2, int val3);

DESCRIPTION:

  futex()系统调用提供了一种方法用于等待某个特定条件的发生。一种典型的应用是在共享内存同步中作为阻塞装置。当使用futex时,绝大部分同步操作都在用户态完成,一个用户态程序只有在有可能阻塞一段较长的时间等待条件的发生时才使用futex。其他的futex操作可以用来唤醒等待特定条件发生的任何进程或线程。

  一个futex是一个32位的值,它的地址通过futex()传入,futexs在所有的平台上都是32位的(包括64位系统上),所有的futex操作都是在这个值上。为了在多个进程间共享futex,futex位于由mmap或者shmat创建的一块共享内存上(这种情况下,futex值在不同的进程上可能位于不同的虚拟地址,但这些虚拟地址都指向相同的物理地址)。在多线程程序中,将futex值放到一个所有线程共享的全局变量中就可以了。

  当执行一个futex操作请求阻塞一个线程时,只有在 *uaddr == val 时,内核才会执行阻塞操作,这个操作中的所有步骤(1. 导入*uaddr的值; 2. 比较; 3.阻塞线程)将原子的执行,并且当其他线程在同一个futex值上并行操作时所有的步骤不会乱序。

  futex的一种使用方式是用来实现锁,锁的状态(acquired or not acquired)可以用在共享内存中的原子标志表示。在非竞争的情况下,线程可以通过原子操作访问和修改锁的状态(这些操作全部在用户态操作,内核不会保存任何关于锁的状态)。从另一方面来说,另一个线程可能无法获取锁(因为锁已经被某个线程获取),这个线程将通过如下这种方式执行futex()等待操作:

atomic<int> lock; // lock : 0. 锁未被获取 1.锁被获取
futex(&lock, FUTEX_WAIT, 1, NULL, NULL, NULL);

  futex(FUTEX_WAIT)将会检测lock的值,只有在等于1时才阻塞线程。当线程释放锁时,该线程必须首先重置锁的状态,然后执行futex操作唤醒阻塞在lock上的线程。

  注意使用futex并没有显示的初始化和销毁操作,内核只有在一个指定的futex值上执行futex操作时(例如FUTEX_WAIT)才会维护futex数据。

Arguments(参数):

  uaddr指向futex值,在所有的平台上,futex值是一个4字节的整数并且必须4字节对齐。

  对于某些阻塞操作,timeout参数是一个指向timespec结构的指针,表明了操作的超时时间。然而,在其他的某些操作下,它的最低4字节被作为一个整数值,这个整数值的含义因futex操作的不同而不同,对于这些操作来说,内核会将timeout值转换为unsigned long,然后转换为uint32_t,在接下来的说明中,它将表示为val2。

  在需要的时候,uaddr2是指向第二个futex值的指针,val3的解释将依赖于具体的操作。

Futex operations (操作) :

  futex_op参数包含两个部分:1.操作类型 2.标志选项(影响操作行为)。

  FUTEX_PRIVATE_FLAG (since Linux 2.6.22)

    这个标志选项可以用在所有的futex操作中,它告诉内核这个futex是进程内的,不和其他进程共享(它只能用来同步同一个进程内的线程),这样内核可以做一些额外的优化。

  FUTEX_CLOCK_REALTIME (since Linux 2.6.28)

    这个标志选项只能用在FUTEX_WAIT_BITSET FUTEX_WAIT_REQUEUE_PI 操作中,如果设置了这个标志选项,内核会将timeout视作基于CLOCK_REALTIME 的绝对时间。如果没有设置这个标志,则内核将它视作基于CLOCK_MONOTONIC的相对时间。

  futex操作包含下面的几种:

  FUTEX_WAIT (since Linux 2.6.0)

  本操作会检查*uaddr是否等于val,如果相等的话,则睡眠等待在uaddr上的FUTEX_WAKE 操作,如果线程开始睡眠,则它被认为是这个futex值上一个等待者。如果两者不相等,则操作失败并返回 error EAGAIN。比较*uaddr和val的目的是为了避免丢失唤醒。

  如果timeout参数不为NULL,则它指定了等待的超时时间(根据CLOCK_MONOTONIC测量得出)。

  FUTEX_WAKE (since Linux 2.6.0)

  本操作会唤醒最多val个等待者,绝大部分情况下,val的值为1(只唤醒一个等待者)或INT_MAX(唤醒所有的等待者) 。注意没有任何机制保证一定唤醒某些特定的等待者(比如被认为是高优先级的等待者)

  参数timeout, uaddr2, val3将被忽略。

  FUTEX_REQUEUE (since Linux 2.6.0)

  本操作和下面的 FUTEX_CMP_REQUEUE 完成相同的功能,除了不检查val3 。(参数val3被忽略)

  FUTEX_CMP_REQUEUE (since Linux 2.6.7)

  本操作首先检查*uaddr是否等于val3,如果不相等,则返回error EAGAIN。否则的话,将唤醒最多val个等待者,如果等待者的数量大于val,则剩下的等待者则从uaddr的等待队列中移除,添加到uaddr2的等待队列中。val2参数指定了移动到uaddr2的等待者的最大数量。

  val的典型值为0或1,指定为INT_MAX是没有任何用处的,这将会使得FUTEX_CMP_REQUEUE 操作和 FUTEX_WAKE 操作相同。同样,val2的值通常为1或INT_MAX,指定为0是没有用的,这样将使得 FUTEX_CMP_REQUEUE  操作和  FUTEX_WAIT 操作相同。

  FUTEX_CMP_REQUEUE 是用来代替 FUTEX_REQUEUE 的,两者的不同点在于是否检查uaddr的值,这个检查操作可用来确保移除添加操作只在特定的条件下发生,这样就避免了某些 race condition。

  FUTEX_CMP_REQUEUE 和 FUTEX_REQUEUE 都可以用来避免 FUTEX_WAKE 可能产生的“线程惊群”现象。考虑下面的情况,多个线程在等待B(使用futex实现的等待队列):

lock(A)
while (!check_value(V)) {
      unlock(A);
      block_on(B);
      lock(A);
};
unlock(A);

  如果一个线程使用 FUTEX_WAKE 唤醒 B上的所有线程,则它们会全部尝试获取锁 A,然而在这种情况下唤醒所有的线程时徒劳的,因为除了一个线程之外其他的线程又全部阻塞在 A 上,相比之下,REQUEUE 操作可以唤醒一个等待线程然后将剩下的等待线程移动到 A 下,当线程解锁 A时其他的线程可以继续执行。

时间: 2024-10-25 05:39:36

futex 手册摘要的相关文章

Lua2.4 参考手册(一)

说明:这个文档是 Lua2.4 的 doc 目录里的 refman.ps 文件.原文版权归原作者所有,这篇翻译只是作为学习之用.如果翻译有不当之处,请参考原文.-------------------以下是正文-------------------编程语言 Lua2.4 的参考手册 摘要:Lua 是一个扩展程序语言,被设计用做其它程序的配置语言.本文档描述 Lua 编程语言 2.4 版,以及 Lua 程序和宿主 C 程序交互的 API.它还提供了一些使用这些主要特点的例子. -----------

如何写IT项目解决方案

如何写IT项目解决方案 解决方案就是把客户的利益和产品特性之间建立一个逻辑性的桥梁 原文链接:http://hi.baidu.com/wy521ly/blog/item/0523092ae2e5a290033bf688.html 2010-02-03 10:46 在公司作为一名售前工程师会有大量的方案策划落到头上,这些方案里小的有几十万,大的有上千万.如何写好方案一直是我们很关注的事情. 而我们基本上都是在方案提交前一两天接到写方案的任务,也不能不做,只好心里大骂一句,骂完后就打电话搞清楚别人的

摘要JSR168 PORLET标准手册汉化整理

本规范汉化资源搜集整理于网上并由我作了些修改和添加,主要为适应大陆的语辞.用语及其他未译之处. 由于本人于水平有限,如有错误,请各位高手指正:若有高见,希望不吝言辞,同为中国开源作项献. 特此严重感谢翻译此规范的原译者: 第一.第二章节     台湾省   Jini 第三章节           上海市   风之舞 第四章~最后章节    台湾省   koji lin JSR168 PORLET标准手册汉化整理 本规范汉化资源搜集整理于网上并由我作了些修改和添加,主要为适应大陆的语辞.用语及其他

《开源世界旅行手册》摘要

气候 地理 基础知识 命令语法结构 参考中文语法结构: 我们1郑重地2推荐3您Linux4! # 1.主语:2.状语:3.谓语:4.宾语(可能会用直接宾语/间接宾语) 翻译成 Linux 的命令,应该是这个样子的: 推荐 --郑重的 您 Linux # 做什么(谓语) --使用选项来精细调节程序的行为(状语) 直接宾语 间接宾语 进程. 为运行中的程序,是程序在内存中的镜像. 路径:相对路径.绝对路径.远程路径. 软件: 按照传统,一个软件通常分别拷贝到同级目录下的 bin.etc.lib.sh

System Center 2016 Data Protection Manager 部署手册

1. 环境描述 活动目录服务器 计算机名:SH-DC-01 Active Directory:365vCloud.net IP地址:192.168.100.2/24 操作系统:Windows Server 2016 中文标准版 已安装角色:ADDS活动目录服务 SCDPM服务器 计算机名:SH-SCDPM-01 Active Directory:365vCloud.net IP地址:192.168.100.7/24 操作系统:Windows Server 2016 中文标准版 已安装角色:无 2

System Center Configuration Manager,Version1606 部署手册

1. 环境描述 活动目录服务器 计算机名:SH-DC-01 所在域名或工作组名称:365vCloud.net IP地址:192.168.100.2/24 操作系统:Windows Server 2016 中文标准版 已安装角色:ADDS活动目录服务 SCCM中心站点服务器(CAS) 计算机名:SH-SCCM-01 所在域名或工作组名称:365vCloud.net IP地址:192.168.100.4/24 操作系统:Windows Server 2016 中文标准版 已安装角色:无 SCCM主站

linux命令手册

linux命令非为内置命令和外部命令 内置命令是shell程序的一部分 外部命令是系统的软件功能,执行过程由shell程序控制 区别内置命令和外部命令:type 内置命令显示为 is a shell builtin: 外部命令显示为路径 获得命令的使用帮助: 内部命令:help COMMAND 外部命令:COMMAND --help 命令手册:manual man COMMAND 查看命令使用手册 man(数字):表示显示第几章节的内容:不跟数字:显示第一次出现的章节 显示出现乱码时,说明字符集

.NET轻量级ORM组件Dapper修炼手册

一.摘要 1.1.为什么叫本次的分享课叫<修炼手册>? 阿笨希望本次的分享课中涉及覆盖的一些小技巧.小技能给您带来一些帮助.希望您在日后工作中把它作为一本实际技能手册进行储备,以备不时之需,一旦当手头遇到与Dapper修炼手册中相似用法的地方和场景,可以直接拿来进行翻阅并灵活的运用到项目中.最后阿笨建议您可以根据自己在工作中碰到的不同的使用场景,不断的完善此本修炼手册. 废话不多说,直接上干货,我们不生产干货,我们只是干货的搬运工. 四.涉及覆盖的知识点 1.C# Linq To Xml技术.

【转载】python实例手册

今天西爬虫的时候遇到了问题,在网上不停地查找资料,居然碰到两篇好文章: 1.python实例手册   作者:没头脑的土豆 另一篇在这:shell实例手册 python实例手册 #encoding:utf8 # 设定编码-支持中文 0说明 手册制作: 雪松 更新日期: 2013-12-19 欢迎系统运维加入Q群: 198173206 # 加群请回答问题 请使用"notepad++"打开此文档,"alt+0"将函数折叠后方便查阅 请勿删除信息,转载请说明出处,抵制不道德