2017-03-20 1 views
0

특정 논리를 하위 프로세스에 위임 할 기존 코드가 있습니다. 요구 사항은 부모가 파이프에 쓰고 자식이 파이프에 읽는 것입니다. 읽은 후에, 자식은 새로운 파이프에 무엇인가를 쓴다. 그리고 부모는 그것을 읽는다.양방향 읽기/쓰기를위한 파이프 액세스 동기화

아래 코드에서 send() 함수는 부모 프로세스의 전용 스레드에 의해 주기적으로 호출됩니다.

LaunchWorker()는 하위 프로세스가 처음 호출 될 때만 fork됩니다.

1) 두 디스크립터의 읽기 및 쓰기 끝을 닫는 방법을 알아낼 수 없기 때문에 파이프에 쓰여진 이전 데이터가 모든 쓰기에 플러시됩니다. 2) 두 개의 설명자에 대해 두 번 필요한 pipe() 호출 중입니까?

이 코드 작업을위한 모든 입력 사항을 크게 높이 실 것입니다. 감사합니다.

typedef struct 
{ 
    WebClient* wc; // user defined class 
    string url; 
    string data; 
    size_t dataLen; 
    DownloadObserver* downloadCallback; // user defined class 
    string* token; 
}Payload; 

PayLoad pl; 

static pid_t worker_pid = 0; 
int fd1[2]; 
int fd2[2]; 

bool done = false; 

void LaunchWorker() 
{ 
    if (worker_pid != 0) 
    { 
     return; 
    } 
    pipe(fd1); 
    pipe(fd2); 

    worker_pid = fork(); 

} 

void send() 
{ 
    //populate pl; 

    LaunchWorker(); 

    if (worker_pid == 0) 
    { 
     while(true) 
     { 
      close(fd1[1]); 
      close(fd2[0]); 

      int cr = read(fd1[0], &pl, sizeof(Payload)); 
      if (cr > 0) 
      { 
       // Upload some data to a remote http endpoint - uses libcurl 
       //if upload success, done = true 

       int cw = write(fd2[1], &done, sizeof(bool)); 
       if (cw > 0) 
       { 
        // success 
       } 
       else 
       { 
        // failure 
       } 
      } 
      else 
      { 
       // failure 
      } 
     } 
    } 
    else if (workper_pid > 0) 
    { 
     close(fd1[0]); 
     close(fd2[1]); 
     int pw = write(fd1[1], &pl, sizeof(Payload)); 
     if (pw > 0) 
     { 
      int pr = read(fd2[0], &done, sizeof(bool)); 
      if (pr > 0) 
      { 
       // do something with value read 
      } 
      else 
      { 
       // failure 
      } 
     } 
     else 
     { 
      failure 
     } 
    } 
} 
+1

예 파이프를 두 개 만들려면 'pipe'를 두 번 호출해야합니다. 이것은 파이프가 단방향이므로 단방향입니다. 감사합니다. –

+0

. 내 첫 번째 질문에 대해서는 코드에서 close()를 호출해야하는 순서에 대한 팁이 있습니까? – user2930006

+0

각 프로세스에서 사용하지 않는 설명자를 닫아야합니다 (예 : 하위 프로세스의 fd1 [1]). 그 외에는 파이프 설명자를 닫을 필요가 없습니다. 어떤 종류의 "동기화"가 필요한지 잘 모르겠습니다. 많은 양의 데이터를 보내고 있습니까? 'Payload'의 크기는 얼마입니까? –

답변

0

첫째, 당신은 포크 직후 파이프 를 사용하지 않은 끝을 닫아야합니다, 그래서 부모는 FD1의 읽기 끝 FD2의 쓰기 끝을 닫아야하고, 아이가 쓰기 끝을 닫아야합니다 fd1과 fd2의 읽기 끝. 이렇게하지 않으면 끝날 때 파이프가 닫히지 않습니다.

그런 다음 모든 것을 중단하려면 각 파이프의 작성자에게 파이프의 쓰기 끝을 닫게합니다. 즉

  • 부모
  • 아이 FD1에 EOF를 판독하고
  • 아이
  • 부모 FD2에 EOF를 읽고 그것을 폐쇄 FD2의 쓰기 단부를 폐쇄 폐쇄 FD1의 단부 물품 닫는다.

또는 다른 방법으로는 자식이 시스템 종료를 시작합니다.

마지막으로 부모 프로세스는 wait 시스템 호출을 실행하여 자식의 종료 결과를 수집해야합니다.

네, 파이프가 두 개 필요합니다. 파이프는 편도입니다.

+0

고맙습니다. 나는 위의 코드를 편집하여 atleast 1) 두 프로세스에서 원치 않는 설명자를 닫는 방법을 보여주었습니다. 2) Payload struct의 정의. 내가 지금보고있는 문제는 처음 쓰기/읽기에서 모든 것이 잘 작동한다는 것입니다. 두 번째 쓰기도 좋습니다.pl은 예상 값을가집니다. 그러나 두 번째 읽기 후에 pl을 확인할 때 pl.url에서 같은 값을 볼 수 있습니다. 두 번째 (및 후속) 읽기에서 잘못 될 수있는 것은 무엇입니까? sizeof (페이로드) 80 바이트. – user2930006

+0

자식의 read() 직전에 pl에 메모리를 할당합니다. '페이로드 * pl = (페이로드 *) malloc (sizeof (페이로드));' 두 번째 읽기의 크기도 정확합니다 (80 바이트). 하지만 여전히 두 번째 읽기 작업을 할 수 없습니다. 위와 동일한 문제입니다. – user2930006

+0

@ user2930006이 질문을 변경하여 편집하지 말고 새 질문을 만들어야합니다. – JeremyP