版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、linux内核-第七章 内核中的同步 内核中的同步内核中的同步 临界区和竞争状态 内核同步措施 并发控制 linux内核-第七章 内核中的同步 对于应用程序开发来说,用户空间的任对于应用程序开发来说,用户空间的任 务调度与同步之间的关系相对简单,无务调度与同步之间的关系相对简单,无 需过多考虑需要同步的原因。因为需过多考虑需要同步的原因。因为: : 在用户空间中各个进程都拥有独立的运行在用户空间中各个进程都拥有独立的运行 空间,进程内部的数据对外不可见,所以空间,进程内部的数据对外不可见,所以 各个进程即使并发执行也不会产生对数据各个进程即使并发执行也不会产生对数据 访问的竞争。访问的竞争。
2、用户空间与内核空间独立,所以用户进程用户空间与内核空间独立,所以用户进程 不会与不会与内核任务内核任务交错执行,因此用户进程交错执行,因此用户进程 不存在与内核任务并发的可能。不存在与内核任务并发的可能。 引言引言 linux内核-第七章 内核中的同步 内核空间中情况要复杂得多,需要考虑内核空间中情况要复杂得多,需要考虑 同步的原因大大增加了。因为同步的原因大大增加了。因为: 内核空间中的共享数据对内核中的所有任内核空间中的共享数据对内核中的所有任 务可见,所以当在内核中访问数据时,就务可见,所以当在内核中访问数据时,就 必须考虑是否会有其他内核任务并发访问必须考虑是否会有其他内核任务并发访问
3、 的可能、是否会产生竞争条件、是否需要的可能、是否会产生竞争条件、是否需要 对数据同步。而内核并发的对数据同步。而内核并发的“罪魁祸首罪魁祸首” 便是内核中复杂多变的任务调度便是内核中复杂多变的任务调度这里这里 的任务调度包含所有可能引起内核任务更的任务调度包含所有可能引起内核任务更 换的情况。换的情况。 引言引言 linux内核-第七章 内核中的同步 什么是临界区什么是临界区(critical regions)? 就是访问和操作共享数据的代码段就是访问和操作共享数据的代码段, ,这段代这段代 码必须被码必须被原子地原子地执行执行 什么是竞争状态什么是竞争状态? 多个内核任务同时访问同一临界区
4、多个内核任务同时访问同一临界区 什么是同步什么是同步? 避免并发和防止竞争状态称为避免并发和防止竞争状态称为同步同步 (synchronization) 临界区和竞争状态临界区和竞争状态 linux内核-第七章 内核中的同步 考虑一个非常简单的共享资源的例子:一考虑一个非常简单的共享资源的例子:一 个全局整型变量和一个简单的临界区,其个全局整型变量和一个简单的临界区,其 中的操作仅仅是将整型变量的值增加中的操作仅仅是将整型变量的值增加1: i+i+ 该操作可以转化成下面三条机器指令序列:该操作可以转化成下面三条机器指令序列: (1) (1) 得到当前变量得到当前变量i i的值并拷贝到一个寄存器
5、的值并拷贝到一个寄存器 中中 (2)(2)将寄存器中的值加将寄存器中的值加1 1 (3) (3) 把把i i的新值写回到内存中的新值写回到内存中 临界区举例临界区举例 linux内核-第七章 内核中的同步 内核任务内核任务1 1 内核任务内核任务 2 2 获得获得i(1) - i(1) - 增加增加 i(1-2) -i(1-2) - 写回写回 i(2) -i(2) - 获得获得 i(2)i(2) 增加增加 i(2-3)i(2-3) 写回写回 i(3)i(3) 临界区举例临界区举例 内核任务内核任务1 1 内核任务内核任务2 2 获得 i(1) - - 获得 i(1) 增加 i(1-2) - -
6、 增加 i(1-2) 写回 i(2) - - 写回 i(2) 可能的实际执行结果: 期望的结果 linux内核-第七章 内核中的同步 v 当共享资源是一个复杂的数据结构时,竞争状当共享资源是一个复杂的数据结构时,竞争状 态往往会使该数据结构遭到破坏。态往往会使该数据结构遭到破坏。 v 对于这种情况,锁机制可以避免竞争状态正如对于这种情况,锁机制可以避免竞争状态正如 门锁和门一样,门后的房间可想象成一个临界区。门锁和门一样,门后的房间可想象成一个临界区。 v 在一个指定时间内,房间里只能有个一个内核在一个指定时间内,房间里只能有个一个内核 任务存在,当一个任务进入房间后,它会锁住身任务存在,当一
7、个任务进入房间后,它会锁住身 后的房门;当它结束对共享数据的操作后,就会后的房门;当它结束对共享数据的操作后,就会 走出房间,打开门锁。如果另一个任务在房门上走出房间,打开门锁。如果另一个任务在房门上 锁时来了锁时来了, ,那么它就必须等待房间内的任务出来那么它就必须等待房间内的任务出来 并打开门锁后,才能进入房间。并打开门锁后,才能进入房间。 共享队列和加锁共享队列和加锁 linux内核-第七章 内核中的同步 任何要访问队列的代码首先都需要占住相任何要访问队列的代码首先都需要占住相 应的锁,这样该锁就能阻止来自其它内核应的锁,这样该锁就能阻止来自其它内核 任务的并发访问任务的并发访问: 任务
8、任务 1 1 试图锁定队列 成功:获得锁 访问队列 为队列解除锁 任务任务2 2 试图锁定队列 失败:等待 等待 等待 成功:获得锁 访问队列 为队列解除锁 共享队列和加锁共享队列和加锁 linux内核-第七章 内核中的同步 v 找出哪些数据需要保护是关键所在找出哪些数据需要保护是关键所在 v 内核任务的局部数据仅仅被它本身访内核任务的局部数据仅仅被它本身访 问,显然不需要保护问,显然不需要保护 v 如果数据只会被特定的进程访问,也如果数据只会被特定的进程访问,也 不需加锁不需加锁 v 大多数内核数据结构都需要加锁:若大多数内核数据结构都需要加锁:若 有其它内核任务可以访问这些数据,那有其它内
9、核任务可以访问这些数据,那 么就给这些数据加上某种形式的锁;若么就给这些数据加上某种形式的锁;若 任何其它东西能看到它,那么就要锁住任何其它东西能看到它,那么就要锁住 它它 确定保护对象确定保护对象 linux内核-第七章 内核中的同步 v 死锁产生的条件:死锁产生的条件:有一个或多个并发执行的有一个或多个并发执行的 内核任务和一个或多个资源,每个任务都在内核任务和一个或多个资源,每个任务都在 等待其中的一个资源,但所有的资源都已经等待其中的一个资源,但所有的资源都已经 被占用。所有任务都在相互等待,但它们永被占用。所有任务都在相互等待,但它们永 远不会释放已经占有的资源,于是任何任务远不会释
10、放已经占有的资源,于是任何任务 都无法继续都无法继续 v 典型的死锁:典型的死锁: v 四路交通堵塞四路交通堵塞 v 自死锁:自死锁:一个执行任务试图去获得一个自一个执行任务试图去获得一个自 己已经持有的锁己已经持有的锁 死死 锁锁 linux内核-第七章 内核中的同步 v 加锁的顺序是关键。使用嵌套的锁加锁的顺序是关键。使用嵌套的锁 时必须保证以相同的顺序获取锁,这时必须保证以相同的顺序获取锁,这 样可以阻止致命拥抱类型的死锁样可以阻止致命拥抱类型的死锁 v 不要重复请求同一个锁。不要重复请求同一个锁。 v 越复杂的加锁方案越有可能造成死越复杂的加锁方案越有可能造成死 锁,因此设计应力求简单
11、锁,因此设计应力求简单 死锁的避免死锁的避免 linux内核-第七章 内核中的同步 v 中断中断中断几乎可以在任何时刻异步中断几乎可以在任何时刻异步 发生,也可能随时打断正在执行的代码。发生,也可能随时打断正在执行的代码。 v 内核抢占内核抢占若内核具有抢占性,内核若内核具有抢占性,内核 中的任务就可能会被另一任务抢占中的任务就可能会被另一任务抢占 v 睡眠及与用户空间的同步睡眠及与用户空间的同步在内核执在内核执 行的进程可能会睡眠,这将唤醒调度程行的进程可能会睡眠,这将唤醒调度程 序,导致调度一个新的用户进程执行序,导致调度一个新的用户进程执行 v 对称多处理对称多处理两个或多个处理器可以两
12、个或多个处理器可以 同时执行代码同时执行代码 并发执行的原因并发执行的原因 linux内核-第七章 内核中的同步 v 为了避免并发,防止竞争。内核为了避免并发,防止竞争。内核 提供了一组同步方法来提供对共享提供了一组同步方法来提供对共享 数据的保护数据的保护 v 原子操作原子操作 v 自旋锁自旋锁 v 信号量信号量 内核同步措施内核同步措施 linux内核-第七章 内核中的同步 v 原子操作可以保证指令以原子操作可以保证指令以原子的方式原子的方式 被执行被执行 v 两个原子操作绝对不可能并发地访问两个原子操作绝对不可能并发地访问 同一个变量同一个变量 v LinuxLinux内核提供了一个专门
13、的内核提供了一个专门的atomic_tatomic_t 类型(一个类型(一个2424位原子访问计数器)和一位原子访问计数器)和一 些专门的函数些专门的函数 ,这些函数作用于这些函数作用于 atomic_tatomic_t类型的变量类型的变量 原子操作原子操作 linux内核-第七章 内核中的同步 下面举例说明这些函数的用法:下面举例说明这些函数的用法: 定义一个定义一个atomic_c类型的数据很简单,还可以定义类型的数据很简单,还可以定义 时给它设定初值:时给它设定初值: atomic_t u; /*定义定义 u*/ atomic_t v = ATOMIC_INIT(0) /*定义定义 v
14、并把它并把它 初始化为初始化为0*/ 对其操作:对其操作: atomic_set( /* 会打印会打印7*/ 原子整数操作最常见的用途就是实现计数器。使原子整数操作最常见的用途就是实现计数器。使 用复杂的锁机制来保护一个单纯的计数器是很笨用复杂的锁机制来保护一个单纯的计数器是很笨 拙的,所以,开发者最好使用拙的,所以,开发者最好使用atomic_inc()和和 atomic_dec()这两个相对来说轻便一点的操作。这两个相对来说轻便一点的操作。 原子操作原子操作 linux内核-第七章 内核中的同步 v 自旋锁是专为防止多处理器并发而引自旋锁是专为防止多处理器并发而引 入的一种锁,它在内核中大
15、量应用于中入的一种锁,它在内核中大量应用于中 断处理等部分,而对于单处理器来说,断处理等部分,而对于单处理器来说, 可简单采用关闭中断的方式防止中断处可简单采用关闭中断的方式防止中断处 理程序的并发执行理程序的并发执行 v 自旋锁最多只能被一个内核任务持有,自旋锁最多只能被一个内核任务持有, 若一个内核任务试图请求一个已被持有若一个内核任务试图请求一个已被持有 的自旋锁,那么这个任务就会一直进行的自旋锁,那么这个任务就会一直进行 忙循环,也就是旋转,等待锁重新可用忙循环,也就是旋转,等待锁重新可用 自旋锁自旋锁 linux内核-第七章 内核中的同步 v 设计自旋锁的初衷是在短期间内进行轻量级设
16、计自旋锁的初衷是在短期间内进行轻量级 的锁定。一个被持有的自旋锁使得请求它的的锁定。一个被持有的自旋锁使得请求它的 任务在等待锁重新可用期间进行自旋,所以任务在等待锁重新可用期间进行自旋,所以 自旋锁不应该被持有时间过长自旋锁不应该被持有时间过长 v 自旋锁在内核中主要用来防止多处理器中并自旋锁在内核中主要用来防止多处理器中并 发访问临界区,防止内核抢占造成的竞争发访问临界区,防止内核抢占造成的竞争 v 自旋锁不允许任务睡眠,持有自旋锁的任务自旋锁不允许任务睡眠,持有自旋锁的任务 睡眠会造成自死锁,因此自旋锁能够在中断睡眠会造成自死锁,因此自旋锁能够在中断 上下文中使用上下文中使用 自旋锁自旋
17、锁 linux内核-第七章 内核中的同步 自旋锁的定义如下:自旋锁的定义如下: typedef struct volatile unsigned int lock; spinlock t; 使用自旋锁的基本形式如下:使用自旋锁的基本形式如下: spinlock t mr_lockSPIN_LOCK_UNLOCKED; /* SPIN_LOCK_UNLOCKED 被定义为被定义为0*/ spin_lock( /*临界区临界区*/ spin_unlock( 因为自旋锁在同一时刻最多只能由一个内核任务持有,因为自旋锁在同一时刻最多只能由一个内核任务持有, 所以一个时刻只允许有一个任务存在于临界区中。
18、所以一个时刻只允许有一个任务存在于临界区中。 自旋锁自旋锁 linux内核-第七章 内核中的同步 v Linux中的信号量是一种睡眠锁。若有中的信号量是一种睡眠锁。若有 一个任务试图获得一个已被持有的信号一个任务试图获得一个已被持有的信号 量时,信号量会将其推入等待队列,然量时,信号量会将其推入等待队列,然 后让其睡眠。这时处理器获得自由而去后让其睡眠。这时处理器获得自由而去 执行其它代码。当持有信号量的进程将执行其它代码。当持有信号量的进程将 信号量释放后,在等待队列中的一个任信号量释放后,在等待队列中的一个任 务将被唤醒,从而便可以获得这个信号务将被唤醒,从而便可以获得这个信号 量量 v
19、信号量具有睡眠特性,适用于锁会被长信号量具有睡眠特性,适用于锁会被长 时间持有的情况,只能在进程上下文中时间持有的情况,只能在进程上下文中 使用使用 信号量信号量 linux内核-第七章 内核中的同步 信号量支持两个原子操作P()和V() ,前者做测试操作,后者叫做增加 操作。 后来的系统把这两种操作分别叫做 down()和up(),Linux也遵从这种叫 法。 信号量信号量 linux内核-第七章 内核中的同步 down()操作通过对信号量计数减1来 请求获得一个信号量。如果结果是0 或大于0,信号量锁被获得,任务就 可以进入临界区了。如果结果是负 数,任务会被放入等待队列,处理 器执行其它
20、任务。 up()操作用来释放信号量,该操作 也被称作是“提升(upping)”信 号量,因为它会增加信号量的计数 值。如果在该信号量上的等待队列 不为空,处于队列中等待的任务在 被唤醒的同时会获得该信号量。 信号量信号量 linux内核-第七章 内核中的同步 Linux内核中,struct semaphore类型表示信号 量: struct semaphore atomic_t count; int sleepers; wait_queue_head_t wait; count:大于0,资源可以使用;等于0,信号量 忙,但没有进程等待;count为负数,则资源不 可用,并至少有一个进程等待。
21、sleepers:存放一个标志,表示是否有一些进程 在信号量上睡眠。 wait:存放等待队列链表的地址,当前等待资源 的所有睡眠进程都放在这个链表中。当然,如 果count大于或等于0,等待队列就为空。 信号量的定义信号量的定义 linux内核-第七章 内核中的同步 静态声明信号量: static DECLARE_SEMAPHORE_GENERIC(name,count); name是信号量变量名,count是信号量的使用者数量 创建更为普通的互斥信号量: static DECLARE_MUTEX(name); 初始化动态创建的信号量: sema_init(sem,count); 初始化动态创
22、建的互斥信号量: init_MUTEX(sem); 创建和初始化信号量创建和初始化信号量 linux内核-第七章 内核中的同步 /*定义并声明一个信号量变量,名字为mr_sem,用于信号量计 数*/ static DECLARE_MUTEX(mr_sem); /*试图获取信号量*/ if(down_interruptible( 使用信号量使用信号量 linux内核-第七章 内核中的同步 信号量与自旋锁的比较信号量与自旋锁的比较 需求 建议的加锁方法 低开销加锁 优先使用自旋锁 短期锁定 优先使用自旋锁 长期加锁 优先使用信号量 中断上下文中加锁 使用自旋锁 持有锁时需要睡眠、 调度 使用信号量
23、 linux内核-第七章 内核中的同步 读读写自旋锁写自旋锁 v对共享数据结构的操作往往分成读对共享数据结构的操作往往分成读/ / 写两种类别:一任务读数据结构时允写两种类别:一任务读数据结构时允 许其他任务读(但不能写);任务写许其他任务读(但不能写);任务写 数据时既不允许其他任务读也不允许数据时既不允许其他任务读也不允许 其他任务写。其他任务写。 vLinuxLinux提供了专门的读提供了专门的读写自旋锁,写自旋锁, 它为读和写分别提供了不同的锁。它为读和写分别提供了不同的锁。 linux内核-第七章 内核中的同步 读读写自旋锁写自旋锁 v一个或多个读任务可以并发的持有读一个或多个读任务
24、可以并发的持有读 者锁;相反,用于写的锁最多只能被者锁;相反,用于写的锁最多只能被 一个写任务持有,而且此时不能有并一个写任务持有,而且此时不能有并 发的读操作。发的读操作。 v读读/ /写锁也叫共享写锁也叫共享/ /排斥锁,或者并发排斥锁,或者并发 / /排斥锁:对读者共享,对写者排斥。排斥锁:对读者共享,对写者排斥。 linux内核-第七章 内核中的同步 读读写自旋锁的使用写自旋锁的使用 v初始化:初始化: rwlock_t mr_rwlock = rwlock_t mr_rwlock = RW_LOCK_UNLOCKED;RW_LOCK_UNLOCKED; v在读者代码分支中使用如下函数
25、:在读者代码分支中使用如下函数: read_lock(read_lock( / /* *临界区(只读)临界区(只读)* */ / read_unlock( read_unlock( linux内核-第七章 内核中的同步 读读写自旋锁的使用写自旋锁的使用 v在写者代码分支中使用如下函数:在写者代码分支中使用如下函数: write_lock(write_lock( / /* *临界区(读写)临界区(读写)* */ / write_unlock( write_unlock( v如上所示,读锁和写锁会位于完全分割开如上所示,读锁和写锁会位于完全分割开 的代码分支中。的代码分支中。 linux内核-第七
26、章 内核中的同步 读读写自旋锁的使用写自旋锁的使用 v不能把一个读锁不能把一个读锁“升级升级”为写锁。如为写锁。如 下代码:下代码: read_lock(read_lock( write_lock( write_lock( 将会带来死锁,因为写锁会不断自旋,等将会带来死锁,因为写锁会不断自旋,等 待所有的读者释放锁,其中包括它自己。待所有的读者释放锁,其中包括它自己。 linux内核-第七章 内核中的同步 读读写自旋锁的使用写自旋锁的使用 v优点:多个读者可以安全地获得同一优点:多个读者可以安全地获得同一 个读锁,即使一个线程递归地获得同个读锁,即使一个线程递归地获得同 一读锁也是安全的。一读
27、锁也是安全的。 v缺点:照顾读比照顾写要多一点,大缺点:照顾读比照顾写要多一点,大 量读者必定会使挂起的写者处于饥饿量读者必定会使挂起的写者处于饥饿 状态。状态。 linux内核-第七章 内核中的同步 读读写信号量写信号量 v同自旋锁一样,信号量也有区分读同自旋锁一样,信号量也有区分读/ /写的写的 可能。读可能。读写信号量比普通信号量更有优写信号量比普通信号量更有优 势。势。 v读读写信号量在内核中由写信号量在内核中由rw_semaphorerw_semaphore结结 构表示构表示 v创建静态声明的读创建静态声明的读写信号量写信号量 Static DECLARE_RWSEM(name);S
28、tatic DECLARE_RWSEM(name); v初始化动态创建的读初始化动态创建的读写信号量:写信号量: init_rwsem(struct rw_semaphore init_rwsem(struct rw_semaphore * *sem);sem); linux内核-第七章 内核中的同步 读读写信号量的使用写信号量的使用 Static DECLARE_RWSEM(mr_rwsem);Static DECLARE_RWSEM(mr_rwsem); / /* *试图获取信号量用于读试图获取信号量用于读* */ / Down_read(Down_read( / /* *临界区(只读)临
29、界区(只读)* */ / Up_read(Up_read( / /* * * */ / / /* *试图获取信号量用于写试图获取信号量用于写* */ / Down_write(Down_write( / /* *临界区(读和写)临界区(读和写)* */ / / /* *释放信号量释放信号量* */ / Up_write(Up_write( linux内核-第七章 内核中的同步 v内核任务是指处于内核态执行的任务,内核任务是指处于内核态执行的任务, 具体讲包括:具体讲包括:“内核线程内核线程”、“系统系统 调用调用”、“硬件中断硬件中断”、“下半部任下半部任 务务”等几类等几类 内核任务及其之间
30、的并发关系 linux内核-第七章 内核中的同步 v系统调用:是用户程序通过门机制来进入系统调用:是用户程序通过门机制来进入 内核执行的内核例程,它运行在内核态,内核执行的内核例程,它运行在内核态, 处于进程上下文中,可以认为是代表用户处于进程上下文中,可以认为是代表用户 进程的内核任务进程的内核任务 v内核线程:内核线程可以理解成在内核中内核线程:内核线程可以理解成在内核中 运行的特殊进程,它有自己的运行的特殊进程,它有自己的“进程上下进程上下 文文” v定时器任务队列:任务队列属于下半部,定时器任务队列:任务队列属于下半部, 主要有调度队列、定时器队列和及时队列主要有调度队列、定时器队列和
31、及时队列 等三种任务队列等三种任务队列 内核任务及其之间的并发关系 linux内核-第七章 内核中的同步 系统调用和内核线程可能和各种系统调用和内核线程可能和各种 内核任务并发执行,可能发生竞内核任务并发执行,可能发生竞 争。争。 内核任务及其之间的并发关系 linux内核-第七章 内核中的同步 v 假设存在这样一个的内核共享资源假设存在这样一个的内核共享资源 链表。另外我们构造一个内核多任务链表。另外我们构造一个内核多任务 访问链表的场景:内核线程向链表加入访问链表的场景:内核线程向链表加入 新节点;内核定时器定时删除接点;系新节点;内核定时器定时删除接点;系 统调用销毁链表。统调用销毁链表
32、。 v 上面三种内核任务并发执行时,有可上面三种内核任务并发执行时,有可 能会破坏链表数据的完整性,所以我们能会破坏链表数据的完整性,所以我们 必须对链表进行同步访问保护,以确保必须对链表进行同步访问保护,以确保 数据一致性。数据一致性。 并发控制实例并发控制实例 linux内核-第七章 内核中的同步 利用利用sharelist.o模块实现上述场景。加载模块实现上述场景。加载 模块时会建立定时器任务列队,并将要模块时会建立定时器任务列队,并将要 执行的任务执行的任务(qt_task)插入定时器队列插入定时器队列 (tq_timer),然后反复调度执行(但),然后反复调度执行(但 别不停的执行)
33、。与此同时利用系统中别不停的执行)。与此同时利用系统中 的的keventd内核线程创建内核线程创建100个内核线程,个内核线程, 由它们执行插入链表的工作。但当链表由它们执行插入链表的工作。但当链表 长度超过长度超过100时,则从链表尾删除节点。时,则从链表尾删除节点。 最 后 当 你 需 要 卸 载 模 块 时 , 调 用最 后 当 你 需 要 卸 载 模 块 时 , 调 用 share_exit函数销毁整个链表,并做一些函数销毁整个链表,并做一些 诸如销毁我们建立的内核线程的收尾工诸如销毁我们建立的内核线程的收尾工 作。作。 实现机制实现机制 linux内核-第七章 内核中的同步 主要的共
34、享资源是链表(主要的共享资源是链表(mine),操作它操作它 的内核任务有三个:一是的内核任务有三个:一是100个内核线程个内核线程 (sharelist),它们负责从表头将新节),它们负责从表头将新节 点(点(struct my_struct)插入链表。二是)插入链表。二是 定时器任务定时器任务(qt_task),它负责每个时钟,它负责每个时钟 节拍时从链表头删除一个节点。三是系节拍时从链表头删除一个节点。三是系 统调用统调用share_exit,它负责销毁链表并卸,它负责销毁链表并卸 载模块。载模块。 实现机制实现机制 linux内核-第七章 内核中的同步 上述场景中存在的任务并发包括:上
35、述场景中存在的任务并发包括: 内核线程之间的并发、内核任务与内核线程之间的并发、内核任务与 定时器任务的并发。我们知道内核定时器任务的并发。我们知道内核 线程执行在进程上下文中,而定时线程执行在进程上下文中,而定时 器任务属于下半部,执行在中断上器任务属于下半部,执行在中断上 下文中。在这两部分交错执行中进下文中。在这两部分交错执行中进 行保护则需要采用自旋锁。行保护则需要采用自旋锁。 实现机制实现机制 linux内核-第七章 内核中的同步 本例子中使用了本例子中使用了spin_lock_bh()锁锁 在内核线程的执行路径中对链表进在内核线程的执行路径中对链表进 行保护;在下半部中,由于任务队行保护;在下半部中,由于任务队 列是串行执行并且不能被内核任务列是串行执行并且不能被内核任务 或系统调用打断,所以不必加锁。或系统调用打断,所以不必加锁。 另外在卸载模块时,
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年南充科技职业学院单招职业技能测试题库及答案详解一套
- 2026年包头铁道职业技术学院单招职业技能考试题库带答案详解(a卷)
- 花艺环境设计师安全演练测试考核试卷含答案
- 感光材料乳剂熔化工班组管理考核试卷含答案
- 出河机司机复试能力考核试卷含答案
- 合成树脂生产工安全防护强化考核试卷含答案
- 生猪屠宰加工工7S考核试卷含答案
- 珂罗版制版员岗前冲突解决考核试卷含答案
- 妇女职业规划方案
- 乙烯-乙烯醇树脂装置操作工安全宣教水平考核试卷含答案
- 2026辽宁大连长兴岛经济技术开发区国有企业招聘渔港港站管理人员24人笔试备考试题及答案解析
- 项目经理廉洁警示教育
- 《浆体管道输送系统的过程监控与故障诊断》
- 高危儿规范化健康管理专家共识解读
- 农业物资:2024年化肥农药销售合同模板
- 2024年03月深圳市深汕特别合作区机关事业单位2024年公开招考46名事务员笔试历年典型考题及考点研判与答案解析
- 2024北京背户车协议书范本
- 巨量引擎推广引流方案
- 中国美食菜谱大全
- 盘扣架安全施工方案审核要点
- 法律、法规识别与管理制度
评论
0/150
提交评论