我想创建一个小程序,接受来自stdin的用户输入,以获得他们想要的进程数,然后,我的程序将按用户指定的方式分叉n个进程。稍后,我想将子数据传输给父级。
但是,我只想要一个父进程。我一直试图弄清楚这个算法,也许我过于复杂了,但我被卡住了。
请注意我只能使用C中的fork和pipe功能(所以不要太疯狂!)
这是我的算法。
仅当我是父进程时才循环,如果我是子进程,则不循环。
如果我是进入循环的父进程,那么我将调用fork()。否则,我还是个孩子,我会做一些与孩子有关的任务(之后我可能会将这些任务交给父母)。孩子不应该重新进入循环,以避免创建子女进程。
这有意义吗?
你建议我做什么?
答案 0 :(得分:1)
让我们说n
是您输入的孩子数量。如果你为每个孩子使用一个烟斗,让我们看看你能做些什么。
在父流程中:
pid_t pid;
int fd[n][2];
for(i = 0; i < n; i++) {
pipe(fd[i]);
pid = fork();
if (pid < 0) {
perror("whatever");
exit(1);
}
else if (pid == 0) {
for(j = 0; j < i; j++) {
if (close(fd[j][0]) < 0) {
perror("closing fd[0]");
exit(1);
}
if (close(fd[j][1]) < 0) {
perror("closing fd[1]");
exit(1);
}
}
func(fd[i]);
}
}
// other parent stuff next && close file discriptors not needed
你的func()
应该是孩子们必须做的事情。它将子管道的2个文件描述符作为参数。请注意,在func
的末尾,您应该exit()
。
为每个孩子制作一个管道的解决方案会好一点但比这更复杂一点(提示:你可以传递fd&#39; s作为参数,也要小心关闭所有fd!)< / p>
此外,您可以通过定义pid
而不是pid_t pid[n];
来保留每个孩子的pid
,并将每个pid称为pid[i]
。
答案 1 :(得分:0)
如果是我,我会将所有fork()
和pipe()
内容移动到它自己的子程序中,并使用明确的语义,并从main()
中的循环中调用该子程序。 / p>
在下面的示例中,spawn()
forks调用child中的work函数,确保子项正确退出,并在父项中返回。
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
/* Launch a child. This routine exit()s in the child and
* return()s in the parent */
void spawn(void (*fn)(int), int *fd) {
int pipefd[2];
int pid;
if(pipe(pipefd) < 0) {
perror("pipe");
exit(1);
}
switch(pid = fork()) {
case -1: /* Error */
perror("fork");
exit(1);
break;
case 0: /* Child */
close(pipefd[0]); /* Kids only talk */
fn(pipefd[1]); /* Put the kid to work */
exit(0); /* Kill the kid */
break;
default: /* Parent */
close(pipefd[1]); /* Parents only listen */
*fd = pipefd[0];
printf("Spawning PID=%d, FD=%d\n", pid, *fd);
break;
}
}
int
get_number_of_children() {
/* TODO: Do stdin-reading here and return a good number */
return 3;
}
void do_work(int fd) {
/* TODO: Whatever work the children might do */
/* For example: */
write(fd, "hello", 5);
}
int main (int ac, char **av) {
int nkids = get_number_of_children();
int fd_array[nkids];
int pid;
/* Birth the children */
for(int i = 0; i < nkids; i++) {
spawn(do_work, &fd_array[i]);
}
/* TODO: Read the data from the file descriptors in fd_array */
/* Finally, wait for all children to die */
while((pid = wait(0)) != -1) {
printf("Waited PID=%d\n", pid);
}
}