`
gstarwd
  • 浏览: 1536677 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

信号量和自旋锁

阅读更多

内核同步措施

    为了避免并发,防止竞争。内核提供了一组同步方法来提供对共享数据的保护。 我们的重点不是介绍这些方法的详细用法,而是强调为什么使用这些方法和它们之间的差别。
    Linux 使用的同步机制可以说从2.0到2.6以来不断发展完善。从最初的原子操作,到后来的信号量,从大内核锁到今天的自旋锁。这些同步机制的发展伴随 Linux从单处理器到对称多处理器的过度;伴随着从非抢占内核到抢占内核的过度。锁机制越来越有效,也越来越复杂。
    目前来说内核中原子操作多用来做计数使用,其它情况最常用的是两种锁以及它们的变种:一个是自旋锁,另一个是信号量。我们下面就来着重介绍一下这两种锁机制。


自旋锁
------------------------------------------------------
    自旋锁是专为防止多处理器并发而引入的一种锁,它在内核中大量应用于中断处理等部分(对于单处理器来说,防止中断处理中的并发可简单采用关闭中断的方式,不需要自旋锁)。
    自旋锁最多只能被一个内核任务持有,如果一个内核任务试图请求一个已被争用(已经被持有)的自旋锁,那么这个任务就会一直进行忙循环——旋转——等待锁重新可用。
要是锁未被争用,请求它的内核任务便能立刻得到它并且继续进行。自旋锁可以在任何时刻防止多于一个的内核任务同时进入临界区,因此这种锁可有效地避免多处理器上并发运行的内核任务竞争共享资源。
    事实上,自旋锁的初衷就是:在短期间内进行轻量级的锁定。一个被争用的自旋锁使得请求它的线程在等待锁重新可用的期间进行自旋(特别浪费处理器时间),所以自旋锁不应该被持有时间过长。如果需要长时间锁定的话, 最好使用信号量。
自旋锁的基本形式如下:
    spin_lock(&mr_lock);
    //临界区
    spin_unlock(&mr_lock);

    因为自旋锁在同一时刻只能被最多一个内核任务持有,所以一个时刻只有一个线程允许存在于临界区中。这点很好地满足了对称多处理机器需要的锁定服务。在单处 理器上,自旋锁仅仅当作一个设置内核抢占的开关。如果内核抢占也不存在,那么自旋锁会在编译时被完全剔除出内核。
    简单的说,自旋锁在内核中主要用来防止多处理器中并发访问临界区,防止内核抢占造成的竞争。 另外自旋锁不允许任务睡眠(持有自旋锁的任务睡眠会造成自死锁——因为睡眠有可能造成持有锁的内核任务被重新调度,而再次申请自己已持有的锁),它能够在中断上下文中使用
    死锁:假设有一个或多个内核任务和一个或多个资源,每个内核都在等待其中的一个资源,但所有的资源都已经被占用了。这便会发生所有内核任务都在相互等待, 但它们永远不会释放已经占有的资源,于是任何内核任务都无法获得所需要的资源,无法继续运行,这便意味着死锁发生了。自死琐是说自己占有了某个资源,然后 自己又申请自己已占有的资源,显然不可能再获得该资源,因此就自缚手脚了。


信号量
------------------------------------------------------
    Linux中的信号量是一种睡眠锁。如果有一个任务试图获得一个已被持有的信号量时,信号量会将其推入等待队列,然后让其睡眠。这时处理器获得自由去执行 其它代码。当持有信号量的进程将信号量释放后,在等待队列中的一个任务将被唤醒,从而便可以获得这个信号量。
    信号量的睡眠特性,使得信号量适用于锁会被长时间持有的情况;只能在进程上下文中使用,因为中断上下文中是不能被调度的;另外当代码持有信号量时,不可以再持有自旋锁。

信号量基本使用形式为:
static DECLARE_MUTEX(mr_sem);//声明互斥信号量
if(down_interruptible(&mr_sem))
    //可被中断的睡眠,当信号来到,睡眠的任务被唤醒
    //临界区
up(&mr_sem);


信号量和自旋锁区别
------------------------------------------------------
    虽然听起来两者之间的使用条件复杂,其实在实际使用中信号量和自旋锁并不易混淆。注意以下原则:
    如果代码需要睡眠——这往往是发生在和用户空间同步时——使用信号量是唯一的选择。由于不受睡眠的限制,使用信号量通常来说更加简单一些。如果需要在自旋 锁和信号量中作选择,应该取决于锁被持有的时间长短。理想情况是所有的锁都应该尽可能短的被持有,但是如果锁的持有时间较长的话,使用信号量是更好的选 择。另外,信号量不同于自旋锁,它不会关闭内核抢占,所以持有信号量的代码可以被抢占。这意味者信号量不会对影响调度反应时间带来负面影响。


自旋锁对信号量
------------------------------------------------------
需求                     建议的加锁方法

低开销加锁               优先使用自旋锁
短期锁定                 优先使用自旋锁
长期加锁                 优先使用信号量
中断上下文中加锁          使用自旋锁
持有锁是需要睡眠、调度     使用信号量

分享到:
评论

相关推荐

    信号量与自旋锁

    本文将深入探讨两种常见的同步机制——信号量和自旋锁,它们在Linux内核中的应用以及如何有效地使用它们。 #### 一、信号量:睡眠锁机制 **信号量**是一种广泛使用的同步机制,用于控制多个进程对共享资源的访问。...

    原子操作、信号量、读写信号量和自旋锁的API

    ### 原子操作、信号量、读写信号量和自旋锁的API详解 #### 一、引言 在现代操作系统中,特别是在多处理器环境下,确保数据的一致性和完整性至关重要。为此,Linux内核提供了多种同步机制来保护共享资源免受并发...

    信号量、互斥体和自旋锁的区别

    ### 信号量、互斥体和自旋锁的区别详解 #### 一、基本概念与应用场景 **信号量**、**互斥体**和**自旋锁**是操作系统中三种常用的同步机制,主要用于解决多线程或多进程环境中资源的并发访问问题。这三种机制虽然...

    华为内部招聘面试题

    这个例子涉及到循环控制表达式中的逻辑运算符`&&`(逻辑与)和`||`(逻辑或)的使用,以及循环内的函数调用。 ```java public class Test { static boolean foo(char c) { System.out.print(c); return true; }...

    基于SMP的Linux内核自旋锁分析.pdf

    Linux内核中有多种方法来实现并发执行,包括信号量、自旋锁、原语操作和等待队列等,但自旋锁是SMP系统中最主要的并发机制。 自旋锁是一种 Busy-Waiting 机制,即当一个处理器尝试访问共享资源时,如果该资源当前被...

    无锁编程之自旋锁的C++实现

    无锁编程是一种高级的并发控制技术,它避免了在多线程环境中使用传统的互斥量或信号量等机制带来的上下文切换开销。在无锁编程中,自旋锁是核心概念之一,它用于保护共享资源,使得在等待资源释放时,线程不会被挂起...

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

    与自旋锁相比,信号量和读写信号量更适合于那些可能需要较长时间持有锁的情况,它们允许调用者进入睡眠状态,但这限制了它们只能在进程上下文中使用。而在中断上下文,如中断处理程序或软中断中,必须使用自旋锁,...

    Windows驱动编程视频教程 提升IRQ与自旋锁

    6. 其他同步机制:对比自旋锁与其他同步机制,如信号量、事件和调度延迟,了解各自适用的场景。 通过这个视频教程,开发者不仅能够提升对IRQ和自旋锁的理解,还能学会如何在实际项目中有效地应用这些知识,编写出...

    Linux设备驱动中的互斥机制.pdf

    Linux 提供了多种互斥机制,包括中断屏蔽、原子操作、信号量和自旋锁等。本文将详细介绍这些互斥机制的优缺点和使用方法。 1. 中断屏蔽 中断屏蔽是避免竞态的简单方法,即在进入临界区之前屏蔽系统的中断。这可以...

    并发控制之自旋锁.pdf

    如果需要长时间锁定资源,应该考虑使用其他机制,如信号量。 2. **避免自旋锁的递归调用**:递归使用自旋锁可能会导致死锁,因为线程可能会无限期地等待自己释放锁。 3. **禁止在自旋锁保护的代码中调用可能导致调度...

    操作系统——理发师问题

    解决理发师问题通常采用信号量机制,包括二元信号量和自旋锁。二元信号量的值只能在0和1之间变化,用来实现资源的互斥访问。自旋锁是另一种同步原语,当获取锁失败时,线程不会被挂起,而是会持续检查锁的状态,直到...

    linux_锁_原子_自旋

    常见的锁类型包括互斥锁(mutex)、读写锁(rwlock)和信号量(semaphore)。互斥锁保证一次只有一个线程能持有锁,实现临界区的互斥访问;读写锁允许多个读取者同时访问,但写入者独占资源;信号量则提供了更灵活的...

    嵌入式系统/ARM技术中的Linux内核同步机制的自旋锁原理

    自旋锁是Linux内核中一种重要的同步机制,特别是在多处理器(SMP)环境中,用于保护共享资源免受并发访问。...因此,合理地使用自旋锁,结合其他的同步机制,如信号量、读写锁等,可以构建更加健壮和高效的嵌入式系统。

    C#多线程编程中的锁系统(四):自旋锁

    二:自旋锁示例 三:SpinLock 四:继续SpinLock 五:总结 一:基础 内核锁:基于内核对象构造的锁机制,就是通常说的内核构造模式。用户模式构造和内核模式构造  优点:cpu利用最大化。它发现资源被锁住,请求就...

    iscsi_target_tq.rar_The Target

    5. 锁机制:理解信号量和自旋锁的概念,以及在多线程环境中的应用。 6. C语言:作为实现语言的基础,需要掌握C语言的语法和特性。 通过对`iscsi_target_tq.c`和`iscsi_target_tq.h`文件的分析和调试,开发者可以更...

    linux内核同步机制1

    在Linux系统中,有多种同步机制,如原子操作、自旋锁和信号量,它们各有特点,用于不同的场景。这里我们将重点讨论自旋锁和信号量。 自旋锁是专为多处理器环境设计的一种轻量级锁定机制,它不允许持锁任务睡眠。...

    linux内核调度与spinlock的相互关系.docx

    本文主要介绍 Linux 内核调度与 Spinlock 之间的相互关系,涵盖了 Spinlock 的基本概念、信号量的概念、 Spinlock 和信号量的对比、自旋锁与 Linux 内核进程调度的关系,以及 Linux 抢占的时间。 一、自旋锁...

    linux驱动基础试题.pdf

    Linux 驱动基础试题涵盖了 Linux 驱动程序的基础知识,包括设备分类、设备节点、驱动程序组织、内存管理、定时器、中断、信号量、自旋锁、设备驱动程序和普通应用程序的异同点等。 一、选择题 1. Linux 系统中将...

Global site tag (gtag.js) - Google Analytics