2014-10-19 1 views
0

영어에 대해 아직 사과합니다. 이해해 주시면 감사하겠습니다. 그래서 나는 printf 전에 아버지의 끝과 printf의 일부를 기다리는 내 프로그램의 printf에이 문제가있다. 그래서 나는 항상 그의 메시지를 모두 인쇄 한 아버지를 얻었고 그 다음 아들은 그의 메시지를 모두 인쇄해야했다.포크에 잘못된 printf가 있습니다.

내가 보았던 것에서 나는 fflush가 있어야한다는 것을 알았지 만 그것은 내 문제를 해결하지 못했다. . 귀하의 도움을 위해서 Thx. 내 코드는 다음과 같습니다.

#include <stdio.h> 
#include <stdlib.h> 
#include <sys/types.h> 
#include <sys/wait.h> 
#include <sys/sem.h> 
#include <sys/ipc.h> 
#include <unistd.h> 
#include <sys/shm.h> 

int cpt = 0; 

void fils(int *cpt){ 
    int i; 
    for(i = 0; i < 3; i++){ 
    (*cpt)++; 
    printf("son : %d\n", *cpt); 
    } 
} 

void pere(int *cpt){ 
    int i; 
    for(i = 0; i < 3; i++){ 
    (*cpt)--; 
    printf("father : %d\n", *cpt); 
    fflush(stdout); 
    } 
} 

int main (int argc, char*argv[]){ 
    key_t key; 
    int memShared; 
    int *cpt = NULL; 

    key = ftok(argv[0],'p'); 
    memShared = shmget(key, sizeof(int), IPC_CREAT|IPC_EXCL|0666); 
    cpt = shmat (memShared, cpt, 0); 
    *cpt = 0; 

    fflush(stdout); 
    switch (fork()){ 
    case -1: perror("erreur de création du fils"); 
     exit(99); 
    case 0: fils(cpt); 
     exit(1); 
    default: pere(cpt); 
     wait(NULL); 
    } 
    shmctl(memShared, IPC_RMID, NULL); 

    return 0; 
} 

와 나는 항상이 터미널

아버지에있다 : -1 아버지 : -1 아버지 : -2 아들 : 0 아들 : -1 아들 : 0

나는 예를 들어 아버지와 교차해야하지만 -1 아들 : 0 아버지 : -1 ... 당신의 도움에 감사드립니다.

+6

당신은 "넘어서 야합니다"라고 말하지만, 그렇게 할 수있는 메커니즘을 구현하지 않았습니다. 두 프로세스 모두 출력물을 모두 작성하기 위해 경주하고 있으며, 프로그램에서 다른 프로세스를 기다릴 필요가 없습니다. 출력물을 번갈아 가며 사용하려면 코드를 작성해야합니다. 또한 공유 메모리에 대한 액세스를 동기화하지 않기 때문에 아버지가 두 개의'-1 '을 연속적으로 쓰는 것과 같은 이상한 결과를 얻게됩니다. –

+0

아버지는'waitpid'를 위해서 필요할 것이기 때문에 항상 변수에'fork'의 결과를 유지할 필요가 있습니다. [shm_overview (7)] (http://man7.org/linux/man-pages/man7/shm_overview.7.html) 및 [sem_overview (7)] (http://man7.org/linux/man -pages/man7/sem_overview.7.html) –

+2

@BasileStarynkevitch : 불필요합니다. 그는 정확하게 하나의 자식 프로세스가 끝나기를 기다리고 있습니다. 그것은 충분히 선택적입니다. (우리는 일반적으로'waitpid'를 사용해야하는 일반적인 경우가 아닙니다.) – Deduplicator

답변

0

이것은 고전적인 경주입니다. 단지 switch에 선 순서를, '첫 아들'순서를 달성하기 위해 :

switch (fork()){ 
case -1: perror("erreur de création du fils"); 
    exit(99); 
case 0: fils(cpt); 
    exit(1); 
default: wait(NULL); //First - wait 
    pere(cpt);  //Then - print 
} 

을 당신은 당신이 의도 한대로 같은 간단한 솔루션이 작동할지 보장이 없습니다. 당신이 원하는 것은 정확히 하나의 루프 반복이 스위치가 꺼질 때까지 프로세스에 의해 실행되도록 보장하는 것입니다.

당신이 그들이 ABABAB 방식으로 들어가게하려면 다른 동기화 메커니즘이 필요합니다. 그 간단한 세마포어로는 충분하지 않다는 것을 명심하십시오. 이 프로세스가 통신 할 수 있도록 파이프 또는 FIFO 대기열이 필요할 수 있습니다. pipe 또는 mkfifo이라는 함수를 찾습니다. 다음과 같이 할 수 있습니다.

for(number_of_iterations) 
{ 
    wait for a message from the other process; 
    do work on shm; 
    send message to another process, allowing it to continue; 
} 

이렇게하면 토큰 개념이 활성화됩니다.

의견에 대한 제안 사항 : 변수가 포크 결과를 유지하면 waitpid을 기다리는 것이 더 많은 프로세스가있을 때 더 안전합니다. wait은 특정 프로세스가 아니라 첫 번째 종료 프로세스를 기다립니다.

-1
[email protected]:~$ 
[email protected]:~$ ./wrong_printf 
father : -1 
son : 0 
son : 1 
son : 2 
father : 1 
father : 0 
[email protected]:~$** 

내 컴퓨터에서 프로그램이 작동합니다. 나는 아버지의 printf와 아들의 printf가 참으로 건넜다는 것을 의미한다.

+0

그건 중요하지 않습니다. 이 프로그램 **은 ** 작동하지만 ** 보장 **되지는 않습니다 **. 그것은 보통 인종에 대한 문제입니다. –