linux - 在 Linux 中是否有一种异步安全的方法来获取当前线程 ID?

标签 linux gcc pthreads signals posix

有什么方法可以从 Linux 中的信号处理程序获取当前线程 ID? getpid() 方法做我想做的,但不清楚它是否是异步安全的。 man 7 signal 提供了一个异步安全的 POSIX 方法列表,但这并没有告诉我们任何关于非 POSIX 方法的信息,例如 getpid()。据推测,Linux 添加的许多非 POSIX 方法中的一些是异步安全的,但我找不到列表。

还有this answer它声称所有直接(非多路复用)系统调用都是异步安全的,但没有提供任何证据。

目标是构建某种异步安全的线程本地存储,因为 __thread is not safe在一般情况下。

不必是“Linux 线程 ID”——任何一致的线程 ID 都可以。例如 pthread_self 会很棒,但没有人声称它是异步安全的。如果我们在 glibc Linux 中检查该方法的实现,它遵循 THREAD_SELF 宏,它看起来像:

# define THREAD_SELF \
({ struct pthread *__self;                                                  \
  asm ("movl %%gs:%c1,%0" : "=r" (__self)                                  \
          : "i" (offsetof (struct pthread, header.self)));                    \
  __self;}) 

似乎这应该是异步安全的,如果有问题的线程是在填充 gs 寄存器的机制下创建的(可能是 Linux 中的所有线程是,我不确定)。还在看that header让我很害怕......

最佳答案

Async-signal-safe access to __thread variables from dlopen()ed libraries? 中所述你提供的(重点是我的):

The __thread variables generally fit the bill (at least on Linux/x86), when the variable is in the main executable, or in a directly-linked DSO.

But when the DSO is dlopen()ed (and does not use initial-exec TLS model), the first access to TLS variable from a given thread triggers a call to malloc...

换句话说,它只需要一次访问该线程特定的变量就可以使它生效并使其在信号处理程序中可用。例如:

  1. 在创建子线程之前,在父线程中屏蔽您感兴趣的信号。
  2. 在调用 pthread_create 后取消阻塞父线程中那些有趣的信号。
  3. 在子线程中初始化您的 __thread 变量并解锁那些有趣的信号。

我通常将 unix 管道的写入端存储在特定于胎面的变量中,信号处理程序将信号编号写入该管道。管道的读取端在同一个线程中使用 select/epoll 注册,这样我就可以在信号上下文之外处理信号。例如:

__thread int signal_pipe; // initialized at thread start

extern "C" void signal_handler(int signo, siginfo_t*, void*)
{
    unsigned char signo_byte = static_cast<unsigned>(signo); // truncate
    ::write(signal_pipe, &signo_byte, 1); // standard unix self pipe trick
}

关于linux - 在 Linux 中是否有一种异步安全的方法来获取当前线程 ID?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21743889/

相关文章:

c - 从 C 代码获取当前使用的文件描述符的计数

c++ - Pthreads - 将顺序程序变成并行

linux - 使用 -lpthread 标志 : 时未定义对 `pthread_init' 的引用

c++ - 使用 -g gcc 标志编译的程序是否比不使用 -g 编译的同一程序慢?

c - 多线程消费者-生产者模型。我如何知道线程何时不忙

linux - 如何根据 Chef Recipe 中命令执行返回的值禁用Linux进程

c - c 中的简单服务器不起作用

c - 如何使用 v4l2 linux 界面从网络摄像头获取视频?

c++ - 交叉编译 C++ 程序时权限被拒绝

c++ - 在 C++ 中使用 curl 时 undefined symbol