OS-李治军-L18-信号量的代码实现
信号量的代码实现
申请信号量,这个在内核中实现,因为信号量中具有pcb。
每个信号量具有唯一的标识,内核根据标识在信号量表中查询信号量。
这里用开关中断来保证原子性。
具体逻辑是,在做相关操作之前,调用wait函数,判断当前信号量的值,判断自己是否要进入等待队列,如果要就schedule。
如果不要,或者schedule后有信号量了而且轮到当前进程工作的时候,就会进一步向下执行

Linux早期版本内读磁盘的工作:

这里使用b_lock作为信号量,其值为1的时候表示被占用,需要将当前进程睡眠。
但是这里使用的居然是while?
故事要从sleep_on开始讲起

前两句有一个非常隐蔽的队列:

当前进程要进入sleep,并且成为阻塞队列的队首,于是将指向队首的指针p设置为指向当前进程。
而tmp指向了前面的队首,即当前队首后面一个pcb。
注意到tmp是存放在内核栈中的,每当发生进程切换的时候,内核栈会发生变化,于是tmp的值也发生了变化。
于是如果要进行队列的pop,就让p的值为tmp即可。
这相当于是,队列的每个元素是当前进程,而其next指针就是tmp。
最后这里总体的逻辑是:
- 当前进程作为新的阻塞队首,其next是前一个队首进程。
- 将当前进程的状态设置为阻塞。
- schedule
- 唤醒下一个进程
唤醒工作:

唤醒由中断来执行,最后会执行unlock_buffer,其先将信号量释放,然后执行wake_up。
wake_up接收队首指针,将队首的状态设置为0,即就绪态。当队首进程被调度的时候,就会回到当时中断的地方,即schedule的下一句,执行其后面两句话,此时tmp指向下一个进程,将其状态设置为就绪态,这样递推下去,就会将阻塞队列全部唤醒。
如果采用if的方法,就是FIFO。
这里采用大家一起醒,然后由cpu调度算法决定高优先级的人先执行,当高优先级的进程执行的时候,又会锁上资源,所以这里要采用while的方法,一直等待,然后被唤醒,又等待,直到优先级足够高被cpu调度算法pick了,才上。

浙公网安备 33010602011771号