我想创造一些中国私语(或电话)游戏。
我创建了一定数量的子进程,每个子进程都必须从字符串中更改1个字母。父进程更改一个字母,然后第一个子进程更改父进程修改的字符串并再更改一个字母。第二个孩子接受第一个孩子修改的字符串(2个字母已经更改)并再更改一个,依此类推。
因此,我想将父母和第一个孩子以及每两个连续的孩子用管道连接起来。 问题是这对3个以上的孩子不起作用。第三个孩子不从第二个孩子读取,它从父母那里读取。你能告诉我我做错了吗?
int nrch;
nrch=(int) strtol(argv[2], (char **)NULL, 10);
msg=argv[3];
printf("Parent: erhalten: %s\n", msg);
int i=0;
msg=modify(argv[3],nrch);
printf("Parent: weiter: %s\n", msg);
pid_t pids[10];
int fd[2];
int fdold[2];
if (pipe(fdold) == -1) {
error("Can't create the pipe");
}
/* Start children. */
for (i = 0; i < nrch; ++i) {
if (pipe(fd) == -1) {
error("Can't create the pipe");
}
if ((pids[i] = fork()) < 0) {
error("Can't fork process");
}
else if (pids[i] == 0) {
//dup2(fd[0], 0);
if(i==0){
close(fdold[1]);
close(fd[0]);
read(fdold[0],msg,sizeof(msg));
printf("child%d: erhalten: %s\n", (i+1), msg);
msg=modify(msg,i);
printf("child%d: weiter: %s\n", (i+1), msg);
write(fd[1],msg,sizeof(msg));
exit(0);
}
else if(i==(nrch-1)){
close(fdold[1]);
read(fdold[0],msg,sizeof(msg));
printf("child%d: erhalten: %s\n", (i+1), msg);
msg=modify(msg,i);
printf("child%d: weiter: %s\n", (i+1), msg);
printf("child%d: Ende: %s\n", (i+1), msg);
exit(0);
}
else{
close(fdold[1]);
close(fd[0]);
read(fdold[0],msg,sizeof(msg));
printf("child%d: erhalten: %s\n", (i+1), msg);
msg=modify(msg,i);
printf("child%d: weiter: %s\n", (i+1), msg);
write(fd[1],msg,sizeof(msg));
exit(0);
}
}
else{
if(i!=0){
close(fd[1]);
}
else{
write(fdold[1], msg,sizeof(msg));
}
if(i>1){
close(fdold[0]);
}
}
pid_t wpid;
int status;
wpid = wait(&status);
memcpy(fdold,fd,(sizeof(int)*2));
}
close(fd[0]);
答案 0 :(得分:1)
我认为你孩子的代码过于复杂。在循环的每次迭代中,您似乎也都是从父级写入的。
您为每个子进程正确创建了一个管道,但是我没有看到将管道的一侧从一个兄弟传递到另一个兄弟的机制,这是父进程需要管理的内容。
在下面的代码中,我使用父节点中的prev_in将管道的读取端最初从父节点传递给第一个子节点,然后从兄弟节点传递给兄弟节点,最后父节点将其用作其管道的读取端。
我没有检查此代码是否存在可能存在的任何缓冲区溢出问题,我只查看了文件描述符管理问题,您应该注意检查其他错误。
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char *modify (char *word, int num)
{
printf ("Modify `%s', (%d)\n", word, num);
word [num] = 'x';
return word;
}
void
whisper (int id, int in, int out)
{
char msg [100];
read(in, msg, sizeof(msg));
printf("child%d: heard: %s\n", id, msg);
modify (msg, id);
printf("child%d: says: %s\n", id, msg);
write(out, msg, sizeof(msg));
}
void
start_whisper (int in, int out, char *msg)
{
char buf [100];
printf ("Parent, starting a whisper with `%s'\n", msg);
write(out, msg, strlen (msg) + 1); /* Also send the NUL. */
read(in, buf, sizeof(buf));
printf("Parent, heard back: %s\n", buf);
}
int
main (int argc, char *argv [])
{
int nrch, i;
char *msg;
pid_t pids[10];
nrch=(int) strtol(argv[2], (char **)NULL, 10);
printf ("Number of children = %d\n", nrch);
msg = argv[3];
printf("Parent: original message: %s\n", msg);
if (nrch == 0 || nrch > strlen (msg))
error ("Invalid number of children");
msg = modify (msg, nrch);
printf("Parent: will start by saying: %s\n", msg);
int fdold[2];
int prev_in, parent_in, parent_out;
if (pipe(fdold) == -1) {
error("Can't create the pipe");
}
printf ("Parent Read: %d, Write: %d\n", fdold [0], fdold [1]);
parent_in = fdold [0];
parent_out = fdold [1];
/* Start children. */
prev_in = parent_in;
for (i = 0; i < nrch; ++i)
{
int fd[2];
if (pipe (fd) == -1) {
error ("Can't create the pipe");
}
if ((pids[i] = fork()) < 0) {
error("Can't fork process");
}
else if (pids[i] == 0)
{
/* Child. */
int my_in, my_out;
close (fd [0]); /* The sibling read handle, this becomes prev_in
and is passed to the next sibling. */
close (parent_out); /* The parent write handle, only the parent
wants to hold this, every child will
close it. */
my_in = prev_in;
my_out = fd [1];
whisper (i, my_in, my_out);
exit (0);
}
else
{
/* Parent. */
close (prev_in); /* The PREV_IN was passed the child we just
created, we no longer need this. */
prev_in = fd [0]; /* The read handle from the pipe we just made
will be passed to the next sibling. */
close (fd [1]); /* The write handle from the pipe we just made
was grabbed by the child we just made, we no
longer need this. */
}
}
start_whisper (prev_in, fdold [1], msg);
pid_t wpid;
int status;
wpid = wait(&status);
return 0;
}