Игнорирование SIGCHLD в некоторых случаях, но не в других - PullRequest
3 голосов
/ 10 марта 2009

В моей программе я выполняю fork () несколько раз в зависимости от ввода пользователя.

В некоторых случаях я хочу обработать SIGCHLD и сказать что-то вроде «Процесс # Закончен». Однако в других случаях я хочу игнорировать этот сигнал.

Как я могу это сделать?

Ответы [ 4 ]

4 голосов
/ 10 марта 2009

Обработка сигналов настроена глобально для процесса. Если вы хотите перехватить асинхронный сигнал, такой как SIGCHLD, когда некоторые дочерние элементы заканчивают работу, но не другие, вы не можете решить игнорировать его заранее для некоторых.

Вам нужно будет обрабатывать сигнал каждый раз в родительском элементе, а затем решить, хотите ли вы игнорировать его в своем обработчике.

Как минимум, ваш обработчик должен выполнить wait () для дочернего элемента (si_pid в структуре siginfo_t), чтобы получить его код возврата. В этот момент вы можете проверить идентификатор процесса и решить, что еще делать. Вам не нужно ничего печатать, если вы не хотите.

3 голосов
/ 11 марта 2009

Вы хотите перехватить сигнал SIGCHLD и затем вызвать функцию. Вы хотите использовать signal() для этого (man signal). В приведенном ниже примере child_died() вызывается после перехвата сигнала SIGCHLD (дочерний процесс на этом этапе не работает). Если есть информация, которую вам нужно передать от дочернего элемента к родительскому элементу, который необходим child_died() для условного выражения, вам необходимо использовать канал (man pipe). Вот пример сигнала и трубы:

#include <signal.h>
#include <strings.h>
#include <stdio.h>

#define MAX_SIZE 256

void child_died(int);

int fd[2];

int main()
{
    int pid;
    extern int fd[];
    char *str;

    pipe(fd);
    signal(SIGCHLD, child_died);

    if ((pid = fork()) < 0) {
        // error
        printf("Error\n");
    } else if (pid == 0) {
        // child
        printf("In child process\n");
        close(fd[0]);
        str = strdup("Message from child process.\n");
        write(fd[1], str, strlen(str) + 1);
    } else {
        // parent
        wait();
        printf("Now in parent\n");
    }

    return 0;
}

void child_died(int s)
{
    char *str;
    close(fd[1]);
    read(fd[0], str, MAX_SIZE);
    printf("%s", str);
}

Сохранено как sigchld.c и скомпилировано с: gcc -Wall sigchld.c -o sigchld

Если вы хотите передать int (например, дочерний pid) или какой-либо другой тип данных из дочернего процесса в родительский процесс, вам нужно будет либо преобразовать его в строку и обратно, либо найти другой способ сделать это. это.

Если вы хотите игнорировать SIGCHLD, то в моем примере вы поместите эту логику в child_died(). Просто используйте простой if. Я не знаю, как вы решаете, когда игнорировать сигнал, а когда печатать то, что вы хотите, поэтому я включил материал канала в мой код выше. Я подумал, что вы будете использовать некоторую информацию из дочернего процесса, и, поскольку child_died() вызывается для родительского процесса, вам потребуется способ передачи данных из дочернего процесса в родительский процесс.

Надеюсь, это поможет. Могут быть лучшие или более простые способы достижения этого, о которых я не знаю. Если есть, пожалуйста, прокомментируйте.

2 голосов
/ 10 марта 2009

Вы можете использовать функцию waitpid в режиме блокировки или неблокирования, чтобы дождаться сигнала от данного потомка и затем выполнить некоторую обработку. На самом деле, у вас есть для использования wait, как указано в ответе Грэма ...

0 голосов
/ 10 марта 2009

Если вы игнорируете SIGCHLD, таблица процессов заполнится зомби.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...