Linux C:после получения сигнала можно ли узнать PID отправителя?

предположим, что моя программа C обрабатывает SIGUSR1. Когда он получает сигнал, можно ли узнать, кто его послал? И. Е. чтобы получить pid этого процесса?

4 ответов


да, если вы используете sigaction вызов для настройки обработчика сигнала вместо signal. Это позволит вам настроить обработчик сигналов, который принимает три параметра:

  • An int, для номера сигнала (так же, как signal)
  • A siginfo_t *, который представляет собой структуру, содержащую все виды информации об источнике сигнала, включая pid отправителя, если это применимо. (Он также включает некоторую информацию о причине сигнала для автоматического сигналы типа SIGSEGV.)
  • A ucontext_t *, что связано с тем, какой поток получил сигнал. В основном игнорируется.

да. Зарегистрируйте обработчик сигналов с помощью sigaction с SA_SIGINFO флаг, заполнив


другой вариант-это использовать 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