2017-01-20 14 views
1

В следующем коде я хочу, чтобы детишка c1 блоков (через трубу), пока ребенок c2 не сделал (по телефону pipe_close() в c2). Однако это не сработает. c1 будет блокироваться навсегда. Он работает, если я перемещаю pipe_close() из c2 и помещаю его в родительский.Доля труб между дочерними процессами детей и сестер

Это потому, что трубы, созданные из родителя, не могут быть разделены между дочерними процессами дочерних узлов?

#include <stdio.h> 
#include <errno.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <stdarg.h> 

static void pipe_close(int *); 
static void pipe_read(int *); 

int 
main(void) 
{ 
    int pp_main[2] = {-1, -1}; 
    pipe(pp_main); 

    int ppid = getpid(); 
    int pgid = getpgrp(); 

    int pid_c1 = fork(); 
    if (pid_c1 == 0) 
    { // in child c1 
     int cpid_c1 = getpid(); 
     int gid = getpgrp(); 
     printf("[c1][%d][%d] is made, wait pipe ready\n", cpid_c1, gid); 
     pipe_read(pp_main); 
     printf("[c1][%d][%d] done\n", cpid_c1, gid); 
    } 
    else 
    { // in parent 
     printf("[main][%d][%d] created child c1: %d\n", ppid, pgid, pid_c1); 
     int pid_c2 = fork(); 
     if (pid_c2 == 0) 
     { // in child c2 
      int cpid_c2 = getpid(); 
      int gid = getpgrp(); 
      printf("[c2][%d][%d] is made\n", cpid_c2, gid); 
      for (int i = 2; i > 0; --i) 
      { 
       printf("[c2][%d][%d] count down %d\n", cpid_c2, gid, i); 
       sleep(1); 
      } 
      pipe_close(pp_main); 
      printf("[c2][%d][%d] done\n", cpid_c2, gid); 
     } 
     else 
     { // in parent 
      printf("[main][%d][%d] created child c2: %d\n", ppid, pgid, pid_c2); 
     } 
     int status; 
     waitpid(pid_c2, &status, 0); 
    } 

    int status; 
    waitpid(pid_c1, &status, 0); 
    return 0; 
} 

static void 
pipe_read(int *pp) 
{ 
    char ch; 
    if (pp[1] >= 0) 
    { 
     close (pp[1]); 
     pp[1] = -1; 
    } 
    if (pp[0] >= 0) 
    { 
     while (read (pp[0], &ch, 1) == -1 && errno == EINTR); 
    } 
} 

static void 
pipe_close(int *pp) 
{ 
    if (pp[0] >= 0) 
     close (pp[0]); 
    if (pp[1] >= 0) 
     close (pp[1]); 
    pp[0] = pp[1] = -1; 
} 

ответ

1

Это работает, если я перееду pipe_close() из c2 и поместить его в родителя.

Ожидаемое поведение. Труба не полностью закрыта до все ссылки на нее закрыты. В вашем коде pipe создан до fork. Следовательно, как родительский, так и дочерний процессы открывают эту трубу. C2-ребенок выйдет, чтобы закрыть ссылки на канал. Однако родительский процесс блокирует ожидание выхода c1. Это никогда не произойдет, потому что родительский процесс явно или неявно (через выход) не закрывает трубку.

+0

О, человек, это все объясняет! большое спасибо! – mitnk