html tool

2021年1月19日星期二

sysdig ::scallslower::futex

参考: https://blog.csdn.net/Javadino/article/details/2891385

要解决的问题:

Futex按英文翻译过来就是快速用户空间互斥体。其设计思想其实不难理解,在传统的Unix系统中,System V IPC(inter process communication),如 semaphores, msgqueues, sockets还有文件锁机制(flock())等进程间同步机制都是对一个内核对象操作来完成的,这个内核对象对要同步的进程都是可见的,其提供了共享的状态信息和原子操作。当进程间要同步的时候必须要通过系统调用(如semop())在内核中完成。

可是经研究发现,很多同步是无竞争的,[popexizhi:这种研究如何做呢?比较感兴趣,这个是推动改进的真正动力,也是看设计的效果真正有效反馈]  即某个进程进入互斥区,到再从某个互斥区出来这段时间,常常是没有进程也要进这个互斥区或者请求同一同步变量的。但是在这种情况下,这个进程也要陷入内核去看看有没有人和它竞争,退出的时侯还要陷入内核去看看有没有进程等待在同一同步变量上。

这些不必要的系统调用(或者说内核陷入)造成了大量的性能开销。

为了解决这个问题,Futex就应运而生,Futex是一种用户态和内核态混合的同步机制。

首先,同步的进程间通过mmap共享一段内存,futex变量就位于这段共享的内存中且操作是原子的,当进程尝试进入互斥区或者退出互斥区的时候,先去查看共享内存中的futex变量,如果没有竞争发生,则只修改futex,而不用再执行系统调用了。当通过访问futex变量告诉进程有竞争发生,则还是得执行系统调用去完成相应的处理(wait 或者 wake up)。

简单的说,futex就是通过在用户态的检查,如果了解到没有竞争就不用陷入内核了,大大提高了low-contention时候的效率。Linux从2.5.7开始支持Futex。[popexizhi: 自己想的类别,把查询是否有同步竞争的查询,从内核态拿到了用户态,可以直接查看了,这样就把”多数无同步竞争“的实验事实使用上了。]

2. Futex系统调用
Futex是一种用户态和内核态混合机制,所以需要两个部分合作完成,linux上提供了sys_futex系统调用,对进程竞争情况下的同步处理提供支持。

---------------------------------------------------------------------------------


 


参考:https://blog.csdn.net/fpcc/article/details/84483954

3、futex的特点

基于上面的种种不便,“物不平则鸣”,牛人们(Hubertus Franke, Matthew Kirkwood, Ingo Molnar and Rusty Russell,无一不是大神啊)创建了futex。这玩意是贯通内核空间和用户空间的一把利器。看看它的中文意义“快速用户空间互斥体”。意味着,快。 
Futex是怎么突出这个快的呢?在同步的线程间,开辟一段共享内存(mmap), futex的变量保存在这段共享内存中,当线程进入(退出)同步区域时,先查询共享内存的中futex变量,如果竞争没有出现,就只修改futex状态,不再进入内核空间调用。反之,还得进入内核控制wait(wake).这样,通过一小段共享内存在用户空间的检查,就极大的避免了不应该进入内核的陷阱。自然,在低频率竞争锁时,效率被大大提高了。 

要解决的问题:

在早期的Linux系统中,多线程的同步分为两种机制,即内核空间机制和用户空间机制。在用户空间进行同步,首先需要使用原子指令将代码锁住,如果利用atomic的原子机制编写过代码,可能这些就很好理解了。 
这里举一个比喻,就好像一个高速的循环,不断的去查询一个标志(可以理解成一个整数:0表示没被锁上,1表示被锁住),所以这个又被形象的称为自旋锁。这时候,CPU是被独占的,如果长时间的CPU被独占,可想而知结果会是如何。所以使用这种机制是有一些限定要求的: 
临界区代码尽量控制在100行以内。 
不要调用系统函数(read等),调用其它函数也应尽量短小。 
不要有大循环,不要有类似sleep动作。 
大的内存复制时,memcpy等函数不建议使用。 
而在内核空间中,实现同步机制和用户空间中没有本质的区别,同样也是类似的使用原子指令操作,正是基于此,内核实现进程的等待和睡眠等功能。 

没有评论:

发表评论