当前位置: 技术问答>linux和unix
为什么对task->falgs的访问不加锁
来源: 互联网 发布时间:2015-11-30
本文导语: 在do_exit(),下面的一句没有任何锁保护。 tsk->flags |= PF_EXITING; 这样其他的进程检查flags的时候岂不是会造成race condition?请高手解惑。 | 1.多CPU竞争条件:由于在LINUX内核中,多CPU情况下,内核...
在do_exit(),下面的一句没有任何锁保护。
tsk->flags |= PF_EXITING;
这样其他的进程检查flags的时候岂不是会造成race condition?请高手解惑。
tsk->flags |= PF_EXITING;
这样其他的进程检查flags的时候岂不是会造成race condition?请高手解惑。
|
1.多CPU竞争条件:由于在LINUX内核中,多CPU情况下,内核会保证一个进程绝不会同时被多个CPU调度,这是由内核方面的进程调度算法来保证的,具体参见LINUX内核设计与实现一书
2.单CPU竞争条件:如果在执行这条语句过程中,突然发生中断,引起重新调度,由于进程调度时是以PCB为单位的,do_exit是由EXIT信号来产生的(也可以是系统调用,最终都是一个exit系统调用),只要保证这个函数不重入,当然就不用锁保护了!!!如果由信号产生,内核对信号的处理本身就是不重入的.如果是由系统调用产生,一个进程发出exit系统调用时,本身都还没返回用户态,所以当它重新被调度时,就不可能再次产生exit系统调用!!!现在你可能会说多线程的情况,前面说过了,LINUX的调度是以PCB为单位的,而多线程是多个PCB的,所以同样不会产生几个线程同时访问一个PCB的结构相应标志的,而在一个辅助线程中写上一句exit时,我想内核应该会设置主线程的一个exit信号(这是我猜测的,你可以去看一下内核中相关处理),从而让主线程得到执行时去处理exit信号,从而设置这个PCB中的相应标识,从而也不会产生竞争条件
3.在进程调度时,会检测所有的PCB,此时存在的竞争:当执行此条语句时,被中断,重新调度,在老版本的进程调度模块,会检测所有的PCB的状态,如果发现此状态还是在RUN,并且此优先级最高,退出中断,继续执行未完的语句,这本身就不会产生竞争,如果计算出此优先级不是最高,退出中断,调度其它进程,也不会出现冲突,再者,老版本的内核不支持内核态抢占,根本就不存在这种情况了.如果是2.6的内核,更加不会出现这种情况,因为在2.6中,进程调度算法进行了优化处理,进程调度时间是常量,也就是在调度时,根本不会去遍历所有的PCB,具体算法参见LINUX内核设计与实现一书
4.在内核驱动模块中存在的竞争:如果你在一个驱动模块中非得要去访问其它PCB结构,那么你的代码一定要保证你对其它PCB模块的访问一定要存在原子性,在多CPU中一定要锁总线,在单CPU中,一定要保证你的代码不会被中断,这是你自己对代码的控制,如果你控制不了这一点,就是你设计的问题了,不光是这里的代码会出现问题,假定你要访问其它进程的资源,你在访问时又不能保证原子性时当你刚好访问到一半时,中断发生,进程切换,刚好你要访问的进程退出了,PCB被回收,然后又切换到你的代码,此时就出问题了!!!!如果你能保证原子性,一切都不会发生,这里的代码被中断,你的代码得到执行,在执行的过程中你保证不会发生任何切换,那么还有什么竞争条件存在呢??????
2.单CPU竞争条件:如果在执行这条语句过程中,突然发生中断,引起重新调度,由于进程调度时是以PCB为单位的,do_exit是由EXIT信号来产生的(也可以是系统调用,最终都是一个exit系统调用),只要保证这个函数不重入,当然就不用锁保护了!!!如果由信号产生,内核对信号的处理本身就是不重入的.如果是由系统调用产生,一个进程发出exit系统调用时,本身都还没返回用户态,所以当它重新被调度时,就不可能再次产生exit系统调用!!!现在你可能会说多线程的情况,前面说过了,LINUX的调度是以PCB为单位的,而多线程是多个PCB的,所以同样不会产生几个线程同时访问一个PCB的结构相应标志的,而在一个辅助线程中写上一句exit时,我想内核应该会设置主线程的一个exit信号(这是我猜测的,你可以去看一下内核中相关处理),从而让主线程得到执行时去处理exit信号,从而设置这个PCB中的相应标识,从而也不会产生竞争条件
3.在进程调度时,会检测所有的PCB,此时存在的竞争:当执行此条语句时,被中断,重新调度,在老版本的进程调度模块,会检测所有的PCB的状态,如果发现此状态还是在RUN,并且此优先级最高,退出中断,继续执行未完的语句,这本身就不会产生竞争,如果计算出此优先级不是最高,退出中断,调度其它进程,也不会出现冲突,再者,老版本的内核不支持内核态抢占,根本就不存在这种情况了.如果是2.6的内核,更加不会出现这种情况,因为在2.6中,进程调度算法进行了优化处理,进程调度时间是常量,也就是在调度时,根本不会去遍历所有的PCB,具体算法参见LINUX内核设计与实现一书
4.在内核驱动模块中存在的竞争:如果你在一个驱动模块中非得要去访问其它PCB结构,那么你的代码一定要保证你对其它PCB模块的访问一定要存在原子性,在多CPU中一定要锁总线,在单CPU中,一定要保证你的代码不会被中断,这是你自己对代码的控制,如果你控制不了这一点,就是你设计的问题了,不光是这里的代码会出现问题,假定你要访问其它进程的资源,你在访问时又不能保证原子性时当你刚好访问到一半时,中断发生,进程切换,刚好你要访问的进程退出了,PCB被回收,然后又切换到你的代码,此时就出问题了!!!!如果你能保证原子性,一切都不会发生,这里的代码被中断,你的代码得到执行,在执行的过程中你保证不会发生任何切换,那么还有什么竞争条件存在呢??????
|
read_lock(&tasklist_lock);禁止了写操作!
|
对于LZ的这种对技术的狂热追求精神,赞一个!!!
您可能感兴趣的文章:
本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。
本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。