【问题标题】:Why is kernel_sigset_t an undeclared identifier after including signal.h?为什么 kernel_sigset_t 在包含 signal.h 后是一个未声明的标识符?
【发布时间】:2020-03-21 01:43:44
【问题描述】:

signal.h 联机帮助页中,rt_sigprocmask 的原型如下:

/* Prototype for the glibc wrapper function */
   int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

/* Prototype for the underlying system call */
   int rt_sigprocmask(int how, const kernel_sigset_t *set,
              kernel_sigset_t *oldset, size_t sigsetsize);

看到kernel_sigset_trt_sigprocmask 的原型中,我假设这种类型的定义将包含在signal.h 中。但是当我尝试在我的程序中使用它时,我收到了 kernel_sigset_t 未声明的错误。

我写了一个简单的小程序来演示错误:

#include <stdio.h>
#include <signal.h>
int main()
{
    printf("%d\n", sizeof(kernel_sigset_t));
    return 0;
}

当我编译时会给出这个消息:

>gcc -o tmp tmp.c
tmp.c: In function ‘main’:
tmp.c:5:24: error: ‘kernel_sigset_t’ undeclared (first use in this function)
    5 |  printf("%d\n", sizeof(kernel_sigset_t));
      |                        ^~~~~~~~~~~~~~~
tmp.c:5:24: note: each undeclared identifier is reported only once for each function it appears in

为什么会这样? 我是不是包含了错误的东西,还是什么?


编辑:更多信息

我问这个问题的原因是因为我正在制作一个程序来跟踪两个并行运行的相同程序,并比较每个系统调用的参数以检查它们是否相等。

为此,我需要检查作为指针的系统调用参数是否指向两个跟踪程序中的相同数据。

因此,通过rt_sigprocmask 系统调用,我想检查kernel_sigset_t 指针setoldset 是否都指向相同的数据。我会通过比较这些指针指向的地址处的sizeof(kernel_sigset_t) 数据长度来做到这一点,并查看它们是否相同(使用process_vm_readv)。

但是,作为kernel_sigset_t,似乎没有定义,我不知道该怎么做。正如手册页所说,内核的sigset_t 和用户空间的大小不同:我应该如何知道要比较的正确大小是多少?如果我只使用sigset_t,是否正确,如果内核不同?

【问题讨论】:

  • 您使用的是什么系统和版本?我查看的linux/signal.h 文件没有定义rt_sigprocmask 也没有定义kernel_sigset_tUbuntu page for signal.h 似乎也没有定义它们。你有联机帮助页的链接吗?它可能与您的系统不对应。
  • &gt;cat /proc/version Linux version 5.3.0-kali2-amd64 (devel@kali.org) (gcc version 9.2.1 20191109 (Debian 9.2.1-19)) #1 SMP Debian 5.3.9-3kali1 (2019-11-20)
  • 您是否正在查看已安装源包中的标头?

标签: c include system-calls


【解决方案1】:

作为一般规则,包含头文件并不总是足够的,有时这些定义深埋在#idfef 层次结构中。

例如查看Linux doco for the sigprocmask call,可以看到需要的feature test macros

 _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _POSIX_SOURCE

意味着其中之一必须为真才能获得sigprocmask


但是,在这种特殊情况下,manpage 显示了最可能出现的问题。在详细说明glibc(用户空间)和内核调用之间的区别的部分中,我们看到(添加了重点):

sigset_t内核定义与 C 库使用的大小不同。在本手册页中,前者被称为kernel_sigset_t(在内核源代码中它仍然被命名为sigset_t)。

换句话说,它的名称与文档原型中显示的名称不同,不幸的是,它与用户空间中定义的名称相同。

如果您混合使用用户空间和内核方法,这可能会导致各种问题 - 我的建议是尽可能只使用用户空间的方法,而将内核的方法留给内核开发人员: -)

cursory investigation系统调用的rt变体(这不是用户空间函数)是添加以满足更大的信号集 - 一旦添加了实时信号,信号位掩码就会超过 32 位,因此必须扩展信号集。

用户空间函数会在后台智能地调用正确的系统调用,旧的系统调用仍然存在但已被弃用。该函数调用还将静默地阻止您摆弄 NPTL(本机 POSIX 线程库)使用的信号。


关于您的问题的更新,您在其中声明要跟踪系统调用以确保传入的参数相同,您实际上并不需要知道那个结构。

rt_sigprocmask 的工作方式是结构的长度实际上是 参数之一, sigsetsize。所以这就是你应该用来比较的大小。

【讨论】:

  • 我更新了我的问题,提供了针对我的问题的更多信息。
  • @NotAPro,请参阅我的答案的附录。实际长度作为最终参数传入,因此您可以使用它。
猜你喜欢
  • 1970-01-01
  • 2022-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多