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

标签 linux multithreading futex

在 Linux 中存在 futex 系统调用之前,pthreads 等线程库使用哪些底层系统调用来阻塞/休眠线程并随后将这些线程从用户空间?

例如,如果一个线程试图获取一个互斥体,用户空间的实现将阻塞该线程(可能在短暂的旋转间隔之后),但我找不到用于此的系统调用( 除外) futex 这是一个相对较新的创作)。

最佳答案

在 futex 和当前 Linux 的 pthreads 实现之前,NPTL(需要内核 2.6 和更新版本),还有另外两个带有 POSIX 线程 API 的线程库:linuxthreads和 NGPT(was basedGnu Pth 上。LinuxThreads 是多年来唯一广泛使用的 libpthread(它可以 still 用于一些奇怪且未维护的 micro-libc 到 work on 2.4 ;其他 micro-libc 变体可能有自己的 builtinfutex +clone 之上实现了类似 pthread 的 API。而且 Gnu Pth 不是线程库,它是具有用户级“线程”切换的单进程线程。

你应该知道有几个Threading Models当我们检查内核是否知道部分或全部用户线程时(向程序添加线程可以使用多少个 CPU 核心;拥有线程的成本是多少/可以启动多少个线程)。模型命名为 M:N,其中 M 是用户空间线程数,N 是操作系统内核可调度的线程数:

  • "1:1"''内核级线程'' - 每个用户空间线程都可由操作系统内核调度。这已在 Linuxthreads、NPTL 和许多现代操作系统中实现。
  • "N:1"''用户级线程'' - 用户空间线程由用户空间规划,它们对内核都是不可见的,它只调度一个进程(它可能只使用 1 个 CPU 内核)。 Gnu Pth ( GNU Portable Threads ) 就是一个例子,对于某些计算机体系结构还有许多其他实现。
  • "M:N"''混合线程'' - 操作系统内核有一些可见和可调度的实体,但其中可能有更多的用户空间线程。有时用户空间线程会在内核可见线程之间迁移。

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

LinuxThreads needs two signals for its internal operation. One is used to suspend and restart threads blocked on mutex, condition or semaphore operations. The other is used for thread cancellation. On ``old'' kernels (2.0 and early 2.1 kernels), there are only 32 signals available and the kernel reserves all of them but two: SIGUSR1 and SIGUSR2. So, LinuxThreads has no choice but use those two signals.

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

对于 M:N 模型,事情非常复杂...对 NGPT 了解不多...POSIX Threads and the Linux Kernel, Dave McCracken, OLS2002,330 中有一段关于 NGPT 的内容第 5 页

There is a new pthread library under development called NGPT. This library is based on the GNU Pth library, which is an M:1 library. NGPT extends Pth by using multiple Linux tasks, thus creating an M:N library. It attempts to preserve Pth’s pthread compatibility while also using multiple Linux tasks for concurrency, but this effort is hampered by the underlying differences in the Linux threading model. The NGPT library at present uses non-blocking wrappers around blocking system calls to avoid blocking in the kernel.

一些论文和帖子:POSIX Threads and the Linux Kernel, Dave McCracken, OLS2002,330 , LWN post about NPTL 0.1

The futex system call is used extensively in all synchronization primitives and other places which need some kind of synchronization. The futex mechanism is generic enough to support the standard POSIX synchronization mechanisms with very little effort. ... Futexes also allow the implementation of inter-process synchronization primitives, a sorely missed feature in the old LinuxThreads implementation (Hi jbj!).

NPTL design pdf :

5.5 Synchronization Primitives The implementation of the synchronization primitives such as mutexes, read-write locks, conditional variables, semaphores, and barriers requires some form of kernel support. Busy waiting is not an option since threads can have different priorities (beside wasting CPU cycles). The same argument rules out the exclusive use of sched yield. Signals were the only viable solution for the old implementation. Threads would block in the kernel until woken by a signal. This method has severe drawbacks in terms of speed and reliability caused by spurious wakeups and derogation of the quality of the signal handling in the application. Fortunately some new functionality was added to the kernel to implement all kinds of synchronization primitives: futexes [Futex]. The underlying principle is simple but powerful enough to be adaptable to all kinds of uses. Callers can block in the kernel and be woken either explicitly, as a result of an interrupt, or after a timeout.

关于linux - 在 futex 之前,线程/进程如何在 Linux 中停放和唤醒?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45764378/

相关文章:

linux - 找不到 yocto-bsp 命令

c# - C#线程通信问题

linux - 如何找到当前二进制文件运行的路径?

vb.net - .NET 多线程变量访问

java - 访问java中的同步方法

linux-kernel - FUTEX_WAIT 和 FUTEX_WAIT_PRIVATE 有什么区别?

c - Linux futex 系统调用虚假唤醒,返回值为 0?

c++ - boost 进程间IPC死锁

linux - 不小心将文件和文件夹移动到不存在的地方

linux - 如何在第 n 行文件的中间插入文本