【发布时间】:2026-01-29 08:50:01
【问题描述】:
根据传统的 POSIX,errno 只是一个整数左值,它与 fork 完美配合,但显然不能与线程配合使用。根据 pthreads,errno 是线程局部整数左值。在 Linux/NTPL 下,作为实现细节,errno 是一些“扩展为返回整数左值的函数的宏”。
在我的 Debian 系统上,这似乎是 *__errno_location (),在其他一些系统上,我见过类似 &(gettib()->errnum 的东西。
TL;DR
假设我已经使用clone 创建了一个线程,我可以直接调用errno 并期望它会起作用,还是我必须做一些特殊的雨舞?例如,我是否需要读取线程信息块中的一些特殊字段,或者一些特殊的 TLS 值,或者,我是否需要设置 glibc 以某种方式存储错误值的线程局部变量的地址?可能是__set_errno_location() 之类的东西?
或者,它会“正常工作”吗?
不可避免地,有人会想回复“简单地使用 phtreads”——请不要。我不想使用 pthreads。我想要clone。我不想要 pthread 的任何不明智的功能,我不想处理它的任何怪癖,也不想要实现这些怪癖的开销。我认识到 pthreads 中的大部分杂乱无章来自于它必须工作(而且,令人惊讶的是,它成功工作)以及其他一些完全崩溃的系统,这些系统已经有近 30 年的历史了,但是并不意味着它对每个人和每种情况都一定是一件好事。在这种情况下,可移植性不是问题。
在这种特殊情况下,我想要的只是启动另一个与父进程在同一地址空间中运行的进程,通过一个简单的锁(例如,futex)进行同步,并且write 正常工作(这意味着我也 em> 必须能够正确读取errno)。尽可能少的开销,不需要甚至不需要其他功能或特殊行为。
【问题讨论】:
-
不要使用
clone(或futex)系统调用;它本质上是为那些实现线程库保留的。只需使用pthread(不使用clone或futex...) -
好的,谢谢您的提示。我熟悉 pthread,并且如前所述,我明确对使用 pthread 不感兴趣。我想使用
clone,并且我有一个可靠工作的futex包装器。我唯一的问题是我找不到关于如何处理errno的信息。 -
这是一个系统特定的实现细节。研究 Linux x86-64 ABI 并查看内核和一些 libc 的源代码,例如 MUSL libc;你需要编写一些汇编代码。