【问题标题】:Can syscall(SYS_gettid) block?syscall(SYS_gettid) 可以阻塞吗?
【发布时间】:2021-12-28 18:36:25
【问题描述】:

我的理解是,如果不是所有系统调用,一些系统调用可能会阻塞。这是阻塞电话吗?我想在重复调用且对时间敏感的函数中获取唯一的线程 ID。我打算这样做:

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

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

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

【问题讨论】:

  • 我无法想象这会阻止的任何原因。它只是从内核数据结构中检索一个值,无需等待。
  • 这不是“阻塞系统调用”,但请记住,所有系统调用都是调度程序决定是时候做其他事情的机会。 (当然,这也可能发生在任何其他时间,但系统调用更有可能)

标签: c linux


【解决方案1】:

您应该使用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

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

00000000000a67c0 <getpid>:
   a67c0:       d503245f        bti     c
   a67c4:       d2801588        mov     x8, #0xac
   a67c8:       d4000001        svc     #0x0
   a67cc:       d65f03c0        ret 

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

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

【讨论】:

  • 线程局部变量可能也值得考虑,特别是如果您可以使用初始执行模型。
  • @o11c 我也确实考虑过。但是,幸运的是,我认为我找到了一种更好的方法,它甚至根本不使用线程 ID,这只是作为当前未使用的参数传入的额外数据,但可以解决我的问题。
猜你喜欢
  • 1970-01-01
  • 2011-09-22
  • 2012-01-20
  • 1970-01-01
  • 2015-11-27
  • 2014-11-01
  • 2012-04-30
  • 1970-01-01
  • 2013-11-19
相关资源
最近更新 更多