Как дочерний процесс убивает другой дочерний процесс, а затем завершается? - PullRequest
0 голосов
/ 11 января 2020

Вот код, в котором родительский процесс записывает строку ввода в канал, а дочерние процессы читают это из канала. Если дочерний процесс читает из канала слово «конец», то я хочу завершить все процессы и затем завершить себя, а если читает слово «фини sh», я хочу подать сигнал отцу за уничтожение всех процессов и затем выйдите. Я запустил код, и у меня была ошибка сегментации. Почему это неправильно?

#define _POSIX_SOURCE
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
void measure_time(int sig)
{
    printf("child [%d] received signal %d\n", getpid(), sig);
}
int main(int argc, char *argv[])
{
    int n_task = 4;
    pid_t pid;
    pid_t pid_array[n_task];
    int fd[2];
    for (int i = 0; i < n_task; i++)
    {
        pid = fork();
        if (pipe(fd) == -1)
        {
            perror(" pipe ");
            exit(1);
        }
        if (pid < 0)
        {
            perror("fork");
            exit(1);
        }
        if (pid == 0) //child
        {
            char *buf;
            close(fd[1]);
            read(fd[0], buf, 10);
            printf("I read: %s", buf);
            if (strcmp(buf, "end") == 0)
            {
                for (int i = 0; i < n_task; i++)
                    kill(pid_array[i], SIGUSR1);
            }else if(strcmp(buf,"finish") == 0){
                /*Here i want father to kill all children and then exit.*/
            }
            exit(0);
        }
        close(fd[0]);
        char *buf;
        printf("Give the input string: \n");
        scanf("%s", buf);
        write(fd[1], buf, strlen(buf));
        close(fd[1]);
        pid_array[i] = pid;
    }
    sleep(1);
    for (int i = 0; i < n_task; i++)
        wait(NULL);
    return (0);
}

Ответы [ 2 ]

1 голос
/ 11 января 2020

Кроме проблемы неинициализированной buf, идентифицированной @G. Sliepen, pipe() необходимо вызывать перед fork(), поскольку дескрипторы файлов остаются открытыми при разветвлении дочерних процессов. Так же работает конвейер.

Вы можете попробовать изменить фрагмент кода, чтобы поставить pipe() перед fork().

...
        if (pipe(fd) == -1)
        {
            perror(" pipe ");
            exit(1);
        }
        pid = fork();
        if (pid < 0)
        {
            perror("fork");
            exit(1);
        }
...

Пожалуйста, прочтите страницу руководства по pipe (2) , в котором представлен пример.

SO имеет этот пост fork () и pipe () в c также объяснили это.

Обновление для завершающего процесса (ов)

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

Кстати, вместо того, чтобы отправлять сигнал SIGUSR1, лучше отправлять сигнал SIGTERM. Хотя SIGUSSR1 может привести к завершению целевого процесса по умолчанию (см. signal (7) ).

до "fini sh", то есть уничтожить (или завершить) все дочерние процессы а также родительский процесс, вы можете просто убить родительский процесс. Все его потомки также были убиты. Или вы можете отправить сигнал той же группе процессов. См. kill (2) .

0 голосов
/ 11 января 2020

Вы объявляете указатель buf, но не инициализировали его. Последующие вызовы read() и scanf() не будут выполнены, поскольку указатель недействителен.

Необходимо убедиться, что buf инициализирован и указывает на допустимую память. Простой способ исправить ваш код - это:

char buf[10];
read(fd[0], buf, 10);

Если вы включите предупреждения компилятора с помощью -Wall, то компилятор предупредит вас об инициализированных переменных.

Знайте о потенциальных возможностях переполнение буфера: если вы объявите char buf[10], убедитесь, что вы никогда не будете записывать в него более десяти байтов. Кроме того, проверьте возвращаемое значение функций, таких как read(), write(), scanf(), чтобы убедиться в отсутствии ошибок, в противном случае содержимое буферов или выходных файлов может быть не таким, как ожидалось.

...