Игнорирование SIGCHLD в некоторых случаях, но не в других

StackOverflow https://stackoverflow.com/questions/631641

  •  08-07-2019
  •  | 
  •  

Вопрос

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

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

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

Это было полезно?

Решение

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

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

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

Другие советы

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top