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

spinlock中不允许休眠调度 转

阅读更多

http://blog.csdn.net/unbutun/archive/2010/07/15/5738313.aspx

 

spinlock的使用,由于开始时不太了解,开发内核模块时,出了问题,调试了好多天,后来才发现,原来在lock的代码里,调用的内核api中,执行了schedule!!!!

转发这篇文章以此来警醒我的无知

 

 

Linux系统提供的内核同步机制有很多种。 
spinlock只是一种选择, 并不是所有同步的地方都用spinlock. 
通常它适用于对内核(包括模块)的一些全局数据结构的访问。 
spinlock中所保护的codes最好能迅速完成,同时释放该锁。 
在无法获得该锁的情况下,内核不会切换,而是不断地尝试, 这也是spinlock名字的由来, 
也正因为此,所以spinlock中的代码不能有schedule()之类的放弃CPU的代码,也不会能被抢占,但可以有中断(下面说明)。因为如果正好调度到另一个kernel path也需要这个锁,整个系统将形成死锁。 
如果有中断服务也会申请该spinlock,那么请用spinlock_irqsave()的API,把中断关掉,不然还是会死锁。

 

5.5.2. 自旋锁和原子上下文

想象一会儿你的驱动请求一个自旋锁并且在它的临界区里做它的事情. 在中间某处, 你的驱动失去了处理器. 或许它已调用了一个函数( copy_from_user, 假设) 使进程进入睡眠. 或者, 也许, 内核抢占发威, 一个更高优先级的进程将你的代码推到一边. 你的代码现在持有一个锁, 在可见的将来的如何时间不会释放这个锁. 如果某个别的线程想获得同一个锁, 它会, 在最好的情况下, 等待( 在处理器中自旋 )很长时间. 最坏的情况, 系统可能完全死锁.

大部分读者会同意这个场景最好是避免. 因此, 应用到自旋锁的核心规则是任何代码必须, 在持有自旋锁时, 是原子性的. 它不能睡眠; 事实上, 它不能因为任何原因放弃处理器, 除了服务中断(并且有时即便此时也不行)

内核抢占的情况由自旋锁代码自己处理. 内核代码持有一个自旋锁的任何时间, 抢占在相关处理器上被禁止. 即便单处理器系统必须以这种方式禁止抢占以避免竞争情况. 这就是为什么需要正确的加锁, 即便你从不期望你的代码在多处理器机器上运行.

在持有一个锁时避免睡眠是更加困难; 很多内核函数可能睡眠, 并且这个行为不是都被明确记录了. 拷贝数据到或从用户空间是一个明显的例子: 请求的用户空间页可能需要在拷贝进行前从磁盘上换入, 这个操作显然需要一个睡眠. 必须分配内存的任何操作都可能睡眠. kmalloc 能够决定放弃处理器, 并且等待更多内存可用除非它被明确告知不这样做. 睡眠可能发生在令人惊讶的地方; 编写会在自旋锁下执行的代码需要注意你调用的每个函数.

这有另一个场景: 你的驱动在执行并且已经获取了一个锁来控制对它的设备的存取. 当持有这个锁时, 设备发出一个中断, 使得你的中断处理运行. 中断处理, 在存取设备之前, 必须获得锁. 在一个中断处理中获取一个自旋锁是一个要做的合法的事情; 这是自旋锁操作不能睡眠的其中一个理由. 但是如果中断处理和起初获得锁的代码在同一个处理器上会发生什么? 当中断处理在自旋, 非中断代码不能运行来释放锁. 这个处理器将永远自旋.

避免这个陷阱需要在持有自旋锁时禁止中断( 只在本地 CPU ). 有各种自旋锁函数会为你禁止中断( 我们将在下一节见到它们 ). 但是, 一个完整的中断讨论必须等到第 10 章了.

关于自旋锁使用的最后一个重要规则是自旋锁必须一直是尽可能短时间的持有. 你持有一个锁越长, 另一个进程可能不得不自旋等待你释放它的时间越长, 它不得不完全自旋的机会越大. 长时间持有锁也阻止了当前处理器调度, 意味着高优先级进程 -- 真正应当能获得 CPU 的 -- 可能不得不等待. 内核开发者尽了很大努力来减少内核反应时间( 一个进程可能不得不等待调度的时间 )在 2.5 开发系列. 一个写的很差的驱动会摧毁所有的进程, 仅仅通过持有一个锁太长时间. 为避免产生这类问题, 重视使你的锁持有时间短.

 

 

如果只要和其他CPU 互斥,就要用spin_lock/spin_unlock,如果要和irq及其他CPU互斥,就要用 
spin_lock_irq/spin_unlock_irq,如果既要和irq及其他CPU互斥,又要保存 EFLAG的状态,就要用spin_lock_irqsave/spin_unlock_irqrestore,如果要和bh及其他CPU互斥,就要用spin_lock_bh/spin_unlock_bh,如果不需要和 其他CPU互斥,只要和irq互斥,则用local_irq_disable/local_irq_enable, 如果不需要和其他CPU互斥,只要和bh互斥,则用local_bh_disable/local_bh_enable, 等等。值得指出的是,对同一个数据的互斥,在不同的内核执行路径中, 
所用的形式有可能不同

 

Mutex属于sleep-waiting类型的锁。

而Spin lock则属于busy-waiting类型的锁

分享到:
评论

相关推荐

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

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

    嵌入式系统/ARM技术中的spinlock与linux内核调度的关系

    在嵌入式系统和ARM技术中,理解和掌握spinlock(自旋锁)与Linux内核调度的关系至关重要,尤其是在设计多线程并发访问共享资源的场景。本文由刘洪涛,一位资深的嵌入式培训讲师,针对这一主题进行了深入探讨。 首先...

    spinlock與linux內核調度的關係

    - 在非进程上下文中,如中断处理程序,自旋锁是首选,因为此时不允许线程睡眠。 **自旋锁与内核调度关系** 在自旋锁保护的代码中,如果发生睡眠,可能导致死锁。这是因为自旋锁在获取时会禁用抢占,这意味着即使在...

    Linux内核分析之调度算法.doc

    rq 结构体中包括了 spinlock_t lock、nr_running、cpu_load 等字段,分别用于实现互斥访问、记录当前处理器上的运行进程数量和表示处理器的负载。 Linux 调度算法的实现中还存在一些重要的宏定义,如 SCHED_NORMAL...

    MCS spinlock的Linux内核模块实现.pdf

    2. MCS Spinlock 的实现:MCS Spinlock 的实现可以通过 Linux 内核模块来实现,通过在 Linux 内核中添加 MCS Spinlock 模块,以实现高效的自旋锁机制。 3. MCS Spinlock 的优点:MCS Spinlock 比传统的自旋锁机制...

    spinlock_test.c

    在实际使用中,在关抢占的情况下调用schedule,内核允许会报bug 2.3.5.3 自旋锁变种分析 自旋锁变种使用的原则就是谁抢CPU就关谁 ① 何时关中断 如果除了当前的内核任务,还有中断处理程序会访问临界区,则需要关...

    linux系统中基于自旋锁的进程调度的实现

    在Linux操作系统中,进程调度是内核核心功能之一,它负责管理系统中的多个并发执行的任务,确保公平且高效地分配CPU资源。自旋锁作为内核同步机制的一部分,被广泛用于保护共享数据结构免受并发访问,特别是在多...

    Linux设备驱动程式学习(5)-高级字符驱动程式操作[(2)阻塞型IO和休眠][汇编].pdf

    1. **禁止在原子上下文中休眠**:这意味着在持有自旋锁、seqlock或RCU锁时,不能进行休眠,因为这可能导致死锁。关闭中断时也不能休眠。 2. **安全休眠**:持有一个信号量时可以休眠,但必须谨慎,确保休眠时间短且...

    spinlock:Go和内联汇编器中的Spinlock实现

    Go和内联汇编程序中的Spinlock实现。 概述 程序包自旋锁提供了汇编中低级自旋锁的实现。 此外,它还提供了基于内置原子的实现的后备功能。 在我的私人笔记本电脑上,基准测试结果如下。 所测量的时间是墙上的时间。...

    mips 多核 互斥 Spinlock 底层实现

    ### MIPS多核处理器中的Spinlock底层实现 #### 引言 随着处理器技术的进步,特别是针对高性能及低功耗的需求,多核处理器成为了嵌入式领域的主流趋势。在多核架构中,不同核心间的资源共享和同步变得至关重要。...

    嵌入式系统/ARM技术中的分析Linux中Spinlock在ARM及X86平台上的实现

    本文主要以2.6.22.6内核分析Linux中spinlock在ARM及X86平台上的实现(不同版本的内核实现形式会有一些差异,但原理大致相同)。此处默认大家已经熟悉了spinlock的使用,重点解释容易引起迷惑的体系结构相关的实现...

    cvmx-spinlock.rar_V2

    本文将深入探讨"CVMX Spinlock"在Linux v2.13.6版本中的实现细节和其在Octeon处理器上的应用。 CVMX,全称Cavium Networks Octeon eXtensions,是针对Cavium Octeon系列多核处理器的一套硬件抽象层。Octeon处理器以...

    linux系统的O(1)调度算法

    1. **spinlock_t lock**:这是一个自旋锁,用于保护运行队列不被多个CPU同时访问,确保数据一致性。 2. **nr_running**:记录当前系统中可运行的进程数量。 3. **active**:指向当前活动的优先级队列,存放还有...

    cas实现spinlock

    cas实现spinlock

    spinlock.rs:Rust 中的自旋锁实现

    Rust 中的自旋锁实现 建造 运行cargo build 用法 该库实现了 Reader/Writer 锁。 锁定共享读取访问的自旋锁时,您将获得对受保护数据的引用,而锁定独占写入访问时,您将获得可变引用。 extern crate spinlock; ...

    Linux学习总结—Linux调度器分析[定义].pdf

    8. **O(1)调度算法**:调度器的开销是常量级别的,不随系统负载增加而增加,从而提高了实时响应速度。 9. **高可扩展性**:通过减少锁粒度,降低了并发访问的冲突,支持大规模的处理器核心数量。 10. **新的数据...

    SpinLock.cpp

    为了效率,不使用C++语言提供的Mutex互斥量,而使用不使用线程被阻塞的方式,即所谓的自旋锁,这是自旋锁的一种实现方式,使用C++11的原子变量,不用锁机制,实现的一种无锁的自旋锁

Global site tag (gtag.js) - Google Analytics