介绍

futex(快速用户空间互斥)是Linux的一个基础组件,可以用来构建各种更高级别的同步机制,比如锁或者信号量等等,POSIX信号量就是基于futex构建的。大多数时候编写应用程序并不需要直接使用futex的,一般用基于它所实现的系统库就够了。

历史

传统的SystemV IPC(进程间通信)进程间同步机制都是通过内核对象来实现的,以semaphore为例,当进程间要同步的时候,必须通过系统调用semop(2)进入内核进行PV操作。系统调用的缺点是开销很大,需要从用户模式切换到内核模式,保存寄存器状态,从用户堆栈切换到内核堆栈,等等,通常要消耗上百条指令。事实上,有一部分系统调用是可以避免的,因为现实中很多同步操作进行的时候根本不存在竞争,即某个进程从持有旗语直至释放信号的这段时间内,常常没有其它进程对同一信号有需求,在这种情况下,内核的参与本来是不必要的,可是在传统机制下,持有旗语必须先调用执行semop(2)进入内核去看看有没有人和它竞争,释放信号量也必须调用执行semop(2)进入内核去看看有没有人在等待同一信号,这些不必要的系统调用造成了大量的性能损耗

futex的设计思想

futex的解决思路是:在无竞争的情况下操作完全在用户空间进行,不需要系统调用,仅在发生竞争的时候进入内核去完成相应的处理(等待或者唤醒)。所以说,futex是一种用户模式和内核模式混合的同步机制,需要两种模式合作才能完成,用户空间,而不是内核对象,futex的代码也分为用户模式和内核模式两部分,无竞争的情况下在用户模式下,发生竞争时则通过sys_futex系统调用进入内核模式进行处理

实现

// 在uaddr指向的这个锁变量上挂起等待(仅当*uaddr==val时)
int futex_wait(int *uaddr, int val);
// 唤醒n个在uaddr指向的锁变量上挂起等待的进程
int futex_wake(int *uaddr, int n);
/*
* This sample show how to use futex betwen two process, and use system v
* shared memory to store data
*/ #include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/syscall.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h> #if __GLIBC_PREREQ(2, 3)
#if defined FUTEX_WAIT || defined FUTEX_WAKE
#include <linux/futex.h>
#else
#define FUTEX_WAIT 0
#define FUTEX_WAKE 1
#endif #ifndef __NR_futex
#define __NR_futex 202
#endif
#endif #define FILE_MODE (S_IRUSR | S_IWUSR) const char shmfile[] = "/tmp";
const int size = 100; struct namelist
{
int id;
char name[20];
}; int
main(void)
{
int fd, pid, status;
int *ptr;
struct stat stat; // create a Posix shared memory
int flags = O_RDWR | O_CREAT;
fd = shm_open(shmfile, flags, FILE_MODE);
if (fd < 0)
{
printf("shm_open failed, errormsg=%s errno=%d", strerror(errno), errno);
return 0;
}
ftruncate(fd, size);
ptr = (int *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); pid = fork();
if (pid == 0) { // child process
sleep(5);
printf("Child %d: start/n", getpid()); fd = shm_open(shmfile, flags, FILE_MODE);
fstat(fd, &stat);
ptr = (int *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
close(fd);
struct namelist tmp; // store total num in ptr[0];
*ptr = 3; namelist *cur = (namelist *)(ptr+1); // store items
tmp.id = 1;
strcpy(tmp.name, "Nellson");
*cur++ = tmp;
tmp.id = 2;
strcpy(tmp.name, "Daisy");
*cur++ = tmp;
tmp.id = 3;
strcpy(tmp.name, "Robbie");
*cur++ = tmp; printf("wake up parent/n");
syscall(__NR_futex ,ptr, FUTEX_WAKE, 1, NULL ); exit(0);
} else{ // parent process
printf("parent start waiting/n");
syscall(__NR_futex , ptr, FUTEX_WAIT, *(int *)ptr, NULL );
printf("parent end waiting/n"); struct namelist tmp; int total = *ptr;
printf("/nThere is %d item in the shm/n", total); ptr++;
namelist *cur = (namelist *)ptr; for (int i = 0; i< total; i++) {
tmp = *cur;
printf("%d: %s/n", tmp.id, tmp.name);
cur++;
} printf("/n");
waitpid(pid, &status, 0);
} // remvoe a Posix shared memory from system
printf("Parent %d get child status:%d/n", getpid(), status);
return 0;
}

上层应用

互斥锁pthread_mutex_t的实现原理

// pthread_mutex_lock:
atomic_dec(pthread_mutex_t.value);
if (pthread_mutex_t.value!=0)
futex(WAIT)
else
success // pthread_mutex_unlock:
atomic_inc(pthread_mutex_t.value);
if(pthread_mutex_t.value!=1)
futex(WAKEUP)
else
success

信号量sem_t的实现原理

sem_wait(sem_t *sem)
{
for (;;) {
if (atomic_decrement_if_positive(sem->count))
break;
futex_wait(&sem->count, 0)
}
} sem_post(sem_t *sem)
{
n = atomic_increment(sem->count);
// Pass the new value of sem->count
futex_wake(&sem->count, n + 1);
}

论文
参考一
参考二

作者:滩主
链接:https://www.jianshu.com/p/d17a6152740c
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

futex的设计与实现的更多相关文章

  1. [转载] Linux Futex的设计与实现

    Linux Futex的设计与实现 引子 在编译2.6内核的时候,你会在编译选项中看到[*] Enable futex support这一项,上网查,有的资料会告诉你"不选这个内核不一定能正 ...

  2. Linux Futex的设计与实现(转)

    引子在编译2.6内核的时候,你会在编译选项中看到[*] Enable futex support这一项,上网查,有的资料会告诉你"不选这个内核不一定能正确的运行使用glibc的程序" ...

  3. 【转】Linux Futex的设计与实现

    引子在编译2.6内核的时候,你会在编译选项中看到[*] Enable futex support这一项,上网查,有的资料会告诉你"不选这个内核不一定能正确的运行使用glibc的程序" ...

  4. 【转】cve2014-3153 漏洞之详细分析与利用

    背景学习: Linux Futex的设计与实现 使用者角度看bionic pthread_mutex和linux futex实现 By kernux TopSec α-lab 一 漏洞概述 这个漏洞是 ...

  5. linux 内核的futex

    futex是linux内核为用户空间实现锁等同步机制而设计的同步排队(队列queueing)服务.在futex.c的注释中,futex起源于"Fast Userspace Mutex&quo ...

  6. linux 内核的futex - requeue 以及 requeue-pi

    futex为更好支持pthread_cond的实现(,最主要是broadcast),设计了requeue功能,并以futex系统调用提供操作接口,包括一对配对的操作 futex_wait_requeu ...

  7. linux 内核的各种futex

    futex 设计成用户空间快速锁操作,由用户空间实现fastpath,以及内核提供锁竞争排队仲裁服务,由用户空间使用futex系统调用来实现slowpath.futex系统调用提供了三种配对的调用接口 ...

  8. linux 内核的futex pi-support,即pi-futex使用rt_mutex委托

    futex的pi-support,也就是为futex添加pi算法解决优先级逆转的能力,使用pi-support的futex又称为pi-futex.在linux内核的同步机制中,有一个pi算法的成例,就 ...

  9. 转载:futex同步机制详解

    在编译2.6内核的时候,你会在编译选项中看到[*] Enable futex support这一项,上网查,有的资料会告诉你"不选这个内核不一定能正确的运行使用glibc的程序", ...

随机推荐

  1. docker部署Redmine项目管理平台

    1.下载镜像(自己用的3.4版本) docker pull redmine:3.4 docker pull mysql:5.7 2.运行 docker run -p 3306:3306 --name ...

  2. 迷你商城后台管理系统————stage1需求分析

    PS:迷你商城后台管理系统---需求分析.docx下载~click me 迷你商城后台管理系统-- 需求分析 1. 引言 作为互联网热潮的崛起,消费者们的普遍差异化,实体商城要想在互联网的浪潮中继续发 ...

  3. 搭建cas 服务器

    https://blog.csdn.net/oumuv/article/details/84306361 记得添加数据库驱动 https://blog.csdn.net/zhouzhiwengang/ ...

  4. Kotlin扩展作用域分析与扩展的根本作用解析

    在上一次https://www.cnblogs.com/webor2006/p/11219358.html学习了Kotlin的扩展,继续这个话题继续拓展,首先提出这么一个问题:假如我们扩展的方法跟类中 ...

  5. P1801 黑匣子[堆]

    题目描述 Black Box是一种原始的数据库.它可以储存一个整数数组,还有一个特别的变量i.最开始的时候Black Box是空的.而i等于0.这个Black Box要处理一串命令. 命令只有两种: ...

  6. Gradient Boosting Decision Tree

    GBDT中的树是回归树(不是分类树),GBDT用来做回归预测,调整后也可以用于分类.当采用平方误差损失函数时,每一棵回归树学习的是之前所有树的结论和残差,拟合得到一个当前的残差回归树,残差的意义如公式 ...

  7. 《The One!团队》第八次作业:ALPHA冲刺(一)

    项目 内容 作业所属课程 所属课程 作业要求 作业要求 团队名称 < The One !> 作业学习目标 (1)掌握软件测试基础技术.(2)学习迭代式增量软件开发过程(Scrum) 第一天 ...

  8. 关于devexpress报表XtraReport,动态修改报表样式(.repx格式),动态添加数据并使用的理解

    一.基本概念: XtraReports 中的每个报表都由 XtraRepot 类的一个实例表示,或者由该类的子类来表示(这种情况更常见). 因此,每个报表都作为带区的容器使用,而每个带区中都包含报表控 ...

  9. Oracle row_number() over() 分析函数--取出最新数据

    语法格式:row_number() over(partition by 分组列 order by 排序列 desc) 一个很简单的例子 1,先做好准备 create table test1( id v ...

  10. PostgreSQL物理坏块和文件损坏案例分享

    作者简介 王睿操,平安好医数据库架构岗,多年postgresql数据库运维开发工作.曾就职于中国民航信息,迪卡侬.对其他数据库产品也有一定的涉猎. 背景 笔者最近发现很多朋友经常遇到PostgreSQ ...