Linux C:после получения сигнала можно ли узнать PID отправителя?
предположим, что моя программа C обрабатывает SIGUSR1. Когда он получает сигнал, можно ли узнать, кто его послал? И. Е. чтобы получить pid этого процесса?
4 ответов
да, если вы используете sigaction
вызов для настройки обработчика сигнала вместо signal
. Это позволит вам настроить обработчик сигналов, который принимает три параметра:
- An
int
, для номера сигнала (так же, какsignal
) - A
siginfo_t *
, который представляет собой структуру, содержащую все виды информации об источнике сигнала, включая pid отправителя, если это применимо. (Он также включает некоторую информацию о причине сигнала для автоматического сигналы типаSIGSEGV
.) - A
ucontext_t *
, что связано с тем, какой поток получил сигнал. В основном игнорируется.
другой вариант-это использовать signalfd()
. Если вы используете сигналы для передачи информации между процессами, то, скорее всего, вам нужна более структурированная обработка сигналов, чем обработчики сигналов. struct signalfd_siginfo::ssi_pid
- это отправитель.
пример из man-страницы:
#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()
, но вы можете передать целое число или указатель в том же вызове.
вот полный пример POSIX-standard sigaction()
API:
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
void sigusr1(int signo, siginfo_t *si, void *data) {
(void)signo;
(void)data;
printf("Signal %d from pid %lu\n", (int)si->si_signo,
(unsigned long)si->si_pid);
exit(0);
}
int main(void) {
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = sigusr1;
if (sigaction(SIGUSR1, &sa, 0) == -1) {
fprintf(stderr, "%s: %s\n", "sigaction", strerror(errno));
}
printf("Pid %lu waiting for SIGUSR1\n", (unsigned long)getpid());
for (;;) {
sleep(10);
}
return 0;
}
попробуйте запустить его, а затем отправить его SIGUSR1 (например,kill -SIGUSR1 that-pid
от снаряда)
sigaction
функция:http://pubs.opengroup.org/onlinepubs/009604499/functions/sigaction.html
siginfo
структура:http://pubs.opengroup.org/onlinepubs/009604499/basedefs/signal.h.html