日期:2014-05-16  浏览次数:20721 次

Linux内核探讨-- 第六章

文是个人分析《Linux内核设计与实现》而写的总结,欢迎转载,请注明出处:

                                                                              http://blog.csdn.net/dlutbrucezhang/article/details/12868723


      第六章--内核同步

      关于同步这个话题,在这里我就不多做介绍了,毕竟,在操作系统和平时写程序时都会考虑这个问题,比如,生产者和消费者问题。
      关于同步,需要介绍的几个主题是:临界区,加锁,死锁。

      1.临界区

      什么是临界区?就是不允许同时执行的那一部分代码,其实这种说法还是有问题的,保持互斥的其实不是那段代码,需要保护的是临界区中的数据修改问题,不能同时执行的那一部分中的数据。这里我就不举例子了,毕竟,这样的东西还是很多的。
      

2.加锁

加锁就是对处于临界区的那段代码加锁,不允许同时访问那段代码。我们可以理解,临界区中的代码是原子执行的,所谓的原子操作,就是,要么这段代码执行且保证不被打断,要么,这么代码根本就不执行。加锁有一些性质将在后面进行介绍。

      3.死锁

死锁就是由于锁的性质引起的进程互相等待且都不释放状态。这种情况的发生是由于进程请求了非递归锁或者是多个进程请求锁时形成了一个请求环。

      说完了这几个比较简单的概念后,下面来介绍内核同步的方法。

      4.自旋锁

      这个是加锁中的一种锁实现方式。从名字我们就可以看出,获取不到锁的进程就只能不停的自旋,直到拥有锁的进程释放了锁才允许其他的进程获取它。自旋锁至多只可以被一个执行线程所拥有,且它是不可递归的。我们想象一种情况,当一个进程获取了自旋锁之后,在临界区中再次请求自旋锁,那么它的动作就是一边自旋等待,一边持有锁,那么这样就导致了死锁,它永远不能释放锁,同时,它也不可能再次得到锁。所以,我们在使用自旋锁时一定不要递归的获得锁。

      5.读写自旋锁

      从名字我们可以知道,这也是一种锁。只是它应用的场合可能是不用于普通自旋锁的。这种锁允许多个读者同时获得锁,同时可以对临界区执行读操作,这里的读操作不对数据进行更改。如果写操作需要执行,那么它需要等待所有的读者都释放了锁之后才能执行,除此之外,它就只能自旋。这种锁的好处是当读者的数目远远多于写者时能获得更高的效率。

      6.信号量

      它是一种睡眠锁。它的原理比较简单,也比较容易使用,且获得的效率也是非常高的。一个进程需要执行临界区中的代码,它就必须要获得信号量,如果此时有其他的进程在使用这个信号量,那么它就会去睡眠,直到使用完信号量的那个进程退出后内核会唤醒睡眠的进程(这里说的是二值信号量)。还有一种信号量是计数信号量,它可以允许多个进程同时进入临界区执行操作,最经典的例子当然是打印机了,加入我们现在有4台打印机,那么信号量的初始值就是4,允许4个进程同时使用打印机,当再有第五个进程需要使用时,它就必须要等待了。

      7.读写信号量

      相应的,对于自旋