2013-02-28 4 views
2

Итак, это проблема im, имеющая прямо сейчас, я создал две разные программы (1 будет управлять другой, а другая будет выполняться несколько раз). Программы будут передавать назад и вперед через сигналы. Мой вопрос: возможно ли (и как) получить идентификатор процесса программы, отправляющего сигнал. Мои программы используют сигнал() для обнаружения сигналов и kill() для их отправки.C - Получить идентификатор процесса сигнализации

ответ

2

Не использовать signal(), это устарело. Если у вас это есть, используйте вместо этого sigaction(), он предоставляет интерфейс для получения идентификатора процесса отправителя.

+1

Это не поймает сигкилл и сигстоп. Например, если вы нажмете ctrl + c из второго процесса, он не будет пойман sigaction(). –

+0

yah thats fine, как я его поймаю sigaction()? – Chris

+0

@Chris: для примера 'sigaction()' s наряду с освещением som при обработке сигналов, взгляните на [эту статью] (http://lazarenko.me/2013/01/15/how-not-to-write -a-signal-handler /), что я написал некоторое время назад. – 2013-02-28 14:48:04

3

Хотя сигнал() находится в стандартной библиотеке C, эта функция не переносима, ее поведение зависит от системы. Лучше использовать sigaction(), который является POSIX.1.

Вот пример того, как использовать sigaction с обработчиком ничтожной ч (ИНТ сиг):

int mysignal (int sig, void (*h)(int), int options) 
{ 
    int r; 
    struct sigaction s; 
    s.sa_handler = h; 
    sigemptyset (&s.sa_mask); 
    s.sa_flags = options; 
    r = sigaction (sig, &s, NULL); 
    if (r < 0) perror (__func__); 
    return r; 
} 

варианты описаны в человеке sigaction. Хороший выбор - options=SA_RESTART.

Чтобы узнать PID процесса, который отправил сигнал, установите options=SA_SIGINFO и используйте обратный вызов sa_sigaction вместо sa_handler; он получит структуру siginfo_t, имеющую поле si_pid. Вы можете связать данные с сигналом, используя sigqueue.

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

1

Чтобы получить идентификатор процесса, отправляющего сигнал, необходимо включить в свои параметры SA_SIGINFO. Если вы это сделаете, интерфейс для sigaction немного отличается. Вот пример правильного обработчика и его установки. (Я включаю SA_RESTART как вариант только потому, что, как правило, хорошая идея, но это не обязательно)

// example of a handler which checks the signalling pid 
void handler(int sig, siginfo_t* info, void* vp) { 
    if (info->si_pid != getpid()) { 
    // not from me (or my call to alarm) 
    return; 
    } 
    // from me. let me know alarm when off 
    alarmWentOff = 1; 
} 

Вот мой общий код для настройки обработчика:

typedef void InfoHandler(int, siginfo_t *, void *); 

InfoHandler* 
SignalWithInfo(int signum, InfoHandler* handler) 
{ 
    struct sigaction action, old_action; 

    memset(&action, 0, sizeof(struct sigaction)); 
    action.sa_sigaction = handler; 
    sigemptyset(&action.sa_mask); /* block sigs of type being handled */ 
    action.sa_flags = SA_RESTART|SA_SIGINFO; /* restart syscalls if possible */ 

    if (sigaction(signum, &action, &old_action) < 0) 
perror("Signal error"); 
    return (old_action.sa_sigaction); 
} 

и, наконец, для данного конкретного случая:

SignalWithInfo(SIGALRM, handler); 
-1

Это изменение теперь. Сигнальная информация показывает не 1 pid, а простой цифровой номер. Это соответствует процессу killall. Возможно, можно перечислить/proc/directories, когда вы найдете/proc/DIGIT, откройте/proc/DIGIT/comm, прочитайте и закройте его. Может быть, acueried имя будет «shutdown» или «reboot»

Смежные вопросы