原子操作
在C函数中按照特定的方式嵌入汇编代码,实现原子操作就更方便,在代码中加上lock前缀的addl、subl、incl、decl指令都是原子操作,lock前缀表示锁定总线。
所以操作系统在实现单变量的原子操作的时候,是需要添加lock前缀的,原子操作只适用于单体变量。
中断控制
在关闭终端函数中先保存eflags寄存器,然后执行cli指令,在开启中断函数中直接回复之前保存的eflags寄存器就行。
pushfl指令把eflags寄存器压入当前栈顶,popfl将当前栈顶的数据弹入到eflags寄存器中,是否开启终端取决于上一次eflags寄存器中的值, 并且popfl指令只会影响eflags寄存器中的IF位。
这是在单核的情况下。
自旋锁
自旋锁的原理:首先读取锁变量, 判断其值是否已经加锁,如果未加锁则执行加锁,然后返回,表示加锁成功;如果已经加锁,就返回开始继续执行第一步进行后续操作。
自旋锁必须保证读取所变量和判断并加锁的操作是原子执行的。x86 CPU提供了一个原子交换指令,xchg, 它可以让寄存器里的一个值跟内存空间中的一个值做交换。
自旋锁依然有中断嵌套的问题,也就是在使用自旋锁的时候需要注意中断。
信号量
使用信号量的步骤:
- 1获取信号量
- 首先对用于保护信号量自身的自旋锁sem_lock进行加锁
- 对信号量值sem_count执行减1操作,并检查其值是否小于0
- 如果sem_count小于0,就让进程进入等待状态并且将其挂入sem_waitlist中,然后调度其他进程运行。
- 2.代码执行流开始执行相关操作
- 3.释放信号量
- 首先对用于保护信号量自身的自旋锁sem_lock进行加锁
- 对信号量值sem_count执行加1操作,并检查其值是否大于0
- 如果sem_count大于0,执行唤醒sem_waitlist中进程的操作,并且需要调度进程时就执行进程调度操作,不管sem_count的值是什么,都标记信号量释放成功,也要对sem_count进行解锁。
网友评论