第二章1.信号量及各种锁_第1页
第二章1.信号量及各种锁_第2页
第二章1.信号量及各种锁_第3页
第二章1.信号量及各种锁_第4页
第二章1.信号量及各种锁_第5页
已阅读5页,还剩24页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、Neusoft Institute of InformationDate: 9 3 2010IT Education & TrainingNeusoft Institute of Information电子工程系-嵌入式嵌入式LinuxLinux驱动设备开发驱动设备开发Neusoft Institute of InformationDate: 9 3 2010IT Education & Training目录并发与竞态并发与竞态自旋锁、读写锁原子操作、等待队列信号量Neusoft Institute of InformationDate: 9 3 2010IT Education & Trai

2、ning并发和它的管理并发和它的管理 Linux 系统的并发源:多个用户空间进程在运行,它们可能以令人惊讶的方式组合运行你的代码.SMP系统能够同时在不同处理器上执行你的代码.内核代码是可抢占的;你的驱动代码可能在任何时间失去处理器,代替它的进程可能也在你的驱动中运行.设备中断是能够导致你的代码并发执行的异步事件.内核也提供各种延迟代码执行的机制, 例如 workqueue,tasklet,定时器.这些能够使你的代码在任何时间以一种与当前进程在做的事情无关的方式运行. Neusoft Institute of InformationDate: 9 3 2010IT Education & Tr

3、aining任何时候一个硬件或软件资源被超出一个单个执行线程共享,并且可能存在一个线程看到那个资源的不一致时,你必须明确地管理对那个资源的存取. 当内核代码创建一个会被内核其他部分共享的对象时, 这个对象必须一直存在(并且功能正常)到它知道没有对它的外部引用存在为止.在大部分情况下, 你将发现内核为你处理引用计数, 但是常常有例外. Neusoft Institute of InformationDate: 9 3 2010IT Education & Training信号量: 是一个单个整型值, 结合有一对函数, 典型地称为 P 和 V. 一个想进入临界区的进程将在相关信号量上调用 P; 如

4、果信号量的值大于零, 这个值递减 1 并且进程继续. 相反, 如果信号量的值是 0 ( 或更小 ), 进程必须等待(睡眠)直到别人释放信号量. 解锁一个信号量通过调用 V 完成; 这个函数递增信号量的值, 并且, 如果需要, 唤醒等待的进程. Neusoft Institute of InformationDate: 9 3 2010IT Education & Training互斥: 阻止多个进程同时在同一个临界区内运行 - 它们的值将初始化为 1. 这样的信号量在任何给定时间只能由一个单个进程或者线程持有. 以这种模式使用的信号量有时称为一个互斥锁. 几乎所有在 Linux 内核中发现的信

5、号量都用作互斥. 建立临界区: 在任何给定时间只有一个线程可以执行代码. Neusoft Institute of InformationDate: 9 3 2010IT Education & Training信号量信号量 信号量在创建时需要设置一个信号量在创建时需要设置一个初始值初始值,表示允许,表示允许有有几个任务几个任务同时访问该信号量保护的共享资源,同时访问该信号量保护的共享资源,初始值为初始值为1 1就变成就变成互斥锁互斥锁(MutexMutex),即同时只能),即同时只能有一个任务可以访问信号量保护的共享资源。有一个任务可以访问信号量保护的共享资源。2.2.当任务访问完被信号量保

6、护的共享资源后,必须当任务访问完被信号量保护的共享资源后,必须释放信号量释放信号量,释放信号量通过把信号量的值加,释放信号量通过把信号量的值加1 1实实现,如果释放后信号量的值为非正数,表明有任现,如果释放后信号量的值为非正数,表明有任务等待当前信号量,因此要唤醒等待该信号量的务等待当前信号量,因此要唤醒等待该信号量的任务。任务。Neusoft Institute of InformationDate: 9 3 2010IT Education & Training信号量的实现也是与体系结构相关的,定义在信号量的实现也是与体系结构相关的,定义在中,中,struct semaphorestruc

7、t semaphore类型用来类型用来表示信号量。表示信号量。1. 1. 定义信号量定义信号量struct struct semaphoresemaphore sem; sem;2. 2. 初始化信号量初始化信号量void void sema_initsema_init (struct semaphore (struct semaphore * *sem, int val)sem, int val)该函数用于初始化设置信号量的初值,它设置信号量该函数用于初始化设置信号量的初值,它设置信号量semsem的值为的值为valval。信号量信号量Neusoft Institute of Informa

8、tionDate: 9 3 2010IT Education & Training信号量信号量void void init_MUTEX init_MUTEX (struct semaphore (struct semaphore * *sem)sem)该函数用于初始化一个互斥锁,即它把信号量该函数用于初始化一个互斥锁,即它把信号量semsem的值设置为的值设置为1 1。void void init_MUTEX_LOCKEDinit_MUTEX_LOCKED (struct semaphore (struct semaphore * *sem)sem)该函数也用于初始化一个互斥锁,但它把信号量该

9、函数也用于初始化一个互斥锁,但它把信号量semsem的值设置为的值设置为0 0,即一开始就处在已锁状态。,即一开始就处在已锁状态。Neusoft Institute of InformationDate: 9 3 2010IT Education & Training定义与初始化的工作可由如下宏一步完成:定义与初始化的工作可由如下宏一步完成:DECLARE_MUTEXDECLARE_MUTEX(name)(name)定义一个信号量定义一个信号量namename,并初始化它的值为,并初始化它的值为1 1。DECLARE_MUTEX_LOCKEDDECLARE_MUTEX_LOCKED(name)

10、(name)定义一个信号量定义一个信号量namename,但把它的初始值设置,但把它的初始值设置为为0 0,即锁在创建时就处在已锁状态。,即锁在创建时就处在已锁状态。信号量信号量Neusoft Institute of InformationDate: 9 3 2010IT Education & Training信号量信号量获取信号量获取信号量void void downdown(struct semaphore (struct semaphore * * sem) sem)获取信号量获取信号量semsem,可能会导致进程睡眠,因此,可能会导致进程睡眠,因此不能在中断上下文使用该函数。该函数

11、将把不能在中断上下文使用该函数。该函数将把semsem的值减的值减1 1,如果信号量,如果信号量semsem的值非负,就直的值非负,就直接返回,否则调用者将被挂起,直到别的任务接返回,否则调用者将被挂起,直到别的任务释放该信号量才能继续运行。释放该信号量才能继续运行。Neusoft Institute of InformationDate: 9 3 2010IT Education & Trainingint int down_interruptibledown_interruptible(struct semaphore (struct semaphore * * sem)sem)获取信号量

12、获取信号量semsem。如果信号量不可用,进程将被。如果信号量不可用,进程将被置为置为TASK_INTERRUPTIBLETASK_INTERRUPTIBLE类型的睡眠状态。类型的睡眠状态。该函数由返回值来区分是正常返回还是被信号该函数由返回值来区分是正常返回还是被信号中断返回,如果返回中断返回,如果返回0 0,表示获得信号量正常返,表示获得信号量正常返回,如果被信号打断,返回回,如果被信号打断,返回-EINTR-EINTR。信号量信号量Neusoft Institute of InformationDate: 9 3 2010IT Education & Training信号量信号量down

13、_killabledown_killable(struct semaphore (struct semaphore * *sem)sem)获取信号量获取信号量semsem。如果信号量不可用,进程。如果信号量不可用,进程将被置为将被置为TASK_KILLABLETASK_KILLABLE类型的睡眠状态。类型的睡眠状态。注:注:down()down()函数现已不建议继续使用。函数现已不建议继续使用。建议使用建议使用down_killable() down_killable() 或或down_interruptible() down_interruptible() 函数。函数。Neusoft Ins

14、titute of InformationDate: 9 3 2010IT Education & Training信号量信号量释放信号量释放信号量void void upup(struct semaphore (struct semaphore * * sem) sem)该函数释放信号量该函数释放信号量semsem,即把,即把semsem的值加的值加1 1,如果如果semsem的值为非正数,表明有任务等待该的值为非正数,表明有任务等待该信号量,因此唤醒这些等待者。信号量,因此唤醒这些等待者。Neusoft Institute of InformationDate: 9 3 2010IT Ed

15、ucation & Training自旋锁自旋锁自旋锁最多只能被一个可执行单元持有。自旋锁最多只能被一个可执行单元持有。自旋锁不会引起调用者睡眠,如果一个执自旋锁不会引起调用者睡眠,如果一个执行线程试图获得一个已经被持有的自旋锁,行线程试图获得一个已经被持有的自旋锁,那么线程就会一直进行忙循环,一直等待那么线程就会一直进行忙循环,一直等待下去,在那里看是否该自旋锁的保持者已下去,在那里看是否该自旋锁的保持者已经释放了锁,经释放了锁,“自旋自旋”就是这个意思。就是这个意思。Neusoft Institute of InformationDate: 9 3 2010IT Education & T

16、raining自旋锁自旋锁spin_lock_initspin_lock_init(x)(x)该宏用于初始化自旋锁该宏用于初始化自旋锁x x,自旋锁在使用前,自旋锁在使用前必须先初始化。必须先初始化。spin_lockspin_lock(lock)(lock)获取自旋锁获取自旋锁locklock,如果成功,立即获得锁,如果成功,立即获得锁,并马上返回,否则它将一直自旋在那里,直并马上返回,否则它将一直自旋在那里,直到该自旋锁的保持者释放。到该自旋锁的保持者释放。Neusoft Institute of InformationDate: 9 3 2010IT Education & Traini

17、ng自旋锁自旋锁spin_trylockspin_trylock(lock)(lock)试图获取自旋锁试图获取自旋锁locklock,如果能立即获得锁,如果能立即获得锁,并返回真,否则立即返回假。它不会一直等并返回真,否则立即返回假。它不会一直等待被释放。待被释放。spin_unlockspin_unlock(lock)(lock)释放自旋锁释放自旋锁locklock,它与,它与spin_trylockspin_trylock或或spin_lockspin_lock配对使用。配对使用。Neusoft Institute of InformationDate: 9 3 2010IT Educat

18、ion & Training信号量与自旋锁的使用场合信号量可能允许有信号量可能允许有多个持有者多个持有者,而自旋锁在任何时候只,而自旋锁在任何时候只能允许能允许一个持有者一个持有者。当然也有信号量叫互斥信号量。当然也有信号量叫互斥信号量( (只只能一个持有者能一个持有者) ),允许有多个持有者的信号量叫计数信,允许有多个持有者的信号量叫计数信号量。号量。信号量信号量适合于适合于保持时间较长保持时间较长的情况;而的情况;而自旋锁自旋锁适合于适合于保保持时间非常短持时间非常短的情况,在实际应用中自旋锁控制的代码的情况,在实际应用中自旋锁控制的代码只有几行,而持有自旋锁的时间也一般不会超过两次上只有

19、几行,而持有自旋锁的时间也一般不会超过两次上下文切换的时间,因为线程一旦要进行切换,就至少花下文切换的时间,因为线程一旦要进行切换,就至少花费切出切入两次,自旋锁的占用时间如果远远长于两次费切出切入两次,自旋锁的占用时间如果远远长于两次上下文切换,我们就应该选择信号量。上下文切换,我们就应该选择信号量。Neusoft Institute of InformationDate: 9 3 2010IT Education & Training rwlock_t类型, 在 中定义 初始化方法:rwlock_t my_rwlock = RW_LOCK_UNLOCKED; /* Static way *

20、/ rwlock_t my_rwlock; rwlock_init(&my_rwlock); /* Dynamic way */n 允许多个读进程同时进入临界区;n 写进程必须互斥访问临界区。 读写锁Neusoft Institute of InformationDate: 9 3 2010IT Education & Training加锁顺序规则 获得多个锁可能是危险的 :Lock1 和 Lock2, 代码需要同时都获取, 你有一个潜在的死锁. 仅仅想象一个线程锁住 Lock1 而另一个同时获得 Lock2. 接着每个线程试图得到它没有的那个. 2 个线程都会死锁. 当多个锁必须获得时, 它

21、们应当一直以同样顺序获得. 以相反的顺序释放。Neusoft Institute of InformationDate: 9 3 2010IT Education & Training原子变量 对共享变量 n_opn_op+; 都可能需要加锁。内核提供了一个原子整数类型称为 atomic_t 下面的操作为这个类型定义并且保证对于一个 SMP 计算机的所有处理器来说是原子的。因为它被编译成一条单个机器指令 void atomic_set(atomic_t *v, int i); atomic_t v = ATOMIC_INIT(0); Neusoft Institute of Informati

22、onDate: 9 3 2010IT Education & Training原子变量 void atomic_add(int i, atomic_t *v);void atomic_sub(int i, atomic_t *v); void atomic_inc(atomic_t *v); void atomic_dec(atomic_t *v); int atomic_inc_and_test(atomic_t *v); int atomic_dec_and_test(atomic_t *v); int atomic_sub_and_test(int i, atomic_t *v); vo

23、id set_bit(nr, void *addr); void clear_bit(nr, void *addr); Neusoft Institute of InformationDate: 9 3 2010IT Education & Training等待队列等待队列在Linux驱动程序设计中,可以使用等待队列来实现进程的阻塞,等待队列可看作保存进程的容器,在阻塞进程时,将进程放入等待队列,当唤醒进程时, 从等待队列中取出进程。Neusoft Institute of InformationDate: 9 3 2010IT Education & TrainingLinux 2.6内核提

24、供了如下关于等待队列的操作:1、定义等待队列wait_queue_head_t my_queue2、初始化等待队列init_waitqueue_head(&my_queue)3、定义并初始化等待队列DECLARE_WAIT_QUEUE_HEAD(my_queue)等待队列等待队列Neusoft Institute of InformationDate: 9 3 2010IT Education & Training4 4、有条件睡眠、有条件睡眠wait_event(queue,condition)wait_event(queue,condition) 当当condition(condition

25、(一个布尔表达式一个布尔表达式) )为真时,立即返回;否为真时,立即返回;否则让进程进入则让进程进入TASK_UNINTERRUPTIBLETASK_UNINTERRUPTIBLE模式的睡眠,并挂模式的睡眠,并挂在在queuequeue参数所指定的等待队列上。参数所指定的等待队列上。wait_event_interruptible(queue,condition)wait_event_interruptible(queue,condition) 当当condition(condition(一个布尔表达式一个布尔表达式) )为真时,立即返回;否为真时,立即返回;否则让进程进入则让进程进入TASK

26、_INTERRUPTIBLETASK_INTERRUPTIBLE的睡眠,并挂在的睡眠,并挂在queuequeue参数所指定的等待队列上。参数所指定的等待队列上。等待队列等待队列Neusoft Institute of InformationDate: 9 3 2010IT Education & Trainingint wait_event_killable(wait_queue_t queue, condition) 当当condition(一个布尔表达式一个布尔表达式)为真时,为真时,立即返回;否则让进程进入立即返回;否则让进程进入TASK_KILLABLE的睡眠,并挂在的睡眠,并挂在queue参数所指定的等待队列上。参数所指定的等待队列上。等待队列等待队列Ne

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论