Предположим, что моя программа 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(), но вы можете передать целое число или указатель в том же вызове.