GCC 警告 gettid() 系统调用包装器,glibc 2.30-8

QnA*_*QnA 5 c linux glibc system-calls

手册页SO post#1 / SO post#2都表明gettid()是在 glibc 2.30 中实现的。我想我正在使用GLIBC 2.30-8,根据ldd --version,但gcc仍然抱怨 -警告:函数'gettid'的隐式声明;您指的是 'getgid' 吗?[-Wimplicit-function-declaration]。我可以忽略警告,程序运行良好。

我尝试使用的标题gettid()<sys/types.h>,遵循手册页。我错过了什么?

syscall(SYS_gettid)使用标头调用<sys/syscall.h>不会触发gcc.

Jos*_*ica 8

手册页中有关该函数的信息是错误的。而不是#include <sys/types.h>这样做:

#define _GNU_SOURCE
#include <unistd.h>
Run Code Online (Sandbox Code Playgroud)

我向手册页邮件列表发送了一封电子邮件,要求更正此问题。


Cra*_*tey 6

注意:这是非常新的,不应该在没有某些条件的情况下依赖它。而且,可能永远都无法依靠。

见下文。


直到 2019 年 2 月,这是联机帮助页上的内容:

来自: man gettid:

注意:此系统调用没有 glibc 包装器;见注释。

而且,从注释:

Glibc 没有为这个系统调用提供包装器;使用syscall(2).

有关更多详细信息,请参阅 NOTES 部分的其余部分。这是因为他们希望您使用其他pthread_self兼容的东西。

glibc是我个人不同意的怪癖/哲学。

因为,有时需要使用 real/linuxtid值。


新方法是 [截至 2019 年 2 月,根据 Joseph]:

#define _GNU_SOURCE
#include <unistd.h>
Run Code Online (Sandbox Code Playgroud)

获得gettid声明。

但 ...

永远不能依赖 [没有#if/#ifdef],因为gettid 系统调用自 2004 年左右的 linux 2.4 以来就已经存在。

因此,添加包装功能花了glibc 15年!?!?:-( IMO,太少,太晚了。

使用新方法时,它会破坏与 15 年内发布的所有发行版的向后兼容性。

所以,忽略这一点并继续使用syscall是要走的路。这是保持向前/向后兼容性的最简单方法。

我们可以创建包装器,但它更复杂 [类似于]:

#if __GLIBC_PREREQ(2,30)
#define _GNU_SOURCE
#include <unistd.h>

#else

#include <sys/syscall.h>

pid_t
gettid(void)
{

    return syscall(SYS_gettid);
}
#endif
Run Code Online (Sandbox Code Playgroud)

事实上,它甚至比这更复杂,因为我们开始包括事物之前,我们必须确保我们有__GLIBC_PREREQ[and__GLIBC____GLIBC_MINOR__]的定义。

而且,做到这一点是有问题的。因此,人们可能会被迫总是这样做:

#define _GNU_SOURCE
#include <unistd.h>
Run Code Online (Sandbox Code Playgroud)

并且,然后添加#if之后。或者,无论实际的神秘方式是什么[我无法亲自测试,因为我在使用旧方法的系统上]。

很乱,[IMO] 不值得麻烦。


而且,情况更糟。

由于旧方法已经存在了这么久,许多应用程序已经定义了自己的gettid包装函数。因此,新声明可能会与此冲突。

因此,无需做任何事情,开发人员就可以重新编译他们 [以前] 的工作代码,并且构建现在会出错。

为了防止这种情况,unistd.h可能应该声明gettid用户是否#define在包含它之前放置了一些(类似于_GNU_SOURCE),例如:

#define _DECLARE_GETTID
#include <unistd.h>
Run Code Online (Sandbox Code Playgroud)

而且,由于新方法打破了 15 年的兼容性,联机帮助页需要记录这一事实并解释旧方法。

因为,尝试编写跨平台代码、跨多个内核版本和多个glibc版本的开发人员需要了解这一点。


更新:

之前没有添加它是有充分理由的 - 它不是应用程序使用的受支持抽象。

这仍然没有给他们打破向后兼容性的许可。

并且,必须为特殊应用程序(例如那些与给定设备驱动程序密切配合的应用程序)合成缺失的功能

许久

15+ 年...

glibc 正在考虑可能的线程模型的想法,其中内核 tid 不会是线程生命周期的不变式。

内核对pthread_t. 它只知道tid. 这就是应用程序必须与内核通信的方式(例如tgkill)。

内核模型中没有任何东西会改变tid中游,就像它会pid在执行过程中改变进程的 a 一样。

这是因为内核对待一个tid就像一个pid调度的目的。pid/tid每个进程和每个线程都有一个任务结构[索引/标识]。

否则,将需要对所有内核调度程序、任务/线程层次结构等进行大修。因此,glibc不可能单独完成此操作。而且,到底是为了什么?

clone创建线程的系统调用之后[可以选择使用相同的地址空间],这在很大程度上是一个不可见的区别,线程在被调度时获得相同的权重[基于调度程序和任务优先级]。

这是内核的做法最大的好处之一:任务/线程当被调度[不像的WinX]一等公民。

旁注:我必须对实时嵌入式 H/W H.264 视频编码器进行编程,并且必须处理nptl[即linuxthreads(?)]的前兆,这导致了吞吐量和延迟方面的严重问题。幸运的是,nptl在我们必须发货之前就出现了。区别是白天和黑夜。

只有在相对最近的讨论之后才被认为是可以的。

所述内核[和/或POSIX]定义的语义,不glibc。glibc 可以遵循和实施,而不是规定。

而且,由于glibc人们顽固 [和令人讨厌],并且花了 15 年的时间来决定 [显而易见的],IMO,他们已经失去了在这件事上的任何谈判权。

  • @JosephSible-ReinstateMonica 几乎不值得 DV。这是如此新的东西,依赖它会在大多数当前/稳定的发行版上崩溃[我的 ubuntu 18.02 几天前更新了]。最好等一年左右,然后直接去。但是,在 libc 版本上添加带有条件的包装器就可以了。`gettid` 系统调用从 2004 年左右的 linux 2.4 开始就已经存在,所以 `glibc` 在 **16 年**之后终于添加了一个包装器!?!?!?因此,依赖“unistd.h”包装器而不使用“#if/#ifdef”将会破坏很多向后兼容性。 (3认同)