syscall(SYS_gettid) 可以阻塞吗?

som*_*ous 1 c linux

我的理解是,一些(如果不是全部)系统调用可能会被阻塞。这是阻塞呼叫吗?我想在一个被重复调用且对时间敏感的函数中获取唯一的线程ID。我本来打算这样做:

//header.h
#define _GNU_SOURCE
#include <sys/syscall.h>
#ifdef SYS_gettid
#define gettid() syscall(SYS_gettid)
#else
#define gettid() 0
#endif
Run Code Online (Sandbox Code Playgroud)
//file.c
#include "header.h"
...
void function()
{
        pid_t thread = gettid();
        //Logic based on thread
        ...
}
Run Code Online (Sandbox Code Playgroud)

这里的函数会被重复调用并且不能阻塞。也许我应该使用pthread_self()and pthread_equal(t1, t2)?谢谢。

编辑:我同样可以使用其中任何一个。我知道它们不提供相同的返回值,但我将对线程 id 执行的逻辑是将其与一组已知的线程 id 进行比较,以基本上找出谁在调用它。我保存了 gettid() 返回值和 pthread_self() 返回值。

zwo*_*wol 5

您应该使用pthread_self,主要是因为它是可移植的syscall(SYS_gettid),但不是可移植的,而且还因为典型的实现根本不需要陷入内核。例如,在我输入此内容的机器上,有一个名为 的特殊硬件寄存器,tpidr_el0用于存储指向特定于线程的数据的指针,因此pthread_self可以只有三个指令,无需更改特权级别:

0000000000077870 <pthread_self>:
   77870:       d53bd040        mrs     x0, tpidr_el0
   77874:       d11e4000        sub     x0, x0, #0x790
   77878:       d65f03c0        ret
Run Code Online (Sandbox Code Playgroud)

公平地说,该架构上的系统调用只是少数指令,例如

00000000000a67c0 <getpid>:
   a67c0:       d503245f        bti     c
   a67c4:       d2801588        mov     x8, #0xac
   a67c8:       d4000001        svc     #0x0
   a67cc:       d65f03c0        ret 
Run Code Online (Sandbox Code Playgroud)

但是系统调用存根的汇编转储并没有显示隐藏在该svc指令后面的数百甚至数千个周期的成本。如果您正在做一些频繁且时间敏感的事情,那么不陷入内核可能是一个巨大的胜利。

我还建议您考虑重新组织代码,以便大批量地完成工作,并且您不需要“我在哪个线程上?” 很经常。根本没有完成的操作总是最快的。

  • 线程局部变量也可能值得考虑,特别是如果您可以使用初始执行模型。 (2认同)