Bee*_*ope 6 linux multithreading futex
在 Linux 中存在系统调用之前futex,线程库使用哪些底层系统调用来pthreads阻塞/休眠线程并随后从用户空间唤醒这些线程?
例如,如果一个线程尝试获取互斥锁,用户态实现将阻止该线程(可能在很短的旋转间隔之后),但我找不到用于此目的的系统调用(除了相对较新的创建的系统调用之外futex) )。
在futex和 Linux 的 pthreads 当前实现 NPTL(需要内核 2.6 及更高版本)之前,还有另外两个带有 Linux 的 POSIX Thread API 的线程库: linuxthreads和 NGPT(基于Gnu Pth。LinuxThreads 是唯一广泛使用的libpthread 已经使用多年了(它仍然可以在一些奇怪且未维护的 micro-libc 中使用,以在 2.4 上工作;其他 micro-libc 变体可能在futex +clone之上有自己的类似 pthread 的 API 的内置实现)。Gnu Pth 是不是线程库,它是具有用户级“线程”切换的单进程线程。
\n\n你应该知道,当我们检查内核是否知道部分或全部用户线程(向程序添加线程时可以使用多少个CPU核心;拥有线程的成本是多少/有多少个线程)时,有几种线程模型可以启动)。模型命名为M:N其中 M 是用户空间线程号,N 是操作系统内核可调度的线程号:
对于 1:1 模型,Unix 中有许多经典的睡眠机制/API,例如选择/轮询和信号以及IPC API 的其他变体。我记得,Linuxthreads对每个线程使用单独的进程(具有完全共享的内存),并且有特殊的管理器“线程”(进程)来模拟一些 POSIX 线程功能。维基百科说 SIGUSR1/SIGUSR2 在 Linux 线程中用于线程之间的一些内部通信,IBM 也说“原语的同步是通过信号实现的。例如,线程阻塞直到被信号唤醒”。另请检查项目常见问题解答http://pauillac.inria.fr/~xleroy/linuxthreads/faq.html#H.4 “使用 LinuxThreads,我无法再在程序中使用信号 SIGUSR1 和 SIGUSR2!为什么?”
\n\n\n\n\nLinuxThreads 的内部操作需要两个信号。一种用于挂起和重新启动因互斥、条件或信号量操作而阻塞的线程。另一个用于线程取消。\n 在“旧”内核(2.0 和早期的 2.1 内核)上,只有 32 个可用信号,并且内核保留除两个之外的所有信号:SIGUSR1 和 SIGUSR2。因此,LinuxThreads 别无选择,只能使用这两个信号。
\n
使用“N:1”模型线程可能会调用一些阻塞系统调用并阻塞所有内容(某些库可能会将一些阻塞系统调用转换为异步,或使用一些SIGALRM 或 SIGVTALRM 魔法);或者它可能会调用一些(非常)特殊的内部线程函数,该函数将通过重写机器状态寄存器来进行用户空间线程切换(如Linux内核中的switch_to,保存IP / SP和其他寄存器,恢复其他线程的IP / SP和寄存器) 。因此,内核不会直接从用户态唤醒任何用户线程,它只是调度整个进程;和用户空间调度程序实现线程同步逻辑(或者只是调用sched_yield在没有线程工作时仅调用或选择)。
对于M:N模型,事情非常复杂...对 NGPT 不太了解... POSIX 线程和 Linux 内核中有一段关于 NGPT,Dave McCracken,OLS2002,330第 5 页
\n\n\n有一个新的 pthread 库正在开发中,称为 NGPT。该库基于 GNU Pth 库,它是一个 M:1 库。NGPT 通过使用多个 Linux 任务来扩展 Pth,从而创建一个 M:N 库。它尝试保留 Pth\xe2\x80\x99s pthread 兼容性,同时还使用多个 Linux 任务进行并发,但这一努力受到 Linux 线程模型中的根本差异的阻碍。NGPT 库目前在阻塞系统调用周围使用非阻塞包装器来避免内核中的阻塞。
\n
一些论文和帖子:POSIX Threads and the Linux Kernel,Dave McCracken,OLS2002,330,LWN post about NPTL 0.1
\n\n\n\n\n\n\nfutex 系统调用广泛用于所有同步原语和其他需要某种同步的地方。futex 机制足够通用,只需很少的工作即可支持标准 POSIX 同步机制。... Futexes 还允许实现进程间同步原语,这是旧的 LinuxThreads 实现中非常错过的一个功能(Hi jbj!)。
\n
\n\n5.5 同步原语 同步原语(例如互斥锁、读写锁、条件变量、信号量和屏障)的实现需要某种形式的内核支持。繁忙等待不是一个选择,因为线程可以具有不同的优先级(除了浪费 CPU 周期之外)。同样的论点排除了仅使用 schedield 的可能性。信号是旧实现的唯一可行的解决方案。线程将在内核中阻塞,直到被信号唤醒。这种方法在速度和可靠性方面存在严重缺陷,原因是虚假唤醒和应用程序中信号处理质量的降低。\n幸运的是,内核中添加了一些新功能来实现\n各种同步原语:futexes [Futex]。基本原理很简单,但功能强大,足以适应各种用途。调用者可以在内核中阻塞并被显式唤醒(由于中断或超时)。
\n
| 归档时间: |
|
| 查看次数: |
2520 次 |
| 最近记录: |