English 中文(简体)
图六
原标题:Forks and Pipes in C UNIX
  • 时间:2009-11-10 03:22:19
  •  标签:

我不敢肯定,我甚至会在这里打上正确的树。

我试图把我的父母过程的数据传给所有儿童。 该系统是一个简单的服务器方案,基本上将保存一个连接客户名单,然后向每个客户发送连接客户的路径表。 这最终将包含关于每个客户的信息内容......但现在我只想从父母那里获得同样的信息。

在母体程序中,首先,我建立了我的管道,将其放开(如管道中没有任何新数据)。 在与客户建立联系后,条目数目变数增加,以反映这一新联系。 然后,我把儿童进程推向新的功能,并更新我的管道,新目录编号(目前我有10个管道,看我是否需要为每个儿童单独设置一个管道)。

            pid_t pid;
    int numchildren;

    int i, n;

    /* Create the pipes. */
    for(i = 0; i < 10; i++)
    {
        if (pipe (mypipe[i]))
        {
        fprintf (stderr, "Pipe failed.
");
        return EXIT_FAILURE;
        }
    }

    for(i = 0; i < 10; i++)
    {
        for(n=0; n<2; n++)
        {
          // Get previous flags
          int f = fcntl(mypipe[i][n], F_GETFL, 0);
          // Set bit for non-blocking flag
          f |= O_NONBLOCK;
          // Change flags on fd
          fcntl(mypipe[i][n], F_SETFL, f);
        }
        //close(mypipe[i][0]);
    }

        pid = fork();

    if (pid == (pid_t) 0)
    {
        close (mypipe[numentries-1][1]);
        recievecmds(new_fd, mypipe[numentries-1][0]);
        close(new_fd);
        return EXIT_SUCCESS;
    }

else if (pid < (pid_t) 0)
{
    fprintf (stderr, "Fork failed.
");
    return EXIT_FAILURE;
}
else
{
    sprintf (buf,"%d",numentries);
    for(i = 0; i < 10; i++)
        write(mypipe[i][1], buf, strlen(buf));
    memset(&buf, 0, sizeof buf);
}

接着,我试图读一下信管中的功能:

nbytes = read(mypipe[childindex][0], buf, sizeof(buf));

第一个客户联系的账号为1,第二客户指2等。 我指的是,我甚至看不到管道的位置,因为我认为,在我所呼吁的职能中,我只能通过管道。 我这样说是错了吗? 令人非常沮丧的是,试图说明这一点。 我怎么能够同时从我的父母程序中更新我的所有儿童进程?

事先非常感谢你。

edit - 我的主要问题是,我每当一个无限的时期就重新宣布管道。 非常 d错,立即认识到,这可能是我问题的根源。 然而,虽然目前第一家儿童/管道 com体含有正确数据......第二个没有。 我遗憾地看到,如果我能凭借咨询意见来表明这一点的话!

当然,由于我手工选择将数据从管道中取出的一种选择,因此,现在我会遇到问题。 我不得不想出一种办法,即要么每当更新所有管道的数据时就获得数据,要么确保仅仅获得最新数据(也许只是一个焦炭时)。

感谢与我站在一起! 我对不把整个方案放在一边表示歉意,但有一个很大的界限。 我当然应该提到,我有了一个无限的漏洞。

问题回答

Various observations

  1. Don t make the pipes non-blocking; you want the children to block when there s no data. At least, in the early phases of the design; later, you may want to let them get on with work when there s no data waiting.
  2. You need to be careful with your plumbing. The parent needs 10 pipes, one for each child. But it only needs the write end of the pipe, not the read end.
  3. The children each need one pipe, for reading. Any superfluous pipes (for example, the write ends of the pipes that the parent had already opened before forking the Nth child) need to be closed.
  4. You could consider using threads - in which case you could perhaps pass the data to the children. But in the long term, it appears that you will be periodically passing data to the children, and then you need a mechanism to get the data to them (other than the function call).
  5. Pipes are easy as long as you pay meticulous attention to which file descriptors are in use. Close all the descriptors you do not need.
  6. The parent will have to loop around all ten pipes writing the same data to each.
  7. It will also need to consider what to do if a child exits. It should close the pipe (no use any more), and decide whether to start a new child (but how will it ensure that the new child has all the accumulated information it needs?).
  8. Watch out for SIGPIPE - maybe install a handler, or maybe use SIG_IGN and detect write errors instead of signals.

Working code

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

enum { NUM_CHILDREN = 10 };
enum { NUM_MESSAGES = 10 };

static int write_pipes[NUM_CHILDREN];
static int n_pipes;

static void be_childish(int *pipe)
{
    int i;
    char buffer[32];
    int nbytes;
    int pid = getpid();
    close(pipe[1]);
    for (i = 0; i < n_pipes; i++)
        close(write_pipes[i]);
    printf("Child %d
", pid);
    while ((nbytes = read(pipe[0], buffer, sizeof(buffer))) > 0)
    {
        printf("Child %d: %d %.*s
", pid, nbytes, nbytes, buffer);
        fflush(0);
    }
    printf("Child %d: finished
", pid);
    exit(0);
}

int main(void)
{
    pid_t pid;
    int i, j;

    /* Create the pipes and the children. */
    for (i = 0; i < NUM_CHILDREN; i++)
    {
        int new_pipe[2];
        if (pipe(new_pipe))
        {
            int errnum = errno;
            fprintf(stderr, "Pipe failed (%d: %s)
", errnum, strerror(errnum));
            return EXIT_FAILURE;
        }
        if ((pid = fork()) < 0)
        {
            int errnum = errno;
            fprintf(stderr, "Fork failed (%d: %s)
", errnum, strerror(errnum));
            return EXIT_FAILURE;
        }
        else if (pid == 0)
        {
            be_childish(new_pipe);
        }
        else
        {
            close(new_pipe[0]);
            write_pipes[n_pipes++] = new_pipe[1];
        }
    }

    for (i = 0; i < NUM_MESSAGES; i++)
    {
        char message[30];
        int len;
        snprintf(message, sizeof(message), "Message %d", i);
        len = strlen(message);
        for (j = 0; j < n_pipes; j++)
        {
            if (write(write_pipes[j], message, len) != len)
            {
                /* Inferior error handling; first failure causes termination */
                fprintf(stderr, "Write failed (child %d)
", j);
                exit(1);
            }
        }
        sleep(1);
    }
    printf("Parent complete
");

    return 0;
}

d 我建议使用共享记忆部分。 你的父母和儿童过程可以一刀切,读/写。 这可以是实际档案,也可以是匿名记忆。 这正是阿帕奇与他们的





相关问题
热门标签