Будет ли выход из программы автоматически закрывать трубу?

Скажем, я создаю канал между дочерним и родительским процессами, и дочерний процесс завершается нормально, будут ли каналы дочернего процесса автоматически закрыты?

Кроме того, если у дочернего процесса также есть дочерний процесс, и дочерний процесс завершается ошибкой сегментации, убьет ли он мой внучатый процесс? Я имею в виду удалить его из таблицы процессов (мне не нужно его ждать).

РЕДАКТИРОВАТЬ: Например, для следующего кода я генерирую ошибку сегментации в дочернем процессе и пытаюсь дождаться ее в родительском процессе. После того, как я запустил программу, waitpid возвращает -1, но когда я проверяю WIFEXITED (статус), кажется, что программа дочернего процесса завершается нормально. И я получил

Не удалось убить дочерний процесс: такого процесса нет

ошибка, попробуйте убить мой внучатый процесс. Интересно, это потому, что ошибка сегментации автоматически закрывает как дочерний, так и внучатый процесс?

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>


int main( void ) {

    pid_t childpid;
    int ends[ 2 ];
    pipe( ends );
    if ( ( childpid = fork() ) == -1 ) {
        perror( "fork failed" );
        exit( 0 );
    }
    if( childpid == 0 ) {
        pid_t cpid;
        if ( ( cpid = fork() ) == -1 ) {
            perror( "fork failed" );
            exit( 0 );
        }
        if ( cpid == 0 ){
            while(1);
        }   
        else{
            printf("cpid is : %d\n",cpid);
            char msg[32];
            sprintf( msg, "%d", cpid );
            printf("cpid con is : %s\n", msg);
            if( write( ends[ 1 ], msg, 32 ) == -1 ) {
                perror( "Write failed" );
                exit( 0 );
            }
            char *s = NULL;
            *s = 15;
            while(1);
        }
    }
    else{
        printf("childpid is : %d\n",childpid);
        char msg[ 32 ];
        int cpid;
        if( read( ends[0], msg,32 ) == -1 ) {
            perror("read failed");
            exit( 0 ); 
        }
        cpid = atoi( msg );
        int status;
        while(1) {
            if ( waitpid( childpid, &status, WNOHANG ) == -1 ) {
                //printf( "%d\n", WIFEXITED(status) );
                if ( kill( cpid, 9 ) == -1 ) {
                    perror( "Killing child process failed" );
                    exit( 0 );
                }
                /*if ( kill( cpid, 9 ) == -1 ) {
                    perror( "Killing child process failed" );
                    exit( 0 );
                }*/

            }
        }
    }
    return 0;
}

person user5574376    schedule 08.03.2016    source источник
comment
Да к первому. Нет ко второму.   -  person kaylum    schedule 09.03.2016
comment
Внимательно посмотрите на последний цикл while. Вы ждете своего ребенка. Это ожидание, скорее всего, удастся с первой попытки. Статус вашего ребенка получен, и pid больше не принадлежит вам. Следующая итерация. Вы ждете pid, который вам не принадлежит — это ожидание обречено на неудачу. Вы пытаетесь убить внука — вам это удается. Следующая итерация. Ваше ожидание продолжает терпит неудачу, и теперь убийство тоже не удается. Вы выходите.   -  person PSkocik    schedule 09.03.2016
comment
Да я только пару секунд назад сообразил, такая глупая ошибка. Спасибо, в любом случае!   -  person user5574376    schedule 09.03.2016
comment
Что вы должны сделать, это while(waitpid(...)==-1) {;}. Также вы можете заменить эти другие while(1) ; на pause();. Избегайте SIGKILL (9), чтение и запись могут быть успешными частично, а pipe может дать сбой.   -  person PSkocik    schedule 09.03.2016
comment
если канал является «именованным каналом», то канал все еще будет существовать, но будет закрыт при сбое процесса. Если канал «не» является «именованным каналом», то канал исчезает при сбое процесса.   -  person user3629249    schedule 09.03.2016


Ответы (1)


ОС закроет все файловые дескрипторы, связанные с процессом, который умер или вышел. Если это закроет последний файловый дескриптор, указывающий на конец канала для чтения, то записи в конец для записи начнут генерировать SIGPIPE (fds — это ссылки с подсчетом ссылок на сущность vnode за ними).

Если родитель умрет, его дочерний элемент будет переродлен в init. init будет ждать его. (Бабушки и дедушки все равно не могут wait на внуков).

person PSkocik    schedule 08.03.2016
comment
Так будет ли init никогда не убивать дочерний процесс? Просто ждать, пока он не кончится? - person user5574376; 09.03.2016
comment
@user5574376 user5574376 Верно. Процесс по-прежнему будет принадлежать группе процессов и может быть уничтожен, потому что эта группа процессов, например, отправила SIGINT через управление заданиями (^C) или SIGHUP, когда процесс переходит в спящий режим, а его группа процессов становится потерянной группой процессов. - person PSkocik; 09.03.2016
comment
Я понимаю, что когда дочерний процесс завершается нормально, мой дочерний процесс будет принят init, но что произойдет, если дочерний процесс вызовет ошибку seg. Когда я пытаюсь убить дочерний процесс через его pid после того, как мой дочерний процесс генерирует ошибку сегментации. У меня нет такой ошибки процесса. Но когда я не генерировал ошибку seg и просто убивал дочерний процесс, я мог успешно убить дочерний процесс без такой ошибки процесса. - person user5574376; 09.03.2016
comment
Неважно, чем закончится процесс. Если это ребенок переживет это, ребенок получит reparented. Если у вас есть конкретный вопрос с конкретным фрагментом кода, задайте его. - person PSkocik; 09.03.2016