JOS大内核锁
2015-11-03 22:29
309 查看
JOSlab4里面,采用了SMT的操作系统,所以可能存在两个CPU同时进入内核态,虽然CPU之间的内核栈,但是多核同步可能还是会出现问题,所以JOS采用大内核锁来锁住整个内核,使得每次只有一个CPU会进入内核,另外的CPU如果申请进入内核态,是进不去的。
首先,看一下内核锁的实现方法:
总共只有三个不同的内容,一个变量,还有就是上锁和解锁。
首先看xchg操作,xchg操作是一个原子操作,它的作用就是交换两个参数,并且返回第一个参数原来的值。
现在看下上锁过程,假设CPU0进入内核,首先要进行上锁操作,
xchg(&lk->locked, 1)
CPU0会执行上面的原子操作,并且返回lk->locked的原来的值,如果原来的值是0,则进入内核,并且内核也被上锁,即lk->locked被赋值为1,当其他CPU要进入的时候,lk->locked一直是1,此时,会执行:
asm volatile (“pause”);
pause指令:
Improves the performance of spin-wait loops. When executing a “spin-wait loop,” a Pentium 4 or Intel Xeon processor suffers a severe performance penalty when exiting the loop because it detects a possible memory order violation. The PAUSE instruction provides a hint to the processor that the code sequence is a spin-wait loop. The processor uses this hint to avoid the memory order violation in most situations, which greatly improves processor performance. For this reason, it is recommended that a PAUSE instruction be placed in all spin-wait loops.
An additional fucntion of the PAUSE instruction is to reduce the power consumed by a Pentium 4 processor while executing a spin loop.
所以,用pause可以让CPU知道接下来的指令是用来自旋等待,就不用做memory reorder了,cache也不用废除了(cache是很宝贵的资源,进程切换的一个重要资源房费就是会导致cache失效,从而导致缓存不命中的问题)。而且附加的功能——减少能耗。
所以用pause就是提醒CPU接下来的指令是自旋等待,什么都不用干,然后CPU一直查询lk->locked的值,直到它的值变为了0,。
2.解锁
解锁就比较简单了,直接把lk->locked变成0就可以了。
所以,总的来说,JOS用了一个简单的自旋锁来当成一个大的内核锁,这里的内核锁实现是用xchg原子操作了实现的。总体来说,这个方法的优点就是实现简单,而且绝对不会出错。缺点也很明显,效率太低了,估计CPU会有很多时间浪费在等待上面。
所以后来的内核的方法,主要采用的是在关键资源上面加锁,而不是在整个内核加锁,这样效率就可以大大的提高,但是相对的实现的难度也加大了。
首先,看一下内核锁的实现方法:
struct spinlock { unsigned locked; }; /***************************************/ spin_lock(struct spinlock *lk) { while (xchg(&lk->locked, 1) != 0) asm volatile ("pause"); } /************************************************/ void spin_unlock(struct spinlock *lk) { xchg(&lk->locked, 0); }
总共只有三个不同的内容,一个变量,还有就是上锁和解锁。
首先看xchg操作,xchg操作是一个原子操作,它的作用就是交换两个参数,并且返回第一个参数原来的值。
现在看下上锁过程,假设CPU0进入内核,首先要进行上锁操作,
xchg(&lk->locked, 1)
CPU0会执行上面的原子操作,并且返回lk->locked的原来的值,如果原来的值是0,则进入内核,并且内核也被上锁,即lk->locked被赋值为1,当其他CPU要进入的时候,lk->locked一直是1,此时,会执行:
asm volatile (“pause”);
pause指令:
Improves the performance of spin-wait loops. When executing a “spin-wait loop,” a Pentium 4 or Intel Xeon processor suffers a severe performance penalty when exiting the loop because it detects a possible memory order violation. The PAUSE instruction provides a hint to the processor that the code sequence is a spin-wait loop. The processor uses this hint to avoid the memory order violation in most situations, which greatly improves processor performance. For this reason, it is recommended that a PAUSE instruction be placed in all spin-wait loops.
An additional fucntion of the PAUSE instruction is to reduce the power consumed by a Pentium 4 processor while executing a spin loop.
所以,用pause可以让CPU知道接下来的指令是用来自旋等待,就不用做memory reorder了,cache也不用废除了(cache是很宝贵的资源,进程切换的一个重要资源房费就是会导致cache失效,从而导致缓存不命中的问题)。而且附加的功能——减少能耗。
所以用pause就是提醒CPU接下来的指令是自旋等待,什么都不用干,然后CPU一直查询lk->locked的值,直到它的值变为了0,。
2.解锁
解锁就比较简单了,直接把lk->locked变成0就可以了。
所以,总的来说,JOS用了一个简单的自旋锁来当成一个大的内核锁,这里的内核锁实现是用xchg原子操作了实现的。总体来说,这个方法的优点就是实现简单,而且绝对不会出错。缺点也很明显,效率太低了,估计CPU会有很多时间浪费在等待上面。
所以后来的内核的方法,主要采用的是在关键资源上面加锁,而不是在整个内核加锁,这样效率就可以大大的提高,但是相对的实现的难度也加大了。
相关文章推荐
- Linux 自检和 SystemTap
- 应用领航:盘点那些年我们一起追过的OS
- 无奇不有!盘点各国自己开发的操作系统
- 可自定义oem的萝卜家园 Ghost XP 新春装机版 V200801 下载
- C#实现判断操作系统是否为Win8以上版本
- Linux操作系统添加新硬盘方法
- Linux内核链表实现过程
- java如何获取本地操作系统进程列表
- Linux rdesktop操作系统下远程登录Windows XP桌面
- 32位操作系统认出超出4G内存的方法
- Linux rpm tar 操作系统下软件的安装与卸载方法
- JavaScript 获取用户客户端操作系统版本
- jsp 获取客户端的浏览器和操作系统信息
- Windows 操作系统的安全设置
- php判断当前操作系统类型
- PHP获取用户的浏览器与操作系统信息的代码
- Perl操作系统环境变量的脚本代码
- javascript获取本机操作系统类型的方法
- 封装好的js判断操作系统与浏览器代码分享
- javascript实现获取浏览器版本、操作系统类型