2016-03-02 6 views
0

Я пытаюсь установить связь между процессами верхнего и нижнего уровня моей программы. Сначала я создаю FIFO, тогда у меня есть цикл for для fork n процессов. Внутри цикла for я проверяю, является ли процесс процессом нижнего уровня, и если это так, я пишу в FIFO.FIFO - чтение из процесса верхнего уровня, запись с нижнего уровня процесса

Я смущен тем, как я могу читать из FIFO после того, как процесс нижнего уровня записывается на него. Если я пытаюсь прочитать перед циклом, цикл никогда не выполняется, потому что ничего не было написано. Если я попытаюсь прочитать во время цикла, в родительском разделе кода, другие родители также смогут его прочитать. Если я пытаюсь читать после цикла for, цикл кода никогда не заканчивается, потому что он застревает, когда последний ребенок пытается писать. Вот мой код:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <fcntl.h> 
#include <sys/shm.h> 
#include <sys/stat.h> 
#include <sys/mman.h> 
#include <unistd.h> 
#include <errno.h> 

#define MAX_BUF 1024 

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

    int numprocs = atoi(argv[1]); 
    int lev = numprocs; 
    fprintf(stdout,"ALIVE: Level %d process with pid=%d, child of ppid=%d.\n", lev, getpid(), getppid()); 
    int currpid = getpid(); 

    //create shared memory 
    const int SIZE = numprocs * sizeof(int); 
    const char *name = "dleggio1OS"; 
    int shm_fd; 
    int *ptr; 
    shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666); 
    ftruncate(shm_fd, SIZE); 
    ptr = mmap(0, SIZE, PROT_WRITE, MAP_SHARED, shm_fd, 0); 
    *ptr = getpid(); 

    //create fifo 
    int fd; 
    char *myfifo = "/tmp/dleggio1fifo"; 
    mkfifo(myfifo, 0666); 
    //read fifo 
    /*char buff[MAX_BUF]; 
    fd = open(myfifo,O_RDONLY); 
    read(fd,buff,MAX_BUF); 
    printf("process %d received %s message.\n",getpid(),buff); 
    close(fd);*/ 


    //spawn procs 
    int i; 
    for(i = 1; i < numprocs; i++){ 
     lev--; 
     int pfds[2]; 
     char buf[30]; 
     if(pipe(pfds) == -1){ 
      perror("pipe"); 
      exit(1); 
     } 
     pid_t pid; 


     if((pid = fork()) < 0){ 
      perror("fork"); 
      exit(1); 
     } 

     if(pid == 0){ //child 

      ptr[i] = getpid(); 

      close(pfds[1]); 
      if(read(pfds[0], buf, 3) <= 0){ 
       perror("child"); 
       exit(1); 
      } 
      int check = atoi(buf); 
      fprintf(stdout,"ALIVE: Level %d process with pid=%d, child of ppid=%d.\n", check, ptr[i], ptr[i-1]); 

      if(check == 1){ //leaf 
       //write to fifo 
       fd = open(myfifo, O_WRONLY); 
       write(fd,"leaf",sizeof("leaf")); 
       close(fd); 
       return 0; 
      } 

     } 
     else{ //parent 
      close(pfds[0]); 
      char hold[3]; 
      sprintf(hold,"%d",lev); 
      if(write(pfds[1], hold, 3) <= 0){ 
       perror("parent"); 
       exit(1); 
      } 
      //read fifo 
      /*char buff[MAX_BUF]; 
      fd = open(myfifo,O_RDONLY); 
      read(fd,buff,MAX_BUF); 
      printf("process %d received %s message.\n",getpid(),buff); 
      close(fd);*/ 

      wait(NULL); 
      return 0; 
     } 
    } 

    //read fifo 

    /*char buff[MAX_BUF]; 
    fd = open(myfifo,O_RDONLY); 
    read(fd,buff,MAX_BUF); 
    printf("received %s message.\n",buff); 
    close(fd);*/ 

    shm_unlink(name); 
    unlink(myfifo); 
    return 0; 
} 

ответ

0

Если я пытаюсь читать во время цикла, в родительском разделе кода, другие родители могут прочитать его.

Все они могут читаться из FIFO, потому что вы создаете FIFO перед тем, как развернуть любые процессы; таким образом, они все используют один и тот же. Если вы хотите, чтобы каждая родительская/дочерняя пара имела частный FIFO, который только они могут использовать, вам необходимо переместить свой вызов mkfifo() внутри цикла и создать FIFO (с уникальным именем) для каждого fork().

+0

Как я могу получить только родительский и нижний уровни верхнего уровня, чтобы иметь частный FIFO? – Dylan

+0

В каждой итерации цикла создайте новый FIFO с уникальным именем (например, добавьте счетчик циклов в конец имени) и используйте это родительское/дочернее. Каждая итерация тогда будет знать только имя своего частного FIFO и не сможет получить доступ к кому-либо другому. – bta