我不确定我是否在这里咆哮着正确的树......但是这里也是。
我正在尝试将父进程中的数据传递给所有子进程。这是一个简单的服务器程序,基本上将保留连接的客户端列表,然后将连接的客户端的路由表发送到每个客户端。这最终将包含关于每个客户端的信息结构......但是现在我只想让每个分叉进程从父进程获得相同的信息。
在父进程中,首先我设置我的管道并将它们设置为非阻塞(当管道中没有任何新数据时)。与客户端建立连接后,将增加条目数变量以反映此新连接。然后我将子进程分叉到一个新函数并用新的表条目更新我的管道数组(我现在有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.\n");
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.\n");
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);
}
然后我尝试在recievecmds()函数中读取管道中的内容:
nbytes = read(mypipe[childindex][0], buf, sizeof(buf));
连接的第一个客户端告诉我numentries = 1,第二个客户端告诉我numentries = 2,依此类推。我的意思是我真的甚至没有看到管道的重点,因为看起来无论我放入管道,我都可以在我调用叉子的函数中传递它。我是以错误的方式来做这件事的吗?试图解决这个问题一直非常令人沮丧。如何从父进程中同时更新所有子进程?
提前非常感谢你。
编辑 - 我的主要问题是我每次都在无限循环中重新声明管道。非常愚蠢的错误,立刻意识到这可能是我问题的根源。但是,现在第一个子/管道组合包含正确的数据......第二个不包含正确的数据。我会看看我是否可以自己解决这个问题,谢谢你的建议!
当然,现在我遇到了问题,因为我手动选择一个选项来从管道中获取数据。我将不得不想办法在每次更新时获取所有管道的数据,或者确保只获取最新数据(可能一次只有一个字符串)。
谢谢你们忍受我们!我为不发布整个程序而道歉......但是有很多。我绝对应该提到我在无限循环中拥有它。
答案 0 :(得分:6)
#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\n", pid);
while ((nbytes = read(pipe[0], buffer, sizeof(buffer))) > 0)
{
printf("Child %d: %d %.*s\n", pid, nbytes, nbytes, buffer);
fflush(0);
}
printf("Child %d: finished\n", 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)\n", errnum, strerror(errnum));
return EXIT_FAILURE;
}
if ((pid = fork()) < 0)
{
int errnum = errno;
fprintf(stderr, "Fork failed (%d: %s)\n", 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)\n", j);
exit(1);
}
}
sleep(1);
}
printf("Parent complete\n");
return 0;
}
答案 1 :(得分:1)
我建议使用共享内存段。您的父进程和子进程可以对同一文件进行mmap,并对其进行读/写状态。这可以是实际文件,也可以是匿名内存段。这正是Apache用ScoreBoardFile做的事情。