本文介绍了在futex之前,如何在Linux中停放和唤醒线程/进程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Linux中没有futex系统调用之前,诸如pthreads的线程库使用了哪些底层系统调用来阻塞/休眠线程,并随后将这些线程从用户区唤醒?

Before the futex system calls existed in Linux, what underlying system calls were used by threading libraries like pthreads to block/sleep a thread and to subsequently wake those threads from userland?

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

For example, if a thread tries to acquire a mutex, the userland implementation will block the thread (perhaps after a short spinning interval), but I can't find the syscalls that are used for this (other than futex which are a relatively recent creation).

推荐答案

在futex和当前用于Linux的pthread NPTL(需要内核2.6及更高版本)的当前实现之前,还有另外两个带有POSIX Thread API的Linux线程库: linuxthreads 和NGPT(其中基于 Gnu Pth .LinuxThreads是多年来唯一被广泛使用的libpthread(它可以用于某些奇怪且未经维护的微型libc中,用于在2.4上工作;其他微型libc变体可能具有自己的内置实现在 futex之上的类似pthread的API +克隆).而且Gnu Pth不是线程库,它是具有用户级线程"切换的单进程线程.

Before futex and current implementation of pthreads for Linux, the NPTL (require kernel 2.6 and newer), there were two other threading libraries with POSIX Thread API for Linux: linuxthreads and NGPT (which was based on Gnu Pth. LinuxThreads was the only widely used libpthread for years (and it can still be used in some strange & unmaintained micro-libc to work on 2.4; other micro-libc variants may have own builtin implementation of pthread-like API on top of futex+clone). And Gnu Pth is not thread library, it is single process thread with user-level "thread" switching.

您应该知道,当我们检查时,有几个线程模型内核是否知道某些或所有用户线程(在向程序添加线程时可以使用多少个CPU内核;拥有线程的成本/可以启动多少个线程)?模型命名为M:N,其中M是用户空间线程号,而N是可由OS内核计划的线程号:

You should know that there are several Threading Models when we check does the kernel knows about some or all of user threads (how many CPU cores can be used with adding threads to the program; what is the cost of having the thread / how many threads may be started). Models are named as M:N where M is userspace thread number and N is thread number schedulable by OS kernel:

  • "1:1"内核级线程"-每个用户空间线程均可由OS内核调度.这是在Linuxthreads,NPTL和许多现代OS中实现的.
  • "N:1"用户级线程"-用户空间线程是由用户空间规划的,它们对于内核都是不可见的,它仅调度一个进程(并且可能仅使用1个CPU内核). Gnu Pth( GNU可移植线程)是它的示例,并且还有许多其他实现一些计算机体系结构.
  • "M:N"混合线程"-OS内核中有一些可见且可调度的实体,但是其中可能有更多的用户空间线程.有时用户空间线程会在内核可见的线程之间迁移.
  • "1:1" ''kernel-level threading'' - every userspace thread is schedulable by OS kernel. This is implemented in Linuxthreads, NPTL and many modern OS.
  • "N:1" ''user-level threading'' - userspace threads are planned by the userspace, they all are invisible to the kernel, it only schedules one process (and it may use only 1 CPU core). Gnu Pth (GNU Portable Threads) is example of it, and there are many other implementations for some computer architectures.
  • "M:N" ''hybrid threading'' - there are some entities visible and schedulable by OS kernel, but there may be more user-space threads in them. And sometimes user-space threads will migrate between kernel-visible threads.

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

With 1:1 model there are many classic sleep mechanisms/APIs in Unix like select/poll and signals and other variants of IPC APIs. As I remember, Linuxthreads used separate processes for every thread (with fully shared memory) and there was special manager "thread" (process) to emulate some POSIX thread features. Wikipedia says that SIGUSR1/SIGUSR2 were used in Linuxthreads for some internal communication between threads, same says IBM "The synchronization of primitives is achieved by means of signals. For example, threads block until awoken by signals.". Check also the project FAQ http://pauillac.inria.fr/~xleroy/linuxthreads/faq.html#H.4 "With LinuxThreads, I can no longer use the signals SIGUSR1 and SIGUSR2 in my programs! Why?"

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

With "N:1" model thread may call some blocking syscall and block everything (some libraries may convert some blocking syscalls into async, or use some SIGALRM or SIGVTALRM magic); or it may call some (very) special internal threading function which will do user-space thread switching by rewriting machine state register (like switch_to in linux kernel, save IP/SP and other regs, restore IP/SP and regs of other thread). So, kernel does not wake any user thread directly from userland, it just schedules whole process; and user space scheduler implement thread synchronization logic (or just calls sched_yield or select when there is no threads to work).

使用M:N模型时,事情非常复杂...对NGPT不太了解... POSIX线程和Linux内核,Dave McCracken,OLS2002,330 第5页

With M:N model things are very complicated... Don't know much about NGPT... There is one paragraph about NGPT in POSIX Threads and the Linux Kernel, Dave McCracken, OLS2002,330 page 5

一些论文和帖子: POSIX线程和Linux内核,Dave McCracken,OLS2002,330 有关NPTL 0.1的LWN帖子

NPTL设计pdf :

这篇关于在futex之前,如何在Linux中停放和唤醒线程/进程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-03 21:50