Предположим, что моя программа C обрабатывает SIGUSR1. Когда он получает сигнал, можно ли узнать, кто его отправил? То есть,. получить pid этого процесса?
Linux C: после получения сигнала можно ли узнать идентификатор отправителя?
Ответ 1
Да, если вы используете вызов sigaction
для настройки вашего обработчика сигнала вместо signal
. Это позволит вам настроить обработчик сигнала, который принимает три параметра:
- An
int
, для номера сигнала (точно так же, какsignal
) - A
siginfo_t *
, который представляет собой структуру, содержащую все виды информации об источнике сигнала, включая pid отправителя, если применимо. (Он также содержит некоторую информацию о причине сигнала для автоматических сигналов типаSIGSEGV
.) - A
ucontext_t *
, который связан с тем, какой поток получил сигнал. В основном игнорируется.
Ответ 2
Да. Зарегистрируйте обработчик сигнала, используя sigaction
с флагом SA_SIGINFO
, заполняя поле sa_sigaction
. Теперь ваша функция обработчика принимает параметр siginfo_t*
, который включает в себя поле si_pid
.
Обратите внимание, что si_pid
устанавливается только при некоторых обстоятельствах. В вашем случае вам нужно проверить, что для параметра si_code
установлено значение SI_USER
или SI_QUEUE
. Подробнее читайте man 2 sigaction
.
Ответ 3
Другой вариант - signalfd()
. Если вы используете сигналы для передачи информации между процессами, то более структурированная обработка сигналов, чем обработчики сигналов, скорее всего, то, что вы хотите. struct signalfd_siginfo::ssi_pid
- отправитель.
Пример из справочной страницы:
#include <sys/signalfd.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
int main(int argc, char *argv[]) {
sigset_t mask;
int sfd;
struct signalfd_siginfo fdsi;
ssize_t s;
sigemptyset(&mask);
sigaddset(&mask, SIGINT);
sigaddset(&mask, SIGQUIT);
/* Block signals so that they aren't handled
according to their default dispositions */
if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
handle_error("sigprocmask");
sfd = signalfd(-1, &mask, 0);
if (sfd == -1)
handle_error("signalfd");
for (;;) {
s = read(sfd, &fdsi, sizeof(struct signalfd_siginfo));
if (s != sizeof(struct signalfd_siginfo))
handle_error("read");
if (fdsi.ssi_signo == SIGINT) {
printf("Got SIGINT\n");
} else if (fdsi.ssi_signo == SIGQUIT) {
printf("Got SIGQUIT\n");
exit(EXIT_SUCCESS);
} else {
printf("Read unexpected signal\n");
}
}
}
См. также: sigqueue()
. Как kill()
, но вы можете передать целое число или указатель в том же вызове.