我的理解是,一些(如果不是全部)系统调用可能会被阻塞。这是阻塞呼叫吗?我想在一个被重复调用且对时间敏感的函数中获取唯一的线程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() 返回值。
您应该使用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指令后面的数百甚至数千个周期的成本。如果您正在做一些频繁且时间敏感的事情,那么不陷入内核可能是一个巨大的胜利。
我还建议您考虑重新组织代码,以便大批量地完成工作,并且您不需要问“我在哪个线程上?” 很经常。根本没有完成的操作总是最快的。