2013-03-06 1 views
0

부모 플레이가 N 개의 하위 프로세스에 대해 4 개를 연결하는 과제를위한 프로그램을 작성 중입니다. 이 프로그램은 파이프를 사용하여 프로세스간에 게임 이동을 알립니다.포크()와 파이프()로 레이스 컨디션

그러나 내 프로그램에있는 경쟁 조건을 수정하는 데 문제가 있습니다. 게임이 끝난 후 자식 프로세스가 read() 호출을 중단시키는 조건이 있습니다. 이것은 하나 이상의 자식 프로세스가있는 경우에만 발생하는 것으로 보입니다.

필자는 명명 된 세마포어와 같은 여러 가지 사항을 시도했지만 포크, 파이프 및 IPC에 대해서는 아직 완전히 익숙하지 않습니다. 내가 관련 코드와 요지를 게시 한 여기에 (나는 최선 내가 가독성을 위해 할 수있는 한 그것을 청소하려고) :

Gist with relevant code

어떤 도움을 크게

편집을 감상 할 수있다

다음은 선언이 추가 된 요지의 관련 소스입니다.

int main (int argc, char const *argv[]) 
{ 
    int dimension = 8, children = 2, i; 
    int child_play_to_win = 0; 
    int fd[children][4]; 
    pid_t childpid[children]; 
    Board** boards = (Board**) malloc(sizeof(Board*) * children); 
    GameMove* lastMove, *tmpMove; 
    char buf[80]; 
    for(i = 0; i < children; i++) { 
    generate_board(&(boards[i]), dimension); 
    int tmp[2]; 
    pipe(tmp); 

    // child read 
    fd[i][0] = dup(tmp[0]); 
    // parent write 
    fd[i][1] = dup(tmp[1]); 

    pipe(tmp); 
    // parent read 
    fd[i][2] = dup(tmp[0]); 
    // child write 
    fd[i][3] = dup(tmp[1]); 

     childpid[i] = fork(); 

    if(childpid[i] == -1) { 
     perror("fork"); 
     exit(1); 
    } 
    if(childpid[i] == 0) { 
     srand(getpid()); 
     close(fd[i][1]); 
     close(fd[i][2]); 
     while(!boards[i]->finished) { 
     // Read in move from parent 
     printf("child[%d] about to read\n", getpid()); 
     read(fd[i][0], &buf, sizeof(GameMove)); 

     // repeat parent move on this board 

     if(gameNotFinished) { 
      // make child move 

      // write move back to parent 

      write(fd[i][3], lastMove, sizeof(GameMove)); 

      // If the board is finished (there was a win), 
      if (!gameNotFinihsed) { 
      // Child wins 
      close(fd[i][0]); 
      close(fd[i][3]); 
      printf("child[%d] ending\n", getpid()); 
      break; 
      } 
     } 
     else { 
      // Parent won 
      close(fd[i][0]); 
      close(fd[i][3]); 
      break; 
     } 
     } 
    dealloc(boards[i]); 
    exit(0); 
    } 
} 

    // When this hits children amount, all games are done 
    int games_complete = 0; 
    // Make first move to all children 
    for (i = 0; i < children; i++) { 
    close(fd[i][0]); 
    close(fd[i][3]); 
    lastMove = placePieceAtBestPosition(boards[i], 1); 
    printf("parent writing to child[%d]\n", childpid[i]); 
    write(fd[i][1], lastMove, sizeof(GameMove)); 
    } 
    while (games_complete != children) { 
    for (i = 0; i < children; i++) { 
     // Read move from child 
     read(fd[i][2], &buf, sizeof(GameMove)); 

     // repeat child move 

     // Check for a child win... 
     if (!checkForWin(boards[i], 2)) { 
     // No win yet, place piece at best position 

     lastMove = placePieceAtBestPosition(boards[i], 1); 

     // check for win again 
     boards[i]->finished = checkForWin(boards[i], 1); 
     // Write move back to child 
     write(fd[i][1], lastMove, sizeof(GameMove)); 

     // If we won, close everything up and increment 
     // the games_complete counter. 
     if(boards[i]->finished) { 
      close(fd[i][1]); 
      close(fd[i][2]); 
      games_complete++; 
     } 
     } else { 
    // write back child move if there was a win 
     write(fd[i][1], lastMove, sizeof(GameMove)); 
     close(fd[i][1]); 
     close(fd[i][2]); 
     printf("Parent lost!):\n"); 
     games_complete++; 
     } 
    } 
    } 
+2

게시하시기 바랍니다 (의 관련 부분) 귀하의 질문에 직접 코드가 아닌 링크를 통해. 감사. –

+0

나에게 맞는 첫 번째 일은 파이프를 만든 후에 이러한'dup' 호출이 필요 없다는 것입니다. 특히 원본 파일 설명자를 닫지 않으므로 특히 그렇습니다. 작성하는 하위 프로세스의 수에 따라 파일 설명자 테이블을 채울 수 있습니다. –

+0

* 왜 * 100 개 이상의 코드 행을 연결하고 소스 파일의 맨 위에 시작 함수 선언을 포함시키지 않습니까? – WhozCraig

답변

0

나는 당신의 문제가 무엇인지 알고 있다고 생각합니다. 각 하위를 포크 할 때 파이프의 부모 측을 닫습니다. 그러나 각 어린이는 여전히 이전의 모든 어린이를 위해 파이프의 부모면을 엽니 다. 이 때문에 마지막으로 생성 된 자식 만 부모 측 파이프를 닫습니다.

는 변경 제안 :

close(fd[i][1]); 
close(fd[i][2]); 

같은 뭔가 :

for (j = 0; j <=i; j++) { 
    close(fd[j][1]); 
    close(fd[j][2]); 
} 
+0

잘자요. 나는 아직도 아이의 독서에 매달려있다. 그러나 이것은 분명히 내가 놓친 것이다. –