C UNIX 中的叉子和管道
我不确定我是否在这里吠叫了正确的树……但就这样吧。
我正在尝试将数据从我的父进程传递给所有子进程。这是一个简单的服务器程序,基本上会保留已连接客户端的列表,然后将已连接客户端的路由表发送到每个客户端。这最终将包括有关每个客户端的信息结构......但现在我只想让每个分叉进程从父进程获取相同的信息。
在父进程中,首先我设置管道并将它们设置为非阻塞(当管道中没有任何新数据可用时)。与客户端建立连接后,条目变量的数量会增加以反映此新连接。然后,我将一个子进程分叉到一个新函数,并使用新的表条目数更新我的管道数组(目前我有 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);
}
然后我尝试读取 receivecmds() 函数中管道中的内容:
nbytes = read(mypipe[childindex][0], buf, sizeof(buf));
连接的第一个客户端告诉我 numentries = 1,第二个客户端告诉我 numentries = 2 等等。我的意思是,我真的没有看到管道的意义,因为似乎无论我在管道中放入什么,我都可以将它传递到我在叉子上调用的函数中。我是否以错误的方式处理这个问题?试图弄清楚这一点非常令人沮丧。如何使所有子进程同时从父进程更新?
预先非常感谢您。
编辑 - 我的主要问题是我每次都在无限 while 循环中重新声明管道。非常愚蠢的错误,立即意识到这可能是我问题的根源。然而,虽然现在第一个子/管道组合包含正确的数据......但第二个却没有。我看看我自己能不能解决这个问题,谢谢你的建议!
当然,现在我遇到了问题,因为我手动选择一个选项来从管道中获取数据。我将不得不想出一种方法,要么在每次更新时获取所有管道的数据,要么确保只获取最新的数据(可能一次只获取一个字符)。
谢谢你们忍受我!我很抱歉没有发布整个程序......但确实有很多。我绝对应该提到我将它置于无限循环中。
I'm not sure if I am even barking up the right tree here... but here goes.
I'm trying to pass data from my parent process to all children. It's a simple server program that basically will keep a list of connected clients and then send the routing table of connected clients to every client. This is eventually going to include a struct of information about each client... but for right now I just want to get every forked process to get the same information from the parent.
In the parent process, first I set up my pipes and set them to nonblocking (for when there isn't any new data available in the pipe). After a connection is made with a client the number of entries variable is increased to reflect this new connection. I then fork a child process to a new function and update my array of pipes with the new number of table entries (I have 10 pipes at the moment to see if I needed to keep a separate pipe for each child).
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);
}
And then I try to read whats in the pipe in the recievecmds() function:
nbytes = read(mypipe[childindex][0], buf, sizeof(buf));
The first client connected tells me numentries = 1, the second client tells me numentries = 2 and so on. I mean I really don't even see the point for a pipe since it seems that whatever I put in the pipe I could just pass it in the function I called on the fork. Am I going about this the wrong way? It's been very frustrating trying to figure this out. How can I keep all of my child processes updated concurrently from my parent process?
Thank you so much in advance.
edit - My main problem was that I was redeclaring the pipe everytime in an infinite while loop. Very dumb mistake, immediately realized that was probably the root of my problem. However, while now the first child/pipe combo contains the correct data... the second does not. I'll see if I can figure this out on my own, thanks for the advice!
Of course now I'm running into problems because I manually select an option to get the data off the pipe. I'm going to have to think up a way to maybe either get the data for all pipes every time it's updated or make sure to get just the newest data (probably just one char at a time).
Thanks for putting up with me guys! And I apologize about not posting the whole program... but there's quite a bit. I definitely should have mentioned that I have it in an infinite loop.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
各种观察
工作代码
Various observations
Working code
我建议使用共享内存段。您的父进程和子进程可以映射同一文件,并对其进行读/写状态。这可以是实际文件,也可以是匿名内存段。这正是 Apache 对其 ScoreBoardFile 所做的事情。
I'd suggest using a shared memory segment. Your parent and child processes can mmap the same file, and read/write state to it. This can be an actual file, or an anonymous memory segment. This is exactly what Apache does with their ScoreBoardFile.