在futex之前,线程/进程如何在Linux中停放和唤醒?
作者:互联网
在Linux中存在futex系统调用之前,线程库(如pthreads)使用哪些底层系统调用来阻塞/休眠线程并随后从用户区唤醒这些线程?
例如,如果一个线程试图获取一个互斥锁,那么userland实现将阻塞该线程(可能是在一个短暂的旋转间隔之后),但我找不到用于此的系统调用(除了futex这是一个相对较新的创建).
解决方法:
在futex和当前实现的pthreads for Linux,NPTL(需要内核2.6和更新版本)之前,还有另外两个带有适用于Linux的POSIX Thread API的线程库:linuxthreads和NGPT(0700在Gnu Pth上.LinuxThreads是唯一广泛使用的libpthread for (它可以在still用于某些奇怪的和未维护的micro-libc到work on 2.4;其他micro-libc变种可能在futex克隆之上拥有自己的builtin pthread-like API实现).而且Gnu Pth不是线程库,它是具有用户级“线程”切换的单进程线程.
当我们检查内核是否知道部分或全部用户线程时,你应该知道有几个Threading Models(通过向程序添加线程可以使用多少CPU内核;拥有线程的成本/线程数可以是多少开始).模型命名为M:N,其中M是用户空间线程编号,N是OS内核可调度的线程编号:
>“1:1””内核级线程” – 每个用户空间线程都可由OS内核调度.这是在Linuxthreads,NPTL和许多现代操作系统中实现的.
>“N:1””用户级线程” – 用户空间线程由用户空间规划,它们对内核都是不可见的,它只调度一个进程(并且它可能只使用1个CPU核心). Gnu Pth(GNU Portable Threads)就是它的一个例子,并且对于某些计算机体系结构还有许多其他实现.
>“M:N””混合线程” – OS内核有一些可见和可调度的实体,但其中可能有更多的用户空间线程.有时用户空间线程将在内核可见线程之间迁移.
使用1:1模型,Unix中有许多经典的睡眠机制/ API,如select / poll和信号以及IPC API的其他变体.我记得,Linuxthreads为每个线程使用了单独的进程(具有完全共享的内存),并且有特殊的管理器“线程”(进程)来模拟一些POSIX线程功能. Wikipedia说SIGUSR1 / SIGUSR2在Linuxthreads中用于线程之间的一些内部通信,同样says IBM“基元的同步是通过信号实现的.例如,线程阻塞直到被信号唤醒.”.另请查看项目FAQ 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或在没有线程工作时选择).
使用M:N模型的东西非常复杂……对NGPT不太了解…有关NGPT的一段有关于POSIX Threads and the Linux Kernel, Dave McCracken, OLS2002,330第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!).
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.
标签:multithreading,linux,futex 来源: https://codeday.me/bug/20191001/1839805.html