一、互斥锁的开销主要在内核态与用户态的切换:
申请锁时,从用户态进入内核态,申请到后从内核态返回用户态(两次切换);没有申请到时阻塞睡眠在内核态。使用完资源后释放锁,从用户态进入内核态,唤醒阻塞等待锁的进程,返回用户态(又两次切换);被唤醒进程在内核态申请到锁,返回用户态(可能其他申请锁的进程又要阻塞)。所以,使用一次锁,包括申请,持有到释放,当前进程要进行四次用户态与内核态的切换。同时,其他竞争锁的进程在这个过程中也要进行一次切换。
进程上下文切换的直接消耗包括CPU寄存器保存和加载,需要调度时有内核调度代码的执行。
二、自旋锁:
与互斥锁不同的是自旋锁不会引起调用者睡眠。如果自旋锁已经被别的进程保持,调用者就轮询(不断的消耗CPU的时间)是否该自旋锁的保持者已经释放了锁("自旋"一词就是因此而得名)。
三、互斥锁、自旋锁的使用场景:
1.由于自旋锁使用者一般保持锁时间非常短,因此选择自旋而不是睡眠,自旋锁的效率远高于互斥锁。
2.自旋锁保持期间是抢占失效的。如果被保护的共享资源需要在中断上下文访问(包括中断上半部和下半部[1]),就必须使用自旋锁。
在ISR中都不能进行进程切换。因为ISR不属于任何进程,而切换只能发生在进程上下文中。虽然ISR在执行过程中要
使用进程的系统堆栈,但那只是借用,堆栈并不属于isr,而是属于进程。 http://www.chinaunix.net/old_jh/4/902033.html
通常32位Linux内核,进程地址空间划分0~3G为用户空间,3~4G为内核空间。内核空间中的内核代码、数据,为所有进程共享,由MMU映射在相同的物理内存地址。
进程进入内核态后,内核代码所使用的栈并不是用户空间中的栈,而是内核空间的栈,进程的“内核栈”。
[1]?怎么理解“中断运行在中断上下文,没有一个所谓的中断描述符来描述它,它不是操作系统调度的单位。一旦在中断上下文中睡眠,首先无法切换上下文(因为没有中断描述符,当前上下文的状态得不到保存),其次,没有人来唤醒它,因为它不是操作系统的调度单位。 ”