抢占式内核与非抢占式内核中的自旋锁(spinlock)的区别

一、概括

(1)自旋锁适用于SMP系统,UP系统用spinlock是作死。

(2)保护模式下禁止内核抢占的方法:1、执行终端服务例程时2、执行软中断和tasklet时3、设置本地CPU计数器preempt_count

(3)自旋锁的忙等待的实际意义是:尝试获取自旋锁的另一个进程不断尝试获取被占用的自旋锁,中间只pause一下!

(4)在抢占式内核的spin_lock宏中,第一次关抢占,目的是防止死锁(防止一个已经获取自旋锁而未释放的进程被抢占!!)。而后又开抢占,目的是让已经释放自旋锁的进程可以被调度出去,让其他进程可以进入临界区。当然,开启内核抢占后,调度器调度的进程是不是在盲等的进程不可而知!

二、具有内核抢占的spin_lock宏

让我们来详细讨论用于请求自旋锁的spin_lock宏。下面的描述都是针对支持SMP系统的抢占式内核的。该宏获取自旋锁的地址sip作为它的参数,并执行下面的操作:

调用preempt_disable()以禁用内核抢占

调用函数__raw_spin_trylock(),它对自旋锁的slock字段执行原子性的测试和设置操作。该操作首先执行等价于下列汇编片段的一些指令:

movb$0,%a1

xchgb%al,slp->slock

汇编语言指令xchg原子性地交换8位寄存器%al和slp->slock指示的内存单元的内容。随后,如果存放在自旋锁中的旧值是正数,函数就返回1,否则返回0。

如果自旋锁中的旧值是正数,宏结束;内核控制路径已经获得自旋锁。

否则,内核控制路径无法获得自旋锁,因此宏必须执行循环一直到在其它CPU上运行的内核控制路径释放自旋锁。调用preempt_enable()递减在第1步递增了的抢占计数器。如果在执行spin_lock宏之前内核抢占被启用,那么其它进程此时可以取代等待自旋锁的进程。

如果break_lock字段等于0,则把它设置为1。通过检测该字段,拥有锁并在其它CPU上运行的进程可以知道是否有其它进程在等待这个锁。如果进程把持某个自旋锁的时间太长,它可以提前释放锁以便等待相同自旋锁的进程能够继续向前运行。

执行等待循环:

while(spin_is_locked(sip)&& slp->break_lock)

cpu_relax();

宏cpu_relax()简化为一条pause汇编语言指令。在Pentium4模型中引入了这条指令以优化自旋锁循环的执行。通过引入一个很短的延迟,加快了紧跟在锁后面的代码的执行并减少了能源消耗。pause与早先的80x86微处理器模型是向后兼容的,因为它对应rep;nop指令,也就是对应空操作。

跳转回第1步,再次试图获取自旋锁

三、非抢占式内核中的spin_lock宏

如果在内核编译时没有选择内核抢占选项,spin_lock宏就与前面描述的spin_lock宏有很大的区别。在这种情况下,宏生成一个汇编语言程序片段,它本质上等价于下面紧凑的忙等待:

1:lock;decbslp->lock

jns3f

2:pause

cmpb$0,slp->slock

jle2b

jmp1b

3;

汇编语言指令decb递减自旋锁的值,该指令是原子的,因为它带有lock字节前缀。随后检测符号标志,如果它被清0,说明自旋锁被设置为1,因此从标记3处继续正常执行。否则,在标签2处执行紧凑循环直到自旋锁出现正值。然后从标签1处开始重新执行,因为不检查其它的处理器是否抢占了锁就继续执行是不安全的。

spin_unlock宏

spin_unlock宏释放以前获得的自旋锁,它本质上执行下列汇编语言指令;

movb$1,slp->slock

并在随后调用preempt_enable(),注意,因为现在的80x86微处理器总是原子地执行内存中的只写访问,所以不使用lock字节。

时间: 2024-10-22 09:18:48

抢占式内核与非抢占式内核中的自旋锁(spinlock)的区别的相关文章

抢占式内核与非抢占式内核

2013-02-06 10:43 3269人阅读 评论(3) 收藏 举报  分类: [OS](4)  版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] UNIX采用抢占式内核,Linux采用非抢占式内核 内核抢占(可抢占式内核):即当进程位于内核空间时,有一个更高优先级的任务出现时,如果当前内核允许抢占,则可以将当前任务挂起,执行优先级更高的进程. 非抢占式内核:高优先级的进程不能中止正在内核中运行的低优先级的进程而抢占CPU运行.进程一旦处于核心态(例如用户进程执行系统调

登录式shell和非登录式shell

在用户的角度,SHELL的类型有两种: 登录式shell: 正常通过某客户端登录 su - USERNAME  或  su -l USERNAME 非登录式shell: su USERNAME 图形终端下打开的命令窗口 自动执行的shell脚本 bash的配置文件: 全局配置: /etc/profile     , /etc/profile.d/*.sh    ,    /etc/bashrc 个人配置: ~/.bash_profile,    ~/.bashrc  profile类的文件: 设

登录式shell和非登录式shell的区别

在用户的角度,SHELL的类型有两种: 登录式shell: 正常通过某客户端登录 su - USERNAME  或  su -l USERNAME 非登录式shell: su USERNAME 图形终端下打开的命令窗口 自动执行的shell脚本 bash的配置文件: 全局配置: /etc/profile     , /etc/profile.d/*.sh    ,    /etc/bashrc 个人配置: ~/.bash_profile,    ~/.bashrc  profile类的文件: 设

[笔记]登录式Shell与非登录式Shell

登录式shell:        通过终端登录        su - USERNAME非登录式shell:        su USERNAME(用su切换用户,不带参数)        GUI下打开命令窗口        自动执行的shell脚本(使用at, crontab, anacron等) bash的配置文件:        全局配置:/etc/profile,/etc/profile.d/*.sh,/etc/bashrc        个人配置:~/.bash_profile,~/.

登录式shell与非登录式shell

登录式shell:su – usernamesu -l username 非登录式shell:su username图形终端下打开命令窗口自动执行的shell脚本 bash的配置文件全局配置:    /etc/profile,/etc/proflie.d/*.sh,/etc/bashrc个人配置:    -/.bash_profile,-/.bashrc profiles类配置文件:    设定环境变量,运行命令或脚本 bashrc类配置文件:    设定本地变量,定义命令别名 登录式shell

Java基础:非阻塞式IO

转载请注明出处:jiq?钦's technical Blog 引言 JDK1.4中引入了NIO,即New IO,目的在于提高IO速度.特别注意JavaNIO不完全是非阻塞式IO(No-Blocking IO),因为其中部分通道(如FileChannel)只能运行在阻塞模式下,而其他的通道可以在阻塞式和非阻塞式之间进行选择. 尽管这样,我们还是习惯将Java NIO看作是非阻塞式IO,而前面介绍的面向流(字节/字符)的IO类库则是非阻塞的,详细来看,两者区别如下: IO NIO 面向流(Strea

Linux内核的同步机制---自旋锁

自旋锁的思考:http://bbs.chinaunix.net/thread-2333160-1-1.html 近期在看宋宝华的<设备驱动开发具体解释>第二版.看到自旋锁的部分,有些疑惑.所以来请教下大家. 以下是我參考一些网络上的资料得出的一些想法,不知正确与否.记录下来大家讨论下: (1) linux上的自旋锁有三种实现: 1. 在单cpu.不可抢占内核中,自旋锁为空操作. 2. 在单cpu,可抢占内核中,自旋锁实现为"禁止内核抢占".并不实现"自旋"

Linux 2.6内核中新的锁机制--RCU

转自:http://www.ibm.com/developerworks/cn/linux/l-rcu/ 一. 引言 众所周知,为了保护共享数据,需要一些同步机制,如自旋锁(spinlock),读写锁(rwlock),它们使用起来非常简单,而且是一种很有效的同步机制,在UNIX系统和Linux系统中得到了广泛的使用.但是随着计算机硬件的快速发展,获得这种锁的开销相对于CPU的速度在成倍地增加,原因很简单,CPU的速度与访问内存的速度差距越来越大,而这种锁使用了原子操作指令,它需要原子地访问内存,

内核同步之自旋锁与读写自旋锁

用在多个CPU系统中的锁机制,当一个CPU正访问自旋锁保护的临界区时,临界区将被锁上,其他需要访问此临界区的CPU只能忙等待,直到前面的CPU已访问完临界区,将临界区开锁.自旋锁上锁后让等待线程进行忙等待而不是睡眠阻塞,而信号量是让等待线程睡眠阻塞.自旋锁的忙等待浪费了处理器的时间,但时间通常很短,在1毫秒以下. 自旋锁用于多个CPU系统中,在单处理器系统中,自旋锁不起锁的作用,只是禁止或启用内核抢占.在自旋锁忙等待期间,内核抢占机制还是有效的,等待自旋锁释放的线程可能被更高优先级的线程抢占CP