操作系统学习:Linux内核并发机制

Linux包含了在其他UNIX系统中出现的所有并发机制,其中包括管道、消息队列、共享内存和信号,除此之外,Linux2.6还包含了一套丰富的并发机制,这套机制是特别为内核态线程准备的。换言之,它们是内核中的并发机制,提供内核代码执行的并发性。

原子操作

Linux提供了一组操作对变量的原子操作。这些操作能够用来避免简单的竟态条件(race condition)。原子操作执行时不会被打断或被干涉。在单处理器上,线程一旦启动原子操作,则从原子操作开始到结束的这段时间内,县城内不会被中断。此外,在多处理器系统中,该原子操作所针对的变量是被锁住的,以免被其他的进程所访问,知道原子操作执行完毕。
在Linux中定义两种原子操作,一种是针对整形变量的整数操作,一种是针对位图中某一位的位图操作,这些操作在linux支持的任何计算机体系结构中都需要实现。在某些体系结构中,这些原子操作有相应的汇编指令。其他体系结构通过锁住内存总线的方式来保证操作的原子性。
对于原子整数操作(atomic integer operation),定义了一个特殊的数据类型atomic_t,原子整数操作仅能用在这个数据类型上,其他操作不允许用在这个数据类型上,好处是:
- 对于在某些情况下不受竟态条件的变量,不能使用原子操作。
- 这种数据类型的变量能够避免被不恰当的非原子操作使用。
- 编译器不能错误地优化对该值的访问。
- 这种数据类型的实现隐藏了与计算机体系结构相关的差异。

自旋锁

在Linux中保护临界区最常见的技术就是自旋锁(spinlock) ,在同一时刻,只有一个线程能获得自旋锁。其他任何企图获取自旋锁的线程将一直进行尝试(即自旋),直到获得该锁。本质上,自旋锁建立在内存区中一个整数上,任何线程进入临界区之前都必须检查该整数。如果该值为0,则线程设置该值为1,然后进入临界区。如果该值为非0,则该线程继续检查该值,直到它为0。自旋锁很容易实现,担忧一个缺点,即在锁外面的线程以忙等待的方式继续执行。因此,自旋锁在获得所需要的等待时间较短时,即等待时间少于两次上下文切换时间时,就会很高效。
自旋锁在单处理器和多处理器系统中的实现是不同的。对于单处理系统,必须考虑如下因素:是否关闭内核抢占(kernel preemption)功能。如果关闭了内核抢占功能,此时线程在内核模式下运行不会被打断,那么锁就会因为没有必要使用而在编译时被删除。如果启用内核抢占,即允许打断内核模式线程,那么自旋锁仍然会编译删除。

信号量

在用户层上,linux提供了和Unix对应的信号量(semaphore)接口,在内核接口,linux提供了供自己使用的信号的具体实现,即在内核中的代码能够调用内核信号量。内核信号量不能通过系统调用直接被用户程序访问。内核信号量作为内核函数实现的,因此比用户可见的信号量更加高效。
Linux在内核提供了三种信号量:二元信号量、技术信号量和读者-写者信号量。

屏障

在一些体系结构中,编译器者处理硬件为了优化性能,可能会对源码的内存访问重新排序。重新排序是为了优化对处理器指令流水线的使用。重新排序的算法包含相应的检查,以保证数据依赖不会发生冲突,例如,代码:

a=1;
b=1;

可被重新排序,以便内存地址b在更新之前更新。然而,代码:

a=1;
b=1;

不能重新排序。即使如此,在某些情况下,读操作和写操作以指定的顺序执行时相当重要的,因为这些信息会被其他线程或硬件设备使用。

为了保证指令执行的顺序。Linux提供了内存屏障(memory barrier)。barrier()操作是mb()的一个轻量版本。
这里写图片描述

这里写图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值