linux 内核的futex
futex是linux内核为用户空间实现锁等同步机制而设计的同步排队(队列queueing)服务。在futex.c的注释中,futex起源于"Fast Userspace Mutex",但它并非只是一个Mutex,而是用户空间线程(pthread)同步机制的底层服务。它的基本设计有三点,1.同步对象可以在进程之使用,并且保证同步对象的内部状态访问有序,2.当同步对象没有竞争的情况下,可以在用户空间快速完成(fastpath),3.当同步对象发生竞争时,必须进入内核使用futex系统提供的排队机制进行仲裁(slowpath),仲裁胜出的任务(进程或线程)必须返回到用户空间完成同步对象的其它状态的修改 。
futex在用户空间只是一个地址对齐的整形,它是用户空间的同步委托给内核的futex系统,futex访问的同步对象内部状态。
内核中的futex系统设计了三个基本结构。futex_key,futex_queue, 以及futex_hash_bucket。
futex_key:是一个使用用户空间中futex的地址,以及地址的映射对象作为键的标识,它是futex可以在进程间共享使用的保证。
futex_hash_bucket:是一个等待队列,内核内建一般为cpu个数的8倍的等待队列。futex根据它的futex_key进行hash后的值,共享对于编号的等待队列。
futex_queue:代表一个任务(进程或线程)在某个futex上的等待关系,是等待队列的链表入口,链入到futex_hash_bucket队列中。
注意的是,每个futex_hash_bucket都有一个spinlock进行同步访问,它实现的队列是prio list,基于priority(优先级)的有序队列。
futex系统提供了基本的同步接口futex_wait(uaddr, flags, val, timeout, bitset)和futex_wake(uaddr, flags, nr_wake, bitset)。
futex_wait:就是排队然后阻塞(睡眠调度)。查找对应队列,队列入队操作,睡眠调度。
futex_wake:就是唤醒阻塞队列的任务(进程或线程)。查找对应队列,队列出队操作,唤醒任务。
调用futex系统调用时,必须传入futex的地址uaddr,以及地址的内存属性flags,同时才能标识出这个futex。futex系统根据futex的地址属性决定生成的key是否需要第二个因素,映射的对象(mm或inode)。当使用文件映射页面,进行进程间共享时,key不能使用虚拟地址进行标识,而要使用映射的物理页面号进行标识。所以在这里大致可以看到,锁的开销随跨越的边界越大而增加。访问页面管理必须进行同步,访问文件系统也必须进行同步。
所以通过uaddr和flags进行futex系统调用,就可以在主机内得到唯一的标识,让futex_wake可以找回进行futex_wait的futex。
futex设计为Fast Userspace Mutex,就是可以让用户空间的实现的Lock和Unlock操作拥有fastpath快速路径,只在没有锁竞争的时候。
如何使用futex实现在用户空间快速的锁,以pthread的lowlevellock为例。
pthread的lowlevellock将futex的锁状态定义为3种:
0,无锁,可以进行快速上锁,不需要使用futex系统调用。
1,上锁,但没有锁竞争。如果这时有其它任务需要上锁,就必须标记futex为状态锁竞争,然后使用futex系统服务。
2,锁竞争,有其它任务将要或正在内核的futex系统中排队等待着锁的使用。
在无锁状态进行Lock,以及非锁竞争的持锁状态进行Unlock都不必须进行futex系统调用。
上锁和解锁,对锁状态的修改在用户空间中完成,锁竞争通过futex系统调用完成。futex系统调用并不进行上锁和解锁操作,只负责排队服务,也就是说futex系统调用并不理会也不必要知道用户空间是如何定义futex的锁状态的。
futex系统的排队服务,通过hash链表,每一个等待都会分配到由futex_key计算出的hash链表上进行排队。hash链表是共享的链表,多个futex的等待可能会共享同一个hash链表,而一个futex的等待只会分配到相同的hash链表上。因为futex_key是唯一的。每一个hash链表都是一个prio有序链表,等待在排队时需要根据阻塞的任务的优先级进行排序插入。
上面是futex提供的最基本的功能,pthread_mutex使用futex_wait和futex_wake实现它的lock和unlock操作。
futex.c文件的注释告诉我们,futex从纳入到linux内核开始就不断增加它的功能,使它更加通用,更好地支持用户空间编程的同步服务。
futex requeueing 随futex纳入到linux内核添加。
robust futex,更加健壮的futex,持有基于futex的锁的任务退出而没有释放,使阻塞于这个锁的其它任务得以解放。
pi-futex,使用rt_mutex代理排队服务,同时使用rt_mutex的PI优先级继承算法,增加futex的功能。
private futexes,优化进程内的futex,因为futex最初被设计,局限于当时的内核,是基于多进程考虑的。
Requeue-PI,一种对non-pi-futex到pi-futex之间的requeue进行优化。
requeue这一功能广泛使用在pthread_cond,换过来说就是为实现pthread_cond而设计的。
linux 内核的futex的更多相关文章
- linux 内核的futex pi-support,即pi-futex使用rt_mutex委托
futex的pi-support,也就是为futex添加pi算法解决优先级逆转的能力,使用pi-support的futex又称为pi-futex.在linux内核的同步机制中,有一个pi算法的成例,就 ...
- linux 内核的futex - requeue 以及 requeue-pi
futex为更好支持pthread_cond的实现(,最主要是broadcast),设计了requeue功能,并以futex系统调用提供操作接口,包括一对配对的操作 futex_wait_requeu ...
- linux内核级同步机制--futex
在面试中关于多线程同步,你必须要思考的问题 一文中,我们知道glibc的pthread_cond_timedwait底层是用linux futex机制实现的. 理想的同步机制应该是没有锁冲突时在用户态 ...
- 用Qemu模拟vexpress-a9 (三)--- 实现用u-boot引导Linux内核
环境介绍 Win7 64 + Vmware 11 + ubuntu14.04 32 u-boot 版本:u-boot-2015-04 Linux kernel版本:linux-3.16.y busyb ...
- linux内核数据结构学习总结
目录 . 进程相关数据结构 ) struct task_struct ) struct cred ) struct pid_link ) struct pid ) struct signal_stru ...
- 戴文的Linux内核专题:07内核配置(3)
转自Linux中国 OK,我们还继续配置内核.还有更多功能等待着去配置. 下一个问题(Enable ELF core dumps (ELF_CORE))询问的是内核是否可以生成内核转储文件.这会使内核 ...
- linux内核编程笔记【原创】
以下为本人学习笔记,如有转载请注明出处,谢谢 DEFINE_MUTEX(buzzer_mutex); mutex_lock(&buzzer_mutex); mutex_unlock(& ...
- Linux 内核综述
一.什么是Linux内核: 内核->操作系统中最重要的部分,内核将在系统引导时被装载进RAM,其中包含了很多关键的例程,以操作系统.内核是OS最为关键的部分,人们常将OS(操作系统)与内核等同. ...
- 基于tiny4412的Linux内核移植(支持device tree)(三)
作者信息 作者: 彭东林 邮箱:pengdonglin137@163.com QQ:405728433 平台简介 开发板:tiny4412ADK + S700 + 4GB Flash 要移植的内核版本 ...
随机推荐
- 为APP加入一个欢迎页面
###添加软件闪图使用的方法: new Handler().postDelayed(new Runnable() { @Override public vo ...
- Alamofire源码解读系列(七)之网络监控(NetworkReachabilityManager)
Alamofire源码解读系列(七)之网络监控(NetworkReachabilityManager) 本篇主要讲解iOS开发中的网络监控 前言 在开发中,有时候我们需要获取这些信息: 手机是否联网 ...
- (3)简单说说java中的异常体系
java异常体系 |--Throwable 实现类描述java的错误和异常 一般交由硬件处理 |--Error(错误)一般不通过代码去处理,一般由硬件保护 |--Exception(异常) |--Ru ...
- C++ Primer 5 CH4 表达式
4.1 基础 函数调用也是一种特殊的运算符,它对运算对象的数量没有限制. C++ 的表达式要么是左值,要么是右值.左值可以位于赋值语句的左边,右值则不可以. 当一个对象被用作右值的时候,用的是对象的值 ...
- 面试 -- ListView对其指定的子Item进行单独的刷新
1,最近在面试题目的时候突然看到了问题"ListView对其指定的子Item进行单独的刷新",当时感觉一脸懵逼,还是第一次听到这个问题,也就是不能使用adapter.notifyD ...
- java学习(一)静态代码块 构造代码块 构造方法的执行顺序及注意问题
今天我总结了一下java中静态代码块 构造代码块 构造方法的执行顺序及其注意问题 首先要知道静态代码块是随着类的加载而加载,而构造代码块和构造方法都是随着对象的创建而加载 当时做了这么一个小案例(想必 ...
- linux之date命令详解
date命令的用处 1.用于显示特殊的时间格式,可以用于对日志文件的命名 2.用于设置时间 ,不过这方面用的比较少,因为一般的服务器都设置的有自动同步网络时间 用法: date [OPTION]... ...
- iPhone与iWatch连接、控制、数据传递(Swift)
最近在做一个项目,涉及到iPhone设备和手表传输数据.控制彼此界面跳转,在网上找了很多资料,发现国内的网站这方面介绍的不多,而国外的网站写的也不是很全,所以在这写这篇博客,给大家参考一下,望大神指点 ...
- cephfs创建及挂载
Ceph 文件系统( Ceph FS )是个 POSIX 兼容的文件系统,它使用 Ceph 存储集群来存储数据.Ceph 文件系统要求 Ceph 存储集群内至少有一个 Ceph 元数据服务器. 1.添 ...
- 深度学习实践系列(3)- 使用Keras搭建notMNIST的神经网络
前期回顾: 深度学习实践系列(1)- 从零搭建notMNIST逻辑回归模型 深度学习实践系列(2)- 搭建notMNIST的深度神经网络 在第二篇系列中,我们使用了TensorFlow搭建了第一个深度 ...