问题1: 中断屏蔽为何只对单核有效
在内核中中断屏蔽使用的API为local_irq_disable()和local_irq_enable(),而两者都只能禁止和使能本CPU内的中断,因此并不能解决SMP多CPU引发的静态问题。
其它重要点:
- 并且中断屏蔽的临界区要尽量的小,不能有耗时操作,因为在内核中很多操作都依靠中断来出来,长时间的屏蔽中断,可能会导致内核崩溃。
- 在开发中很少遇到单核的CPU(老师和网友说的)!!!
问题2:在同一个进程如果多次获取同一把锁此时cpu死锁(执行这个代码的cpu)
进程在第一次获取自旋锁的时候能够成功(没有其他进程获取这个自旋锁的时候),在第二次获取自旋锁的时候就会忙等,一直等待自旋锁被释放,此时这个进程没法继续往下执行,自然也执行不到释放锁的代码,所以会产生死锁。
其它重要点:
- 自旋锁是针对多核设计的,对于单核不支持抢占的CPU,自旋锁执行空操作。
- 自旋锁在上锁期间会关闭抢占。任何一个核拿到了自旋锁,该核上的抢占调度也暂时禁止了,但是没有禁止另外一个核的抢占调度。
- 自旋锁持有的时间必须短,也就是临界区要尽可能的短,只有临界区尽可能的短自旋锁的效率才够高,因为自旋是占用CPU资源的。你持有锁的时间越长,另一个进程可能不得不自旋等你释放锁,长时间的持有锁也阻止了当前处理器调度, 意味着高优先级进程 – 真正应当能获得 CPU 的 – 可能不得不等待。
- 自旋锁可以工作在中断上下文,因为中断处理函数中不允许有耗时操作。
- 在自旋锁锁定期间不能调用可能引起进程调度的函数。 如果进程获得自旋锁之后再阻塞, 如调用copy_from_user()、copy_to_user()(拷贝时间太长的话,可以让cpu先执行其它的代码,然后再回来执行拷贝)、kmalloc()和msleep()等函数, 则可能导致内核的崩溃。
问题3:信号量和自旋锁的区别
- 信号量遵循了让权等待原则,在进程无法获得临界资源的时候进程会进入到休眠态;而自旋锁在获取不到临界资源的时候会一直忙等。
- 信号量不会产生死锁,而自旋锁会。
- 信号量保护的临界区可以很大,里面可以有延时、耗时、甚至休眠的操作;而自旋锁保护的临界区要尽可能的小
- 信号量工作在进程上下文(在进程中使用,不能在中断中使用);自旋锁可以在中断上下中使用。
- 信号量上锁的时候是不会关闭抢占的;自旋锁会在上锁后关闭抢占。
问题4:互斥体和信号量的区别
信号量在获取的不到临界资源的时候会直接进入休眠状态,而互斥体会等待一会,再进入休眠。
在进程上下文中,不知道临界区大小的时候,如果需要上锁优先选择互斥体。因为互斥体在获取不到临界资源的时候会稍微等待一会儿,如果要保护的临界区访问时间比较短时,就省去上下文的切换,进程上下文切换的开销也很大,正是因为等待的这个时间,所以临界区比较小的时候互斥体的效率高。
当所要保护的临界区访问时间比较短时, 用自旋锁是非常方便的, 因为它可节省上下文切换的时间。 但是CPU得不到自旋锁会在那里空转直到其他执行单元解锁为止, 所以要求锁不能在临界区里长时间停留, 否则会降低系统的效率。