我想创建一些中文耳语(或电话)游戏。
我创建了一定数量的子进程,每个子进程必须从字符串中更改1个字母。父节点更改一个字母,然后第一个子节点获取父节点修改的字符串并再更改一个字母。第二个子元素接受第一个元素修改过的字符串(已经改变了2个字母),然后再改变一个,以此类推。
因此,我想用一个管道连接父节点和第一个子节点以及每两个连续的子节点。问题是,这并不适用于超过3个孩子。第三个子进程不读取第二个进程的数据,而是读取父进程的数据。你能告诉我我做错了什么吗?
int nrch;
nrch=(int) strtol(argv[2], (char **)NULL, 10);
msg=argv[3];
printf("Parent: erhalten: %sn", msg);
int i=0;
msg=modify(argv[3],nrch);
printf("Parent: weiter: %sn", 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: %sn", (i+1), msg);
msg=modify(msg,i);
printf("child%d: weiter: %sn", (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: %sn", (i+1), msg);
msg=modify(msg,i);
printf("child%d: weiter: %sn", (i+1), msg);
printf("child%d: Ende: %sn", (i+1), msg);
exit(0);
}
else{
close(fdold[1]);
close(fd[0]);
read(fdold[0],msg,sizeof(msg));
printf("child%d: erhalten: %sn", (i+1), msg);
msg=modify(msg,i);
printf("child%d: weiter: %sn", (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]);
我认为你为孩子写的代码太复杂了。在循环的每次迭代中,您似乎都是从父级编写的。
您正确地为每个子进程创建了一个管道,但我没有看到将管道的一边从一个兄弟进程传递到另一边的机制,这是父进程需要管理的事情。
在下面的代码中,我在父类中使用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: %sn", id, msg);
modify (msg, id);
printf("child%d: says: %sn", 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: %sn", 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 = %dn", nrch);
msg = argv[3];
printf("Parent: original message: %sn", msg);
if (nrch == 0 || nrch > strlen (msg))
error ("Invalid number of children");
msg = modify (msg, nrch);
printf("Parent: will start by saying: %sn", 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: %dn", 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;
}