<script>function StorePage(){d=document;t=d.selection?(d.selection.type!='None'?d.selection.createRange().text:''):(d.getSelection?d.getSelection():'');void(keyit=window.open('http://www.365key.com/storeit.aspx?t='+escape(d.title)+'&u='+escape(d.location.href)+'&c='+escape(t),'keyit','scrollbars=no,width=475,height=575,left=75,top=20,status=no,resizable=yes'));keyit.focus();}</script>
作者:刘洪涛,华清远见嵌入式学院金牌讲师,ARM公司授权ATC讲师。
关于自旋锁用法介绍的文章,已经有很多,但有些细节的地方点的还不够透。我这里就把我个人认为大家容易有疑问的地方拿出来讨论一下。
一、自旋锁(spinlock)简介
自旋锁在同一时刻只能被最多一个内核任务持有,所以一个时刻只有一个线程允许存在于临界区中。这点可以应用在多处理机器、或运行在单处理器上的抢占式内核中需要的锁定服务。
二、信号量简介
这里也介绍下信号量的概念,因为它的用法和自旋锁有相似的地方。
Linux中的信号量是一种睡眠锁。如果有一个任务试图获得一个已被持有的信号量时,信号量会将其推入等待队列,然后让其睡眠。这时处理器获得自由去执行其它代码。当持有信号量的进程将信号量释放后,在等待队列中的一个任务将被唤醒,从而便可以获得这个信号量。
三、自旋锁和信号量对比
在很多地方自旋锁和信号量可以选择任何一个使用,但也有一些地方只能选择某一种。下面对比一些两者的用法。
表1-1自旋锁和信号量对比
应用场合
|
信号量or自旋锁
|
低开销加锁(临界区执行时间较快)
|
优先选择自旋锁
|
低开销加锁(临界区执行时间较长)
|
优先选择信号量
|
临界区可能包含引起睡眠的代码
|
不能选自旋锁,可以选择信号量
|
临界区位于非进程上下文时,此时不能睡眠
|
优先选择自旋锁,即使选择信号量也只能用down_trylock非阻塞的方式
|
四、自旋锁与linux内核进程调度关系
我们讨论下表1-1中的第3种情况(其它几种情况比较好理解),如果临界区可能包含引起睡眠的代码则不能使用自旋锁,否则可能引起死锁。
那么为什么信号量保护的代码可以睡眠而自旋锁就不能呢?
先看下自旋锁的实现方法吧,自旋锁的基本形式如下:
spin_lock(&mr_lock);
//临界区
spin_unlock(&mr_lock);
跟踪一下spin_lock(&mr_lock)的实现
#define spin_lock(lock) _spin_lock(lock)
#define _spin_lock(lock) __LOCK(lock)
#define __LOCK(lock) \
do { preempt_disable(); __acquire(lock); (void)(lock); } while (0)
注意到“preempt_disable()”,这个调用的功能是“关抢占”(在spin_unlock中会重新开启抢占功能)。从中可以看出,使用自旋锁保护的区域是工作在非抢占的状态;即使获取不到锁,在“自旋”状态也是禁止抢占的。了解到这,我想咱们应该能够理解为何自旋锁保护的代码不能睡眠了。试想一下,如果在自旋锁保护的代码中间睡眠,此时发生进程调度,则可能另外一个进程会再次调用spinlock保护的这段代码。而我们现在知道了即使在获取不到锁的“自旋”状态,也是禁止抢占的,而“自旋”又是动态的,不会再睡眠了,也就是说在这个处理器上不会再有进程调度发生了,那么死锁自然就发生了。
咱们可以总结下自旋锁的特点:
● 单处理器非抢占内核下:自旋锁会在编译时被忽略;
● 单处理器抢占内核下:自旋锁仅仅当作一个设置内核抢占的开关;
● 多处理器下:此时才能完全发挥出自旋锁的作用,自旋锁在内核中主要用来防止多处理器中并发访问临界区,防止内核抢占造成的竞争。
五、linux抢占发生的时间
最后在了解下linux抢占发生的时间,抢占分为用户抢占和内核抢占。
用户抢占在以下情况下产生:
● 从系统调用返回用户空间
● 从中断处理程序返回用户空间
内核抢占会发生在:
● 当从中断处理程序返回内核空间的时候,且当时内核具有可抢占性;
● 当内核代码再一次具有可抢占性的时候。(如:spin_unlock时)
● 如果内核中的任务显式的调用schedule()
● 如果内核中的任务阻塞。
基本的进程调度就是发生在时钟中断后,并且发现进程的时间片已经使用完了,则发生进程抢占。通常我们会利用中断处理程序返回内核空间的时候可以进行内核抢占这个特性来提高一些I/O操作的实时性,如:当I/O事件发生的是时候,对应的中断处理程序被激活,当它发现有进程在等待这个I/O事件的时候,它会激活等待进程,并且设置当前正在执行进程的need_resched标志,这样在中断处理程序返回的时候,调度程序被激活,原来在等待I/O事件的进程(很可能)获得执行权,从而保证了对I/O事件的相对快速响应(毫秒级)。可以看出,在I/O事件发生的时候,I/O事件的处理进程会抢占当前进程,系统的响应速度与调度时间片的长度无关。
分享到:
相关推荐
Linux 内核调度与 Spinlock 的相互关系 本文主要介绍 Linux 内核调度与 Spinlock 之间的相互关系,涵盖了 Spinlock 的基本概念、信号量的概念、 Spinlock 和信号量的对比、自旋锁与 Linux 内核进程调度的关系,以及...
在嵌入式系统和ARM技术中,理解和掌握spinlock(自旋锁)与Linux内核调度的关系至关重要,尤其是在设计多线程并发访问共享资源的场景。本文由刘洪涛,一位资深的嵌入式培训讲师,针对这一主题进行了深入探讨。 首先...
Linux 内核分析之调度算法 Linux 内核分析之调度算法是 Linux 内核中的一种用于进程调度的机制。调度算法的主要目标是将有限的 CPU 资源分配给多个进程,以提高系统的整体性能和效率。 Linux 调度算法在 2.6.32 ...
《深入理解Linux内核》是Linux系统开发领域的一本经典著作,中文第三版更是结合了最新的Linux内核版本,提供了全面且深入的内核解析。这本书涵盖了从内核设计哲学到具体实现细节的广泛主题,旨在帮助读者深入理解这...
**自旋锁与Linux内核调度关系详解** 自旋锁是一种在多线程环境中用于保护临界区的同步机制,其基本原理是当一个线程试图获取已被其他线程持有的自旋锁时,该线程将不断循环检查锁的状态,直到获得锁为止,即“自旋...
在Linux内核中,常见的同步原语包括自旋锁(spinlock)、读写锁(rwlock)、信号量(semaphore)和完成标志(completion)。自旋锁用于保护短时间的临界区,防止其他CPU核同时访问;读写锁则允许同时有多个读取者但...
《Linux内核源码完全注释》是一份深入解析Linux内核的重要参考资料,它涵盖了Linux内核中的关键组件和机制,包括同步、信号、内存管理、调度、文件系统、网络系统以及时钟等方面。这份资料的编纂历经三年,旨在为...
Linux 内核抢占是指内核代码可以被抢占的机制,即当一个高优先级的进程到达时,不管当前进程处于用户态还是核心态,如果当前允许抢占,可抢占内核的 Linux 都会调度高优先级的进程运行。 内核抢占的实现机制 Linux...
不过,根据标题“轻松与Linux内核交流借鉴.pdf”,我可以假设文件内容涉及到Linux内核的相关知识,以及如何与Linux内核进行交流和借鉴的技巧和方法。接下来我将尝试从以下几个方面梳理关于Linux内核的基础知识点: ...
Linux 中主要有三种内核锁:spinlock、mutex 和rwlock。spinlock 是一种低级别的锁机制,适用于短期的锁定操作;mutex 是一种互斥锁机制,适用于长期的锁定操作;rwlock 是一种读写锁机制,适用于读写操作。 二、...
"LINUX内核经典面试题" 作为一个专业的IT行业大师,我将从给定的文件中生成相关知识点: 一、Linux内核锁 Linux中主要有两种内核锁:spinlock和mutex。spinlock是一种忙等锁,用于保护短期的临界资源,而mutex是...
3. **进程管理**:Linux内核负责进程的创建、调度、同步和通信。理解`fork()`和`exec()`如何创建新进程,以及`wait()`和`signal()`如何处理进程间交互,对于编写多线程和多进程程序至关重要。 4. **内存管理**:...
1. **进程管理**:Linux内核中的进程管理是其核心功能之一,包括进程创建、调度、同步和通信等。了解`do_fork()`函数如何创建新的进程,以及`schedule()`函数如何根据调度策略决定下一个执行的进程,对于理解内核...
Linux内核作为该操作系统的核心部分,负责系统资源的管理与调度,以及硬件和软件之间的通信。在多核处理器、多线程、网络通讯等并发环境下,数据同步问题变得尤为重要,是保证系统稳定运行的关键技术之一。 数据...
《深入理解Linux内核》是Linux系统开发领域的一本经典著作,它为读者提供了深入了解Linux内核机制的机会。这本书的第三版,"Understanding_the_Linux_Kernel_3rd",全面解析了Linux 2.6版本的内核,涵盖了自第二版...
本篇文章主要探讨了Linux内核中的互斥机制,包括Semaphore和Spinlock两种主要的同步工具,以及它们在不同场景下的应用。 Semaphore是一种进程级别的互斥手段,它主要用于多个进程之间对共享资源的访问控制。当一个...
中断处理分为硬中断和软中断,其中硬中断是实时响应的,而软中断可以在中断完成后由内核调度执行。 6. **系统调用**:通过定义新的系统调用,可以扩展Linux内核的功能,使其能够被用户空间程序直接调用。这涉及到`...