一尘不染

在futex之前,如何在Linux中停放和唤醒线程/进程?

linux

futex在Linux中存在系统调用之前,线程库使用了哪些底层系统调用,例如pthreads阻塞/hibernate了线程并随后从用户区唤醒了这些线程?

例如,如果某个线程尝试获取互斥量,则userland实现将阻塞该线程(可能在较短的旋转间隔之后),但是我找不到用于此目的的syscall(除了futex相对较新的创建之外)
)。


阅读 542

收藏
2020-06-07

共1个答案

一尘不染

futex的和当前实现并行线程的Linux之前,NPTL(需要内核2.6和更高版本),此外,还有两个线程库与POSIX线程API的Linux:
Linux线程这和NGPT(基于牛羚第P。LinuxThreads中是唯一的广泛应用libpthread已有多年历史了(它仍然可以在某些陌生且未维护的micro-
libc中使用,以在2.4上运行;其他micro-
libc变体可能在futex + clone
之上具有内置的类似pthread API
内置实现。)Gnu
Pth是不是线程库,它是具有用户级“线程”切换的单进程线程。

你应该知道,有几个线程模型,当我们检查不内核知道的一些或所有用户线程(多少CPU内核可以增加线程程序中使用的;什么是具有线程/多少线程的成本可能会开始)。模型被命名为M:N,其中M是用户空间线程号,N是可由OS内核计划的线程号:

  • “ 1:1”“内核级线程”-OS内核可以调度每个用户空间线程。这是在Linuxthreads,NPTL和许多现代OS中实现的。
  • “ N:1”“用户级线程”-用户空间线程是由用户空间规划的,它们对于内核都是不可见的,它仅调度一个进程(并且可能仅使用1个CPU内核)。Gnu Pth(GNU可移植线程)就是它的示例,并且某些计算机体系结构还有许多其他实现。
  • “ M:N”“混合线程”-OS内核有一些可见且可调度的实体,但是其中可能有更多的用户空间线程。有时用户空间线程将在内核可见线程之间迁移。

在1:1模型中,Unix中有许多经典的睡眠机制/
API,例如选择/轮询和信号以及IPC
API的其他变体。我记得,Linuxthreads为每个线程(具有完全共享的内存)使用单独的进程,并且有特殊的管理器“线程”(进程)来模拟某些POSIX线程功能。Wikipedia表示SIGUSR1
/
SIGUSR2在Linuxthreads中用于线程之间的一些内部通信,IBM则说
“原语的同步是通过信号实现的。例如,线程阻塞直到被信号唤醒为止。”
另请检查项目常见问题解答http://pauillac.inria.fr/~xleroy/linuxthreads/faq.html#H.4
“有了LinuxThreads,我不能再在程序中使用信号SIGUSR1和SIGUSR2!为什么?”

LinuxThreads的内部操作需要两个信号。 一种用于挂起和重新启动在互斥,条件或信号量操作中阻塞的线程。 另一个用于线程取消。
在``旧’‘内核(2.0和2.1早期的内核)上,只有32个可用信号,内核保留所有信号,但只有两个:SIGUSR1和SIGUSR2。因此,LinuxThreads除了使用这两个信号外别无选择。

使用“ N:1”模型线程可以调用某些阻塞的系统调用并阻塞所有内容(某些库可能会将某些阻塞的系统调用转换为异步,或使用某些SIGALRM或SIGVTALRM
magic
);或者它可能调用某些(非常)特殊的内部线程功能,该功能将通过重写机器状态寄存器来进行用户空间线程切换(例如linux内核中的switch_to,保存IP
/ SP和其他注册表,恢复IP / SP和其他线程的注册表)
。因此,内核不会直接从userland唤醒任何用户线程,它只是调度整个进程。和用户空间调度程序实现线程同步逻辑(或仅sched_yield在没有工作线程时调用或选择)。

对于M:N模型,事情非常复杂…对NGPT不太了解…在POSIX线程和Linux内核中有关于NGPT的一小段
,Dave
McCracken,OLS2002,330,
第5页

有一个正在开发的名为NGPT的新pthread库。该库基于GNU
Pth库,它是一个M:1库。NGPT通过使用多个Linux任务扩展了Pth,从而创建了M:N库。它试图保留Pth的pthread兼容性,同时还使用多个Linux任务进行并发,但是由于Linux线程模型的根本差异而使这项工作受阻。当前,NGPT库在阻塞系统调用周围使用非阻塞包装程序,以避免在内核中阻塞。

一些论文和文章:POSIX Threads和Linux Kernel,Dave
McCracken,OLS2002,330
LWN关于NPTL
0.1的文章

futex系统调用广泛用于所有同步原语和其他需要某种同步的地方。futex机制足够通用,可以非常轻松地支持标准POSIX同步机制。…
Futexes还允许实现进程间同步原语,这是旧版LinuxThreads实现中非常错过的​​功能(嗨,jbj!)。

NPTL设计pdf

5.5同步原语同步原语(例如互斥锁,读写锁,条件变量,信号量和屏障)的实现需要某种形式的内核支持。繁忙等待不是一种选择,因为线程可能具有不同的优先级(除了浪费CPU周期之外)。相同的参数排除了计划收益率的排他性使用。
信号是旧实施的唯一可行解决方案。
线程将阻塞内核,直到被信号唤醒为止。该方法在速度和可靠性方面存在严重缺陷,这些缺陷是由虚假唤醒和应用中信号处理质量的下降引起的。幸运的是,内核中添加了一些新功能,以实现各种同步原语:futexes
[Futex]。基本原理很简单,但功能强大到足以适应各种用途。调用程序可以在内核中阻塞,也可以由于中断而显式唤醒,也可以在超时后唤醒。

2020-06-07