问题 防止linux线程被调度程序中断


你如何告诉linux中的线程调度程序不会因任何原因中断你的线程?我在用户模式下编程。简单地锁定互斥锁是否可以实现这一点?我希望防止在执行某个函数时调度进程中的其他线程。他们会阻止,我会浪费cpu周期与上下文切换。我希望执行该函数的任何线程能够在不中断的情况下完成执行,即使超出了线程的时间片。


3193
2018-04-07 20:36


起源

嗨,谢谢你的所有评论。我想我学到了答案,这是不对的。我问的原因是:我们的应用程序在IO等待状态中花费了大量时间,因为它访问每小时更改500 GB的数据文件。我想使用大量线程来执行并行IO(是的,文件管理器可以处理它......他们已经处理了来自3200个app实例的IO,这不是为了处理更多工作,而是为了缩短时间)。我们的盒子都是带有8-64“CPU”的MP,计算实际内核和超线程...所以我可以同时运行很多线程。 - johnnycrash
Parallell IO通常会降低性能,可能相当可观。驱动器无法并行处理(超出某个点,具体取决于您的raid设置)。如果您想要最大限度地提高性能,您需要一些IO线程向工作线程提供(尽可能大的)数据。 - leeeroy
看看aio.h.异步输入输出@leeeroy Parallell IO可以获胜,因为它允许块设备调度程序实际上有事情要安排并更好地利用磁盘读/写磁头的扫描。 Plus驱动器有自己的缓存并进行自己的调度。无论哪种方式,AIO也应该获得好处。 - nategoose


答案:


你如何告诉linux中的线程调度程序不会因任何原因中断你的线程?

无法真正完成,你需要一个实时系统。你将获得关于linux的关闭的事情是 将调度策略设置为实时调度器,例如, SCHED_FIFO,还设置了PTHREAD_EXPLICIT_SCHED属性。参见例如 这里 ,即使是现在,例如, irq处理程序和其他东西会中断你的线程并运行。

但是,如果您只关心自己进程中的线程无法执行任何操作,那么是的,让它们阻塞正在运行的线程保持的互斥锁就足够了。

困难的部分是协调所有其他线程,以便在线程需要执行其操作时获取该互斥锁。


8
2018-04-07 21:02



基本上它是一堆工作线程和工作队列。现在我几乎没有锁定,因为我准备工作然后解雇线程。对于阶段2,我希望通过让线程在队列中添加更多工作来增加并列性。为此,线程必须检查公共数据存储以查看数据是否存在。非抗性数据=队列的工作。正是这个函数检查了我担心会被访问的公共数据存储。我想我只需要制作一个绝对需要通过重写来锁定额外小的部分。 - johnnycrash
我一直在用这个 asgaard.homelinux.org/svn/threadqueue 做类似的事情。你解雇了没有。你想要的工作线程,并通过线程提供它们,阻塞和等待,直到数据添加到队列。如果你没有比你有核心更多的工作线程,它们之间的争用应该是最小的。 - nos


你应该构建你的sw,这样你就可以了  依赖于调度程序从您的应用程序的角度做“正确”的事情。调度程序很复杂。它会做它认为最好的事情。

上下文切换很便宜。你说

我会浪费带有上下文切换的cpu周期。

但你不应该这样看待它。使用互斥锁和阻塞/等待进程的多线程机制。机器在那里供你使用......


2
2018-04-07 20:45



是的,我同意。我不想重新发明轮子。我只是想知道如何最大限度地利用车轮。我在某地读到,互斥锁可以锁定并解锁,每秒数千次。这太慢了我所需要的。你是正确的架构。不幸的是,我有20年的旧代码,所以我的第一个计划是尝试一些只需要很少改变的东西。因此有关先发制人的问题。此外,它使用了很多memmap。我的猜测是memmap在4k块调用malloc。我可能有64个同时的memmaps正在进行所有想要malloc 50次。 - johnnycrash
好吧,mmap不会调用malloc,它会在内核中的内存页面中出错。还有,几千/秒太慢了?无争用地锁定/解锁互斥锁可以以数百万/秒的顺序进行,当存在争用并且线程必须阻塞时,它会变慢。 - nos
@Larry K你能不能支持“上下文切换便宜”的说法? - Bacon


你不能。如果你能阻止你的线程永远不会释放请求和饿死其他线程。

您可以做的最好的事情是设置线程优先级,以便调度程序优先于优先级较低的线程。


1
2018-04-07 20:40



荡。线程优先级是一个问题,除非我在进入函数时可以更改它,然后在退出时降低。而且,就周期而言,这会花费多少。工作线程是我担心的,并且会有很多。 - johnnycrash


为什么不简单地让竞争线程阻塞,那么调度程序将没有任何东西可以安排,但你的生活线程?为什么复杂的设计第二次猜测调度程序?


1
2018-04-07 20:42



好吧,我想,如果线程A将一个资源锁定在线程A的时间片的末尾,那么它就可以被抢占。然后调度程序将循环遍历所有其他工作线程,假设有50个。由于此函数极有可能被命中,50个线程中的每个线程可能会执行一小段时间,然后阻塞。所以我认为由于抢占式调度程序,我只有50个上下文切换。不必浪费。 - johnnycrash


查看Linux下的实时调度。我从来没有这样做过,但是如果你真的需要这个,那么就像你可以在用户应用程序代码中获得的那样。

你似乎害怕的并不是那么大的交易。您无法阻止内核中断您的程序以获得真正的中断或更高优先级的任务想要运行,但是通过定期调度,内核确实使用了它自己的计算优先级值,它几乎可以处理您担心的大部分问题。如果线程A独占地保存资源X(X可以是锁定)并且线程B在资源X上等待变为可用,那么A的有效优先级将至少与B的优先级一样高。它还考虑了进程是否正在使用大量的cpu,或者是否花费大量时间来计算优先级。当然,好的价值也在那里。


1
2018-04-07 20:56



谢谢。我不担心内核抢占我,只是在我的进程中的其他线程。那些中断就没问题了。让我的进程中的另一个线程运行的中断是我担心的。 - johnnycrash
你使用的单词似乎与你想要的不相符,我不确定你想要的是你真正想要的。您可能想要合作多线程,或者您可能想要其他东西。你的意思是当线程A持有锁X时,没有其他想要锁X的线程可以执行,因为这几乎是所有线程同步的用途。你只需要正确设计你的代码;在正确的时间/地点呼叫和释放锁。如果你的意思是当线程A持有锁X时,那么根本没有其他线程可以执行,你应该查看SIGSTOP - nategoose