Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1570467
  • 博文数量: 77
  • 博客积分: 1205
  • 博客等级: 少尉
  • 技术积分: 4476
  • 用 户 组: 普通用户
  • 注册时间: 2010-04-22 21:48
文章分类
文章存档

2018年(1)

2017年(1)

2015年(1)

2014年(18)

2013年(12)

2012年(44)

分类: LINUX

2012-10-09 13:21:41

前阵子有网友发短消息问:“...在研究自旋锁的时候,发现在 spin_lock_irq函数,也就是在自旋锁中关闭中的这类函数中,既然已经关闭了本地中断,再禁止抢占有没有多余。也就是说,既然本地中断已经禁止 了,在本处理器上是无法被打断的,本地调度器也无法运行,也就不可以被本地调度程序调度出去..."

从spinlock设计原理看,使用它的时候,在临界区间是务必确保不会发生进程切换。现在的问题是,如果已经关闭了中断,在同一处理器上如果不关掉内核抢占的特性,会不会有进程调度的情况发生,如果没有,那我个人的理解是,在local_irq_disable之后再使用peempt_disable就多此一举了。

这个在SMP系统上最好理解了,假设有A和B两个处理器,使用spin lock的进程(简称"焦点进程"好了)运行在处理器A上,一种很明显的情形就是如果有个进程(简称“睡眠进程”好了)先于焦点运行,但是因为等待网卡的一个数据包,它进入了sleep状态,然后焦点开始被调度运行,后者在spin lock获得锁后进入临界区,此时网卡收到了"睡眠进程“的数据包,因为焦点只是关闭了A上的中断,所以B还是会接收并处理该中断,然后唤醒“睡眠进程“,后者进入运行队列,此时出现一个调度点,如果”睡眠“的优先级高于”焦点“,那么就有进程切换发生了,但是如果焦点所使用的spin lock中关闭了内核抢占,那么就使得先前的进程切换成为不可能。

如果是在单处理器系统上,local_irq_disable实际上关闭了所有(其实就一个)处理器的中断,所有有中断引起的调度点都不可能存在,此时有无其他与中断无关的调度点出现呢?在2.4上,因为没有抢占,这种情形绝无可能,事实上,早期的内核很大程度上是依赖local_irq_disable来做资源保护,这个看看2.4的内核源码就很清楚了,里面有大量的对local_irq_disable函数的直接调用。2.6有了抢占的概念,UP下关闭中断,如前所述,实际上已经杜绝了内部因素导致的“就绪队列中加入一个进程”这个调度点的可能(内部因素实际上只剩下了一个处理器的异常,但是关中断的情形下,即便有异常也不会导致进程的切换),因此到这里我们可以这样说,在UP上关闭中断情形下,preempt_disable其实是多余的。但是我们知道,spin lock是一种内核API,不只是kernel的开发者在用,更多的内核模块(.ko,实际当中更多地表现形式是设备驱动程序)开发者也在使用。内核的设计者总是试图将其不能控的代码(所谓的外部因素了)可能给内核带来的损失降低至最小的程度,这个表现在内核对中断处理框架的设计时尤其明显,所以在UP系统下先后使用local_disable_irq和preempt_disable,只是尽量让你我可能在spin lock/unlock的临界区中某些混了头的代码不至于给系统带来灾难,因为难保某些人不会在spin lock的临界区中,比如去wake_up_interruptible()一个进程,而被唤醒的进程在可抢占的系统里就是一个打开的潘多拉盒子。



阅读(13117) | 评论(17) | 转发(11) |
给主人留下些什么吧!~~

lmnos2012-10-11 20:31:47

MagicBoy2010: 这个可以参考现在内核代码中中断处理框架中防止中断栈溢出的方法,相对中断嵌套导致的中断栈溢出,普通进程的内核态堆栈溢出概率极低.....
但确实没有什么硬性措施,如果这种情况一旦发生的化,那将是灾难性的后果。在进程的用户态下,只要控制好映射用户态堆栈的页表,就可以硬性的扩充用户态堆栈的大小或者检测用户态堆栈是否溢出。但是内核态堆栈则无法这样做,只能靠内核开发者良好的编程行为,我不知道,我在一内核模块的函数中写这样的语句,比如
knrl_mode()
{
    ......
     char buf[8192];
    ......
}
会产生什么情况。

MagicBoy20102012-10-11 20:10:50

tekkamanninja: 我也不太确定,所以请教下陈老师~~~~~
RTFSCing~~~.....
可以看看最新的代码,ret_from_exception中在中断关闭的情形下如何处理。我个人觉得异常在发生时和进程关系密切,比如缺页异常,没有理由在这种情形下做一次进程切换,但是这个还是仔细看看内核代码比较稳妥,应该是在arch/x86/kernel/entry.s中。。。

MagicBoy20102012-10-11 20:08:26

lmnos: 既然说到异常,我也有个问题想请教陈老师,x86下,一个进程的内核态堆栈溢出的化,怎么办,有什么办法可以检测,如果检测到该怎么办,这个问题我一直都没想明白.....
这个可以参考现在内核代码中中断处理框架中防止中断栈溢出的方法,相对中断嵌套导致的中断栈溢出,普通进程的内核态堆栈溢出概率极低

lmnos2012-10-11 17:30:10

tekkamanninja: 我也不太确定,所以请教下陈老师~~~~~
RTFSCing~~~.....
既然说到异常,我也有个问题想请教陈老师,x86下,一个进程的内核态堆栈溢出的化,怎么办,有什么办法可以检测,如果检测到该怎么办,这个问题我一直都没想明白。谢谢了

tekkamanninja2012-10-11 17:15:59

lmnos: ARM我不是很了解,x86的情况下,内核态的代码,能产生异常吗,处理异常应该不会发生调度吧,我也不太了解。.....
我也不太确定,所以请教下陈老师~~~~~
RTFSCing~~~