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.
手册页中有关该函数的信息是错误的。而不是#include <sys/types.h>这样做:
#define _GNU_SOURCE
#include <unistd.h>
Run Code Online (Sandbox Code Playgroud)
我向手册页邮件列表发送了一封电子邮件,要求更正此问题。
注意:这是非常新的,不应该在没有某些条件的情况下依赖它。而且,可能永远都无法依靠。
见下文。
直到 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,他们已经失去了在这件事上的任何谈判权。
| 归档时间: |
|
| 查看次数: |
792 次 |
| 最近记录: |