вилка () и труба () - PullRequest
       29

вилка () и труба ()

1 голос
/ 31 октября 2009

Мне нужна помощь с этим примером приложения. Когда я запускаю его, он застревает после того, как дочерний процесс печатает «Child child!».

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>

#define INPUT 0
#define OUTPUT 1
int main()
{
    int fd1[2];
    int fd2[2];
    int pid;
    if (pipe(fd1) < 0)
        exit(1);
    if (pipe(fd2) < 0)
        exit(1);
    if ((pid = fork()) < 0)
    {
        perror("fork");
        exit(1);
    }
    else if (pid == 0)
    {
        close(fd1[INPUT]);
        close(fd2[OUTPUT]);
        char *str = "Hello World!";
        printf("Child sending!\n");
        write(fd1[OUTPUT], str, strlen(str));
        char *bufferc = (char *)malloc(1000);
        char *readbufferc = (char *)malloc(80);
        int rdc;
        int gotdata = 0;
        while (gotdata == 0)
             while ((rdc = read(fd2[INPUT], readbufferc, sizeof(readbufferc))) > 0)
             {
               strncat(bufferc,readbufferc,rdc);
               gotdata = 1;
             }
        printf("Child received: %s",bufferc);
        free(readbufferc);
        free(bufferc);
        exit(0);
    }
    else
    {
        close(fd1[OUTPUT]);
        close(fd2[INPUT]);
        int rd;
        char *buffer = (char *)malloc(1000);
        char *readbuffer = (char *)malloc(80);
        int gd = 0;
        while (gd == 0)
             while ((rd = read(fd1[INPUT],readbuffer, sizeof(readbuffer))) > 0)
             {
               strncat(buffer, readbuffer,rd);
               gd = 1;
             }
        printf("Parent received: %s\n",buffer);
        free(readbuffer);
        printf("Parent sending!");
        write(fd2[OUTPUT], buffer, strlen(buffer));
        free(buffer);
    }
    return 0;
}

Кстати, есть ли способ отладки, когда я использую fork, потому что GDB автоматически переходит к родительскому процессу

Ответы [ 4 ]

4 голосов
/ 01 ноября 2009

После того, как дочерний объект пишет родителю, он должен закрыть конец записи канала, чтобы родитель знал, что он достиг EOF.

1 голос
/ 31 октября 2009

В вашем коде много ошибок. Почему вы используете fd2 без инициализации? Убери это. Теперь он застрял в «Child child», потому что чтение канала является блокирующим вызовом, и вы помещаете его в цикл while, который никогда не вернется. Пожалуйста, обратитесь к справочной странице трубы.
Если вы хотите разорвать этот цикл while, закройте все концы записи этого канала.

Также для отладки дочернего процесса используйте команду gdb follow-fork-mode в качестве дочернего процесса перед вызовом fork () во время отладки.

1 голос
/ 31 октября 2009

Несколько неправильных вещей:

  • fd2 просто никогда не инициализируется.

  • Родитель никогда не выйдет из этого:

    while ((rd = read(fd1[INPUT],readbuffer, sizeof(readbuffer))) > 0)
    {
        strncat(buffer, readbuffer,rd);
        gd = 1;
    }
    

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

0 голосов
/ 31 октября 2009

Вы звоните read() в ожидании, что если нечего читать, он вернется с нулевым прочитанным байтом. Однако то, что вы видите, это то, что read() ждет некоторых данных перед возвратом. Чтобы решить эту проблему, вам нужно сделать одно из двух:

  • установить сокет на неблокирующий читает (не рекомендуется)
  • используйте select() или poll(), чтобы увидеть, есть ли какие-либо данные для чтения, прежде чем вы их прочитаете

Также несколько других пунктов:

...