我正在运行2个线程(假设它们暂时是pthreads)。 Thread_1()进行用户定义的API调用,最终在内核中完成一些工作。 Thread_2()完全在用户空间中。
我的问题是:在API调用正在进行时,Thread_2()可以通过抢占Thread_1()来开始执行,控件是在内核中的某个地方吗?如果不是,为什么,如果我希望这种情况发生(出于任何原因),我该怎么办?
答案 0 :(得分:8)
对内核的调用被认为是阻止或非阻塞。阻止调用(例如等待数据从网络套接字读取)当然可以被抢占,而您无需执行任何操作。其他线程将继续运行。非阻塞内核调用可以被认为是非常快的,实际上,如果你实际上可以抢占它们并不重要。
通常,在编写多线程代码时,您要专注于这些线程如何相互交互,并将它们与内核的交互留给内核进行管理。它旨在做得很好。
答案 1 :(得分:7)
这取决于内核。经典内核不允许抢占(除非在睡眠线程时的特定点)。但是更新的内核已经开始在内核中启用抢占。
Linux支持使用CONFIG_PREEMPT构建的可抢占内核。从内核文档:
此选项通过制作来减少内核的延迟 所有内核代码(不在关键部分执行) 抢占。这样就可以对交互事件做出反应 允许低优先级进程被非自愿地抢占 即使它在内核模式下执行系统调用也会 否则不会达到自然的先发制人点。 这样即使在应用程序运行时,应用程序也可以更加“顺畅 系统负载不足,但吞吐量略低 并且内核代码的运行时开销很小。
如果要为桌面或内容构建内核,请选择此选项 具有延迟要求的嵌入式系统,以毫秒为单位 范围。
答案 2 :(得分:5)
如果您询问是否可以抢占阻塞内核调用,如fread()
需要磁盘IO,那么是。
更具体地说,阻塞调用基本上会让Thread_1在等待它等待的任何东西时进入休眠状态。如果Thread_1处于休眠状态,那么Thread_2将被安排运行(除非有更高优先级等待运行)。
编辑:如果你想要一种“相当自信”Thread_1正在执行阻塞调用的方法,那么使Thread_2的优先级低于Thread_1(这样它通常不会 run除非Thread_1被阻止)并且当它运行时,它将其优先级提升到比Thread_1更高的级别,直到硬件中断被传递,此时它降低其优先级并调用sched_yield()
。