GCC 警告 gettid() 系统调用包装器,glibc 2.30-8
GCC warns about gettid() syscall wrapper, with glibc 2.30-8
man page and SO post#1/SO post#2 都表明 gettid()
是在 glibc 2.30 中实现的。根据 ldd --version
,我想我正在使用 GLIBC 2.30-8,但 gcc
仍然抱怨 - 警告:函数 'gettid 的隐式声明';您指的是 ‘getgid’ 吗? [-Wimplicit-function-declaration]。我可以忽略警告,程序运行正常。
我尝试与 gettid()
一起使用的 header 是 <sys/types.h>
,遵循手册页。我错过了什么吗?
使用 header <sys/syscall.h>
调用 syscall(SYS_gettid)
不会触发来自 gcc
的警告。
注意:这太新了,没有某些条件不应该依赖它。而且,可能 永远不会 值得信赖。
见下文。
2019 年 2 月之前,联机帮助页是这样说的:
发件人:man gettid
:
Note: There is no glibc wrapper for this system call; see NOTES.
并且,来自注释:
Glibc does not provide a wrapper for this system call; call it using syscall(2)
.
有关详细信息,请参阅注释部分的其余部分。这是因为他们希望您使用其他 pthread_self
兼容的东西。
我个人不同意 glibc
quirk/philosophy。
因为,有时需要使用real/linux tid
值。
新方法是[截至 2019 年 2 月,据 Joseph 称]:
#define _GNU_SOURCE
#include <unistd.h>
获得gettid
声明。
但是...
这 永远不会 [没有 #if/#ifdef
] 因为 gettid
系统调用 已经被大约从 linux 2.4 开始,大约在 2004 年。
因此,添加包装函数花了glibc
15年!?!? :-( IMO,太少,太晚了。
使用新方法时,它会破坏与那 15 年期间发布的所有发行版的向后兼容性。
所以,忽略这一点并继续使用 syscall
是可行的方法。这是保持 forward/backward 兼容性的最简单 方法。
我们可以创建包装器,但它更复杂[类似于]:
#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
事实上,它比这更复杂,因为我们必须确保我们有 __GLIBC_PREREQ
[and __GLIBC__
and __GLIBC_MINOR__
] before[的定义=158=] 我们开始包括东西。
而且,要做到这一点是有问题的。所以,一个人可能会被迫总是做:
#define _GNU_SOURCE
#include <unistd.h>
然后,然后 添加 #if
。或者,无论实际的神秘方式是什么[我无法亲自测试,因为我在使用旧方法的系统上]。
混乱,[IMO]不值得麻烦。
而且,情况更糟。
由于旧方法已经存在了很长时间,许多应用程序已经定义了自己的 gettid
包装函数。所以,新声明可能会与此冲突。
因此,开发人员无需执行任何操作即可重新编译他们的[以前]工作代码,并且构建现在会出错。
为了防止这种情况,unistd.h
应该 仅 声明 gettid
如果用户在包含它之前放置了一些 #define
(类似于_GNU_SOURCE
) 喜欢:
#define _DECLARE_GETTID
#include <unistd.h>
而且,由于新方法打破了 15 年的兼容性,联机帮助页需要记录这一事实并解释旧方法。
因为,尝试编写跨平台代码、跨多个内核版本和多个 glibc
版本的开发人员需要了解这一点。
更新:
There's very good reason it was not added before - it was not a supported abstraction for application use.
这仍然没有授予他们打破向后兼容性的许可。
而且,必须为特殊应用程序(例如,那些与给定设备驱动程序密切合作的应用程序)合成缺失的功能
For a long time
15 岁以上 ...
glibc was entertaining the idea of possible thread models where the kernel tid would not be an invariant for the thread lifetime.
内核对pthread_t
一无所知。它只知道 tid
。这就是应用程序必须与内核通信的方式(例如 tgkill
)。
内核的 模型中没有任何东西会改变 tid
中游,就像它不会改变 pid
中的进程一样执行到一半。
那是因为内核将 tid
当作 pid
来进行调度。每个进程和每个线程都有一个任务结构 [indexed/identified by pid/tid
]。
否则,将需要对所有内核调度程序、task/thread 层次结构等进行大修。因此,glibc
不可能单独完成这项工作。而且,为了什么目的?
在创建线程的 clone
系统调用之后 [可以选择使用相同的地址 space],这在很大程度上是一个不可见的区别,线程在被调度时获得相同的权重 [基于关于调度程序和任务优先级。
这是内核方法的一大好处:tasks/threads 是 第一 class 公民[不同于 WinX]。
旁注: 我必须编写实时嵌入式 H/W H.264 视频编码器,并且必须处理 nptl
[即linuxthreads
(?)] 它导致了有关吞吐量和延迟的严重问题。幸运的是,nptl
在我们不得不发布之前出现了。区别是白天和黑夜。
It was only after relatively recent discussions that it was deemed ok.
内核[and/orPOSIX]定义了语义,而不是glibc
。 glibc 开始遵循和实施,而不是命令。
而且,因为 glibc
人们顽固 [并且 令人讨厌 ],并且花了 15 年时间才决定 [ 显而易见 ], IMO,他们在这件事上失去了任何讨价还价的权利。
手册页中有关该函数的信息有误。而不是 #include <sys/types.h>
,而是这样做:
#define _GNU_SOURCE
#include <unistd.h>
我向手册页邮件列表发送了一封电子邮件,要求更正此问题。
man page and SO post#1/SO post#2 都表明 gettid()
是在 glibc 2.30 中实现的。根据 ldd --version
,我想我正在使用 GLIBC 2.30-8,但 gcc
仍然抱怨 - 警告:函数 'gettid 的隐式声明';您指的是 ‘getgid’ 吗? [-Wimplicit-function-declaration]。我可以忽略警告,程序运行正常。
我尝试与 gettid()
一起使用的 header 是 <sys/types.h>
,遵循手册页。我错过了什么吗?
使用 header <sys/syscall.h>
调用 syscall(SYS_gettid)
不会触发来自 gcc
的警告。
注意:这太新了,没有某些条件不应该依赖它。而且,可能 永远不会 值得信赖。
见下文。
2019 年 2 月之前,联机帮助页是这样说的:
发件人:man gettid
:
Note: There is no glibc wrapper for this system call; see NOTES.
并且,来自注释:
Glibc does not provide a wrapper for this system call; call it using
syscall(2)
.
有关详细信息,请参阅注释部分的其余部分。这是因为他们希望您使用其他 pthread_self
兼容的东西。
我个人不同意 glibc
quirk/philosophy。
因为,有时需要使用real/linux tid
值。
新方法是[截至 2019 年 2 月,据 Joseph 称]:
#define _GNU_SOURCE
#include <unistd.h>
获得gettid
声明。
但是...
这 永远不会 [没有 #if/#ifdef
] 因为 gettid
系统调用 已经被大约从 linux 2.4 开始,大约在 2004 年。
因此,添加包装函数花了glibc
15年!?!? :-( IMO,太少,太晚了。
使用新方法时,它会破坏与那 15 年期间发布的所有发行版的向后兼容性。
所以,忽略这一点并继续使用 syscall
是可行的方法。这是保持 forward/backward 兼容性的最简单 方法。
我们可以创建包装器,但它更复杂[类似于]:
#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
事实上,它比这更复杂,因为我们必须确保我们有 __GLIBC_PREREQ
[and __GLIBC__
and __GLIBC_MINOR__
] before[的定义=158=] 我们开始包括东西。
而且,要做到这一点是有问题的。所以,一个人可能会被迫总是做:
#define _GNU_SOURCE
#include <unistd.h>
然后,然后 添加 #if
。或者,无论实际的神秘方式是什么[我无法亲自测试,因为我在使用旧方法的系统上]。
混乱,[IMO]不值得麻烦。
而且,情况更糟。
由于旧方法已经存在了很长时间,许多应用程序已经定义了自己的 gettid
包装函数。所以,新声明可能会与此冲突。
因此,开发人员无需执行任何操作即可重新编译他们的[以前]工作代码,并且构建现在会出错。
为了防止这种情况,unistd.h
应该 仅 声明 gettid
如果用户在包含它之前放置了一些 #define
(类似于_GNU_SOURCE
) 喜欢:
#define _DECLARE_GETTID
#include <unistd.h>
而且,由于新方法打破了 15 年的兼容性,联机帮助页需要记录这一事实并解释旧方法。
因为,尝试编写跨平台代码、跨多个内核版本和多个 glibc
版本的开发人员需要了解这一点。
更新:
There's very good reason it was not added before - it was not a supported abstraction for application use.
这仍然没有授予他们打破向后兼容性的许可。
而且,必须为特殊应用程序(例如,那些与给定设备驱动程序密切合作的应用程序)合成缺失的功能
For a long time
15 岁以上 ...
glibc was entertaining the idea of possible thread models where the kernel tid would not be an invariant for the thread lifetime.
内核对pthread_t
一无所知。它只知道 tid
。这就是应用程序必须与内核通信的方式(例如 tgkill
)。
内核的 模型中没有任何东西会改变 tid
中游,就像它不会改变 pid
中的进程一样执行到一半。
那是因为内核将 tid
当作 pid
来进行调度。每个进程和每个线程都有一个任务结构 [indexed/identified by pid/tid
]。
否则,将需要对所有内核调度程序、task/thread 层次结构等进行大修。因此,glibc
不可能单独完成这项工作。而且,为了什么目的?
在创建线程的 clone
系统调用之后 [可以选择使用相同的地址 space],这在很大程度上是一个不可见的区别,线程在被调度时获得相同的权重 [基于关于调度程序和任务优先级。
这是内核方法的一大好处:tasks/threads 是 第一 class 公民[不同于 WinX]。
旁注: 我必须编写实时嵌入式 H/W H.264 视频编码器,并且必须处理 nptl
[即linuxthreads
(?)] 它导致了有关吞吐量和延迟的严重问题。幸运的是,nptl
在我们不得不发布之前出现了。区别是白天和黑夜。
It was only after relatively recent discussions that it was deemed ok.
内核[and/orPOSIX]定义了语义,而不是glibc
。 glibc 开始遵循和实施,而不是命令。
而且,因为 glibc
人们顽固 [并且 令人讨厌 ],并且花了 15 年时间才决定 [ 显而易见 ], IMO,他们在这件事上失去了任何讨价还价的权利。
手册页中有关该函数的信息有误。而不是 #include <sys/types.h>
,而是这样做:
#define _GNU_SOURCE
#include <unistd.h>
我向手册页邮件列表发送了一封电子邮件,要求更正此问题。