2011-02-04 4 views
0
void doWork(){ 

    int fd[2]; 
    int pret = pipe(fd); 

    close(0); 
    close(1); 
    int dret = dup2(fd[1], 1); 
    close(fd[1]); 

    while(1){ 

    char buf[256]; 
    system("whoami"); 
    int rret = read(fd[0], buf, 256); 

    if(/* something interesting */){ 
     return; 
    } 
    } 
} 

int main(int argc, char* argv[]){ 

    int children = 2; 

    for(unsigned work = 0; work < children; ++work){ 

    pid_t pid = fork(); 

    if(pid == 0){ 
     doWork(); 
     break; 
    } 
    } 
    int status; 
    wait(&status); 

    return 0; 
} 

이 예제에는 어떤 문제가 있습니까? 각 자식 프로세스가 외부 프로그램을 호출하도록 한 다음 파이프에서 해당 프로그램의 출력을 읽으려고합니다. 내 코드는 자식이 1로 설정된 경우에만 작동합니다.병렬 포크 파이프

편집 : fork/pipe를 사용하여 작업 병렬 처리를 수행하려고합니다. 상위 프로세스와 하위 프로세스 간에는 통신이 없습니다. 각 하위 프로세스는 외부 프로그램을 실행하고 출력을 읽고 출력을 처리 한 다음 원하는 출력이 발견 될 때까지 계속합니다.

+0

몇 명의 어린이에게 어떤 문제가 있습니까? 그 행동을 설명해 주시겠습니까? –

+0

나는 전에 말한 것을 되돌립니다. 여러 자식 프로세스가 있으면 정상적으로 실행됩니다. 문제는 둘 이상의 자식 프로세스에서 프로그램이 더 빨라야하지만 완료하는 데 오랜 시간이 걸리지 만 단 하나의 자식 프로세스 만 있으면 단 몇 초만 걸립니다. SunOS 5.10에서 실행하고 있습니다. 어쩌면 그것과 관련이 있나? – Arlen

답변

6

fork() 전에 파이프를 만들어야합니다. 코드에서 자식 프로세스 만 파이프를가집니다. 공유하려면 두 프로세스가 모두 필요합니다.

예는 :

int fd[2]; 
pid_t pid; 

if (pipe(fd)) { /* TODO: handle error */ } 

pid = fork(); 
if (pid < 0) { /* TODO: handle error */ } 

if (pid == 0) 
{ 
    /* We are the child. Set fd[1] as stdout. */ 
    if (dup2(fd[1], 1)) { /* TODO: handle error */ } 

    /* Close fd[0]; this process doesn't need it. */ 
    close(fd[0]); 

    do_work(); 
    exit(0); 
} 
else 
{ 
    /* We are the parent... */ 
    /* Close the other guy's write fd. */ 
    close(fd[1]); 

    /* Now read from fd[0] */ 
    /* Possibly waitpid() on child pid, etc. */ 
} 

또한 : 나는 fork() 전에 fflush(stdout); 전화를 좋아한다. 그렇지 않으면 printf()으로 이상한 행동을 관찰하게됩니다.

+0

자식 프로세스는'fd [1]'을 stdout에 복사 한 후에도 필요하지 않으므로 닫아야합니다. – caf

+0

@caf - 동의합니다. 하지만'fd [0]'을 닫지 않으면 더 나쁜 결과를 낳습니다. 그래서 항상 그렇게 할 것입니다. 'fd [0]'을 닫으면 부모가 죽으면'fd [1]'에'SIGPIPE'를 쓰게됩니다. 그러나 만약 당신이 프로세스에서'fd [0]'으로 그 상황에 빠지면, 파이프의 버퍼가 꽉 찼다면 멈출 수 있습니다. OTOH'fd [1]'은 프로세스 종료시에 닫혀서 열어 두는 것이별로 중요하지 않습니다. – asveikau

+0

죄송합니다.하지만 도움이되지 않습니다. 파이프와 포크로 작업 병렬 처리를 달성하려고합니다. 각 자식 프로세스는 'system()'호출을합니다. 외부 프로그램의 출력은 파이프로 방향 재 지정되어 읽을 수 있고 처리 할 수 ​​있습니다. 그 아이는 "흥미로운"것이 발생할 때까지이 반복을 계속합니다. 내 코드의 문제는 여러 자식 프로세스가 서로 간섭하는 것 같습니다. – Arlen

1

하위 프로세스를 실행하고 콘텐츠를 구문 분석하고 해석 한 다음 종료 할 하위를 생성하려고합니까? 그렇다면 만들려는 각 작업마다 fork 두 번 필요합니다. 하위 프로세스의 결과를 처리 할 하위 클래스를 처음 생성하면 두 번째 하위 프로세스를 시작할 수 있습니다. 그런

뭔가 :

void ExecuteCommandAndInterpretResult(const char* command) 
{ 
    int fd[2]; 
    if (pipe(fd)) 
     exit(1); 

    pid_t pid = fork(); 
    if (pid < 0) 
     exit(1); 

    if (pid == 0) 
    { 
     if (dup2(fd[1], 1)) 
      exit(1); 

     close(fd[0]); 
     execl(command, basename(command), NULL); 
     exit(1); 
    } 
    else 
    { 
     int status; 

     close(fd[1]); 
     // do something with output from command 

     wait(&status); 
     exit(0); 
    } 
} 

#define CHILDREN 2 
int main() 
{ 
    unsigned int i; 
    pid_t pids[CHILDREN]; 

    for (i = 0; i < CHILDREN; i ++) 
    { 
     pids[i] = fork(); 
     if (pids[i] < 0) 
     { 
      // TODO: handle error 
     } 
     else if (pids[i] == 0) 
     { 
      ExecuteCommandAndInterpretResult("/usr/bin/ls"); 
      exit(0); 
     } 
    } 

    for (i = 0; i < CHILDREN; i ++) 
    { 
     if (pids[i] > 0) 
     { 
      int status; 
      waitpid(pids[0], &status, 0); 
     } 
    } 

    return 0; 
} 
0

당신이 whoami을 실행하기 위해 아이에 popen()를 사용하여 고려 적이 있습니까?