Чтение от одного дочернего процесса блокирует других детей - PullRequest
0 голосов
/ 16 марта 2020

Как вы можете видеть из кода, которым я поделился ниже, я пытаюсь реализовать 1 центральный сервер и n детей. Сначала я создаю всех n детей, разветвляясь с сервера. Также перед разветвлением я создаю двунаправленные трубы, используя Pipe. Разветвив и создав n детей, я хочу читать символы из дочерних кодов. Все они посылают символ «А», но я могу читать только от одного ребенка. Я использую опрос, чтобы выбрать активных детей и пытаюсь прочитать данные из них. Что может вызвать блокировку программы на одном ребенке? Я буду признателен за любую помощь.

#define Pipe(fd) socketpair(AF_UNIX, SOCK_STREAM, PF_UNIX, fd)
int n = 5;    
struct pollfd pfd[n];

for (int i = 0; i < n; i++){
    Pipe(fd[i]);
    if (fork() == 0){
        close(fd[i][0]);
        dup2(fd[i][1], 0);
        dup2(fd[i][1], 1);
        close(fd[i][1]);
        execl(code, arguments);
    }

    else {
        close(fd[i][1]);
        dup2(fd[i][0], 0);
        dup2(fd[i][0], 1);
        close(fd[i][0]);
    }

    struct pollfd s;
    s.fd = fd[i][1];
    s.events = POLLIN;
    s.revents = 0;
    pfd[i] = s;
}   

while(1){
    poll(pfd, n, 2);
    for (int i = 0; i < n; i++){
        if (pfd[i].revents && POLLIN){
            char data;
            read(0, &data, 1);

            if (data == 'A'){ 
            .
            .
            .
            }
        }
    } 
}

1 Ответ

0 голосов
/ 16 марта 2020

В родительском файле может быть только один стандартный дескриптор входного файла и один стандартный дескриптор выходного файла. Ваш код выглядит следующим образом:

for (int i = 0; i < n; i++){
    Pipe(fd[i]);
    if (fork() == 0){
        close(fd[i][0]);
        dup2(fd[i][1], 0);
        dup2(fd[i][1], 1);
        close(fd[i][1]);
        execv(code, arguments);
    }
    else {
        close(fd[i][1]);
        dup2(fd[i][0], 0);
        dup2(fd[i][0], 1);
        close(fd[i][0]);
    }
    …poll setup…
}

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

Вы не должны использовать dup2() в родителях; вам, вероятно, нужно держать дескрипторы файлов открытыми в массиве, чтобы использовать их для отдельного общения с детьми.

Я не рассмотрел, почему вы используете индексы [0] и [1] после fd[i] как вы, но это не так.

Вы должны поставить как минимум exit(1); или _exit(1); после вызова execv(); Я бы предпочел, чтобы сообщение об ошибке выводилось также на stderr, сообщая о сбое execv(). Вам не нужно проверять возвращаемое значение; если execv() возвращается, это не удалось; если это удастся, он не вернется. В противном случае, если execv() завершится неудачно, вы можете получить несколько процессов, все они думают, что они являются родителями. Это приводит к хаосу. Всегда следите за тем, чтобы не выполнять другие программы!

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