Почему kernel_sigset_t является необъявленным идентификатором после включения signal.h? - PullRequest
1 голос
/ 21 марта 2020

Из справочной страницы 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_t находится в прототипе для rt_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 set и oldset оба указывают на одни и те же данные. Я бы сделал это, сравнив длину данных sizeof(kernel_sigset_t) по адресам, указанным этими указателями, и выяснил, совпадают ли они (используя process_vm_readv).

Однако, как и kernel_sigset_t, это казалось бы, не определено, я не знаю, как это сделать. Как говорится на странице руководства, ядро ​​sigset_t и пользовательское пространство имеют разные размеры: как мне узнать, какой правильный размер сравнивать? Если я просто использую sigset_t, будет ли правильно, если ядро ​​будет другим?

1 Ответ

0 голосов
/ 21 марта 2020

Как правило, не всегда достаточно включить заголовочный файл, иногда эти определения находятся глубоко внутри #idfef иерархий.

Например, при проверке документа Linux для sigprocmask вызов , вы можете увидеть необходимые макросы тестирования функции :

 _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _POSIX_SOURCE

, означающие, что один из них должен быть истинным, чтобы получить sigprocmask.


Однако в данном конкретном случае manpage показывает наиболее вероятную проблему. В разделе, детализирующем различия между glibc (пространство пользователя) и вызовами ядра, мы видим (выделение добавлено):

определение *1022* ядра sigset_t отличается по размеру из того, что используется библиотекой C. На этой странице руководства первая упоминается как kernel_sigset_t (в источниках ядра она все же называется sigset_t).

In другими словами, оно имеет имя, отличное от того, которое показано в документированном прототипе, и, к сожалению, такое же имя, как и определенное в пользовательском пространстве.

Это может привести к возникновению всевозможных проблем, если вы смешаете Методы пользовательского пространства и ядра - я бы порекомендовал просто использовать методы пользовательского пространства, если это возможно, и оставить ядро ​​разработчикам ядра: -)

Из поверхностного исследования , rt вариант системного вызова (это не функция пользовательского пространства) был добавлен для обслуживания большего набора сигналов - после добавления сигналов реального времени битовая маска сигнала превысила 32 бита, поэтому набор сигналов пришлось расширить.

Пользовательское пространство Функция будет разумно назвать правильный системный вызов под одеялом, и старая система вызов все еще там, но не рекомендуется. Этот вызов функции также будет молча препятствовать тому, чтобы вы возились с сигналами, используемыми NPTL, собственной библиотекой потоков POSIX.


В отношении обновлений вашего вопроса, в которых вы заявляете, что хотите отслеживать систему вызовы, чтобы убедиться, что переданные аргументы одинаковы, вам на самом деле не нужно , чтобы узнать размер этой структуры.

Способ rt_sigprocmask работает так: длина структуры на самом деле является одним из аргументов, sigsetsize. Так что это размер, который вы должны использовать для сравнения.

...