Несколько вилка () Дети с трубами - PullRequest
1 голос
/ 28 октября 2011

Я пытаюсь создать программу на C ++, которая создает дочерние объекты с помощью fork ().Он должен взять номер childs из argv и создать этих childs, каждый дочерний элемент создает другого и общаться друг с другом с помощью каналов ....

Example ./a.exe 2

**OUTPUT**
P1 exists
P2 created
Write message: Hello
P1 sending message (“Hello”) to P2
P2 received message (“Hello”) from P1

Я получаю число от argv, создавая правильное число childs(я думаю), функции для чтения и записи в трубу, все в порядке.Но у меня есть проблема, чтобы сделать это с несколькими дочерними элементами !!

  1. Моя первая проблема заключается в том, что, если я добавлю больше 2 в argv, дочерний порядок не будет возрастать, как должен! (Созданный показывает позже)
  2. Но моя большая проблема в том, что если я напишу сообщение из 2 слов, я смогу прочитать только первое слово перед пробелом !! Я использую scanf.

НЕКОТОРЫЙ МОЙ КОД

// ПОЛУЧЕНИЕ, ПРОВЕРКА ARGV
// ОТКРЫТИЕ ТРУБЫ

         pid=fork();
         if (pid!=0){


                      waitpid(pid,&child_status,0);
                      printf("\n\n****Parent Process:ALL CHILD FINISHED!****");

                     }
          else if (pid==0)
          {

                 printf("\n P%d Exists \n",i); 
                     close (mypipe[READ_END]);
                      write(mypipe[WRITE_END], msg, 256);  /* write pipe*/                   
                       close (mypipe[WRITE_END]);          
                    printf("Write a message: \n");
                     scanf("%s",msg);
                       printf("\n P%d sending message: '%s' to P%d \n",i,msg,i+1); 

         do{
            childpid[i] = fork();
           if (childpid[i] > 0){   


                       /* wait for child to terminate */
                             waitpid(childpid[i],&child_status,0);  
                 }
           else if (childpid[i] == 0)
           {
               /*child process childpid = 0*/
               printf("\n P%d Created \n",i+1);
               close (mypipe[WRITE_END]);   
                 read(mypipe[READ_END], msg, 256);  /* read pipe */
                 close (mypipe[READ_END]);
                 printf("\n P%d received message: '%s' from P%d \n",i+1,msg,i);          
                 exit(0);
                 return;

            }
           else{
                   printf("Child Fork failed");
                   }
                      i++;
                   }

                   while (i<x);


                   }
                   else{
                   printf("Fork failed");
                   }    
                          }

Я читал другие подобные вопросы и пробовал много вещей, но не помог !!Любая помощь будет оценена !!Спасибо!

1 Ответ

1 голос
/ 28 октября 2011

У вас есть несколько проблем в коде, который вы показываете, и отсутствует код, как диагностировано в комментарии.

Одна проблема заключается в том, что вы закрываете оба конца единственного канала в первом дочернем элементе, а затем закрываетеэто второй раз (но, к счастью, вы игнорируете ошибку).Более серьезно, у любых последующих потомков есть только закрытый канал для работы, и это не поможет им.

Другая проблема заключается в том, что родительский процесс не закрывает канал;в этой программе это может не иметь значения, поскольку вы не пытаетесь читать в EOF, но в большинстве программ это будет иметь значение.

Другая проблема заключается в том, что вы не читаете сообщение из стандартного ввода до тех пор, пока не получите 'Я пытался написать неинициализированное сообщение в канал.Не сразу понятно, следует ли вам подключить стандартный ввод дочернего элемента к концу чтения канала.Вы записываете 256 байт в канал, даже если сообщение не такое длинное.

У вас возникают проблемы с несколькими словами, потому что scanf("%s", msg) предназначен для чтения до первого пробела (пробел, новая строка, табуляция,так далее).В этом контексте я бы, вероятно, использовал fgets() для чтения информации.

Я думаю, вам нужен новый канал для каждого ребенка.Вероятно, вам следует проверять ошибки при каждом системном вызове, но это проще, если у вас есть простая функция сообщения об ошибках, например:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h>
#include <errno.h>

static char *arg0 = 0;

static void err_exit(const char *fmt, ...)
{
    int errnum = errno;
    va_list args;
    va_start(args, fmt);
    fprintf(stderr, "%s (%d): ", arg0, (int)getpid());
    vfprintf(stderr, fmt, args);
    va_end(args);
    if (errnum != 0)
        fprintf(stderr, "Error %d: %s\n", errnum, strerror(errnum));
    exit(1);
}

int main(int argc, char **argv)
{
    int i=1;
    int x;
    int pid, mypipe[2];
    pid_t childpid[256];
    int child_status;
    char msg[256];

    arg0 = argv[0];

    if (argc != 2 || (x = atoi(argv[1])) <= 0)
        err_exit("Usage: %s num-of-children\n", argv[0]);
    if (pipe(mypipe) < 0)
        err_exit("pipe error\n");

У вас есть серьезные мысли о том, как вы хотите организовать вещи так, чтобысообщение передается от одного процесса к другому.Это только начало ... функция сообщения об ошибках может быть вам полезна.

...