C使用管道与父母沟通儿童

时间:2016-01-06 12:58:48

标签: c linux pipe fork

我的程序会创建与用户放入参数一样多的子项。将消息发送给父母时遇到问题。我希望每个孩子都使用烟斗向父母发送信息。我不知道怎么做。我知道它对一个孩子有用:http://tldp.org/LDP/lpg/node11.html但不知道如何为许多孩子做这件事。

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


int main(int argc, char **argv)
{
        pid_t pid;

        if(argc < 3)
        {
                printf("Not enought arguments");
                exit(0);
        }

        int number = atoi(argv[2]); // number of childern
        pid_t pids[number],pid_s;
        int i,n=number,status;
        int pipes[number*2];
        char buff[512];
        int r=0,w=0,rr=0,ww=0;

        for(i=0; i<n; i++)
        {
                if(pipe(pipes+(i*2)) < 0)
                {
                        perror("failed to allocate pipes");
                }
        }

        if(strcmp("-p", argv[1]) == 0)
        {
                //
        }

        if(strcmp("-f", argv[1]) == 0)
        {
                //
        }


        switch (pid = fork()) {
           case -1:
                        perror("Error in fork");
                        exit(0);

                        break;
           case 0:


               for(i=0; i < n; i++)
               {
                       if((pids[i] = fork()) < 0)
                       {
                               perror("error fork");
                       }
                       else if(pids[i] == 0)
                       {
                            close(pipes[0+r]);
                            char *reply = "message";
                            int val = getpid();
                            write(pipes[1+w], &val, strlen(reply)+1);

                            r+=2;
                            w+=2;

                            printf("Stworzylem dziecko z numerem: %d \n", getpid());
                            execvp(argv[0],NULL);
                       }
               }

               while(n > 0)
               {
                       pid_s = wait(&status);
                       --n;
               }
                      break;
        default:


               for(i=0; i<n; i++)
               {
                    close(pipes[1+rr]);
                    int n;
                    read(pipes[0+ww],&n,sizeof(n));
                    printf("Wiadomosc: %d \n", n);
                    rr+=2;
                    ww+=2;
               }
               if(wait(0) == -1)
               {

               }

                      break;
     }

    return 0;

}

我希望程序创建N个孩子。 每个孩子都必须向父母发送消息。我使用了exec任务,因为在我的任务中写道,每个孩子都应该作为一个单独的程序运行。我创建了一个示例流,但它无法正常工作。

现在程序创建了N个子进程。从孩子的父母过程的沟通不工作。

编辑:

对我来说,发送和接收数据始终是通过相同的事情。我发送过程的PID,但总是选择相同的。

2 个答案:

答案 0 :(得分:1)

管道是一个非常不适合这个问题的工具,因为它们基本上是一对一的通信方法。您需要的是多对一的通信方法。为此,我建议使用message queue。这将允许您的父级订阅消息队列,并允许无限数量的子节点写入消息队列,并将其消息全部复制到父节点。

答案 1 :(得分:1)

我不能按照你想要的双叉业务来做。 而且我不倾向于为你写整篇文章,但这里是我如何编写代码的概述:

    int *   pids;
    int *   fds;
    int     pipefds[2];
    char *  message = "message";
    int     alive   = 0;

    pids = malloc(n * sizeof(int *));
    fds =  malloc(n * sizeof(int *));

    for (i = 0; i < n; ++i) {
            if (pipe(pipefds) == -1) exit(1);
            switch (pid = fork()) {
                case -1:                    /* error */
                    exit(2);
                case 0:                     /* child */
                    close(pipefds[0]);
                    write(pipefds[1], message, strlen(message)+1);
                    _exit(0);
                default:                    /* parent */
                    closefds[1];
                    pids[i] = pid;
                    fds[i] = pipefds[0];
                    ++alive;
            }
    }
    while (alive > 0) {
            /* select on the fds[] of all alive (fds[i] != -1) children */
            /* if EINTR, do waitpid(-1, &status, WNOHANG); */
            /*   to see if a child has exited */
            /*     if so, find it in pids, say at index 'x', and:  */
            /*       close(fds[x]); fds[x] = -1; --alive; */
            /* if select said I/O ready for a pipe */
            /*    then read that pipe */
    }