2009-03-16 6 views
3

나는 약간의 병렬 처리가 이득이되는 어플리케이션을 가지고있다. 토론 목적으로, 10 개의 텍스트 파일이있는 디렉토리가 있다고 가정 해 봅시다. 프로그램을 시작하고 10 개의 프로세스를 포크하고 각각이 파일 중 하나를 취하고 파일의 내용을 대문자로 나타내려고합니다. 부모 프로그램은 아이들이 대기 중 하나를 사용하여 완료 할 때까지 기다릴 수 있음을 인정합니다. 함수를 사용하거나 함수를 사용하십시오.unix-fork-monitor-child-progress

부모 프로세스가 각 fork 된 프로세스의 진행 상황을 모니터링하고 프로세스가 진행될 때 진행률 막대와 같은 것을 표시하도록하고 싶습니다.

내 질문

분기 된 프로세스가이 정보를 부모에게 다시 전달할 수있는 합리적인 대안은 무엇입니까? 어떤 IPC 기법을 사용하는 것이 합리적일까요?

답변

2

진행 상황 만 모니터링하려는 상황에서 가장 쉬운 방법은 공유 메모리를 사용하는 것입니다. 모든 프로세스는 공유 메모리 블록에서 진행 값 (예 : 정수)을 업데이트하고 마스터 프로세스는 블록을 정기적으로 읽습니다. 기본적으로이 체계에서는 잠금이 필요하지 않습니다. 또한 마스터는 원할 때마다 정보를 읽을 수 있기 때문에 "폴링"스타일 응용 프로그램이므로 진행 데이터를 처리하기위한 이벤트 처리가 필요하지 않습니다.

+0

진행 값이 멀티 바이트 인 경우 캐시에서 정렬까지 모든 종류에 따라 잠금이 필요할 수 있습니다. 이것은 "주행 거리 문제"라고 불리곤했습니다. 기본적으로 (그리고 빅 엔디안 십진법에서) 1999 년부터 2000 년까지 독자는 1900 년, 2099 년 등을 볼 수 있습니다. – MarkusQ

0

오늘 아침 누군가는 항상 파이프를 사용하여 아이들이 부모 프로세스에게 모든 것이 잘 진행되고 있다는 알림을 보낼 수 있다고 말했습니다. 이는 괜찮은 해결책으로, 오류를 인쇄하고 더 이상 stdout/stderr 등에 액세스 할 수없는 곳에 특히 유용합니다.

1

몇 가지 옵션

  • 신호
  • FIFO를/명명 된 파이프 아이들의
  • 표준 출력 또는 기타 통과 핸들 : - 당신은 "uppercasing 파일"비유)에 opped로 많은, 당신이 실제로 무엇을하는지에 따라 달라집니다
  • 메시지 큐 (해당하는 경우)
0

Boost.MPI이이 시나리오에서 유용합니다. 당신이 원하는 모든 진행 업데이트의 경우 가장 쉬운 방법은 익명을 사용하는 것이 아마도 지금까지,
www.boost.org/doc/html/mpi.html

1

: 당신은 과잉을 고려할 수 있지만, 조사 확실히 가치 파이프. pipe (2) 호출은 두 개의 파일 디스크립터를 제공 할 것이다. 포크를 잡기 바로 전에 그것을 호출하고, 부모가 첫 번째 fd를 듣고 자식이 두 번째 자식을 쓰게하십시오. (이 작업은 파일 디스크립터와이를 포함하고있는 두 요소 배열이 공유 메모리 그 자체가 아니라 프로세스간에 공유되기 때문에 덮어 쓰지 않는 한 값을 공유 할 수 있도록 쓰기시 복사가되기 때문에 작동합니다.

2
당신이 필요로하는 유일한 진보 "많은 작업이 완료 어떻게?", 다음의 경우

간단한

while (jobs_running) { 
    pid = wait(&status); 
    for (i = 0; i < num_jobs; i++) 
     if (pid == jobs[i]) { 
      jobs_running--; 
      break; 
     } 
    printf("%i/%i\n", num_jobs - jobs_running, num_jobs); 
} 

할 것입니다. 진행 상황을보고하기 위해, 진행중인 다른 제안들에 대한 벙어리 구현을 여기에 설명합니다.

파이프 :

#include <poll.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <time.h> 
#include <unistd.h> 

int child(int fd) { 
    int i; 
    struct timespec ts; 
    for (i = 0; i < 100; i++) { 
     write(fd, &i, sizeof(i)); 
     ts.tv_sec = 0; 
     ts.tv_nsec = rand() % 512 * 1000000; 
     nanosleep(&ts, NULL); 
    } 
    write(fd, &i, sizeof(i)); 
    exit(0); 
} 

int main() { 
    int fds[10][2]; 
    int i, j, total, status[10] = {0}; 
    for (i = 0; i < 10; i++) { 
     pipe(fds[i]); 
     if (!fork()) 
      child(fds[i][1]); 
    } 
    for (total = 0; total < 1000; sleep(1)) { 
     for (i = 0; i < 10; i++) { 
      struct pollfd pfds = {fds[i][0], POLLIN}; 
      for (poll(&pfds, 1, 0); pfds.revents & POLLIN; poll(&pfds, 1, 0)) { 
       read(fds[i][0], &status[i], sizeof(status[i])); 
       for (total = j = 0; j < 10; j++) 
        total += status[j]; 
      } 
     } 
     printf("%i/1000\n", total); 
    } 
    return 0; 
} 

공유 메모리 : 등 처리

#include <semaphore.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <sys/mman.h> 
#include <time.h> 
#include <unistd.h> 

int child(int *o, sem_t *sem) { 
    int i; 
    struct timespec ts; 
    for (i = 0; i < 100; i++) { 
     sem_wait(sem); 
     *o = i; 
     sem_post(sem); 
     ts.tv_sec = 0; 
     ts.tv_nsec = rand() % 512 * 1000000; 
     nanosleep(&ts, NULL); 
    } 
    sem_wait(sem); 
    *o = i; 
    sem_post(sem); 
    exit(0); 
} 

int main() { 
    int i, j, size, total; 
    void *page; 
    int *status; 
    sem_t *sems; 
    size = sysconf(_SC_PAGESIZE); 
    size = (10 * sizeof(*status) + 10 * sizeof(*sems) + size - 1) & size; 
    page = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0); 
    status = page; 
    sems = (void *)&status[10]; 
    for (i = 0; i < 10; i++) { 
     status[i] = 0; 
     sem_init(&sems[i], 1, 1); 
     if (!fork()) 
      child(&status[i], &sems[i]); 
    } 
    for (total = 0; total < 1000; sleep(1)) { 
     for (total = i = 0; i < 10; i++) { 
      sem_wait(&sems[i]); 
      total += status[i]; 
      sem_post(&sems[i]); 
     } 
     printf("%i/1000\n", total); 
    } 
    return 0; 
} 

오류가 명확성을 위해 생략.