【发布时间】:2015-09-08 14:09:00
【问题描述】:
请看下面的代码:
#include<stdio.h>
main(){
int pid, fds[2], pid1;
char buf[200];
pipe(fds);
pid = fork();
if(pid==0)
{
close(fds[0]);
scanf("%s", &buf);
write(fds[1], buf, sizeof(buf)+1);
}
else
{
pid1 = fork();
if(pid1==0)
{
close(fds[1]);
read(fds[0], buf, sizeof(buf)+1);
printf("%s\n", buf);
}
else
{
Line1: wait();
}
}
}
如果我不注释掉 Line1,它工作正常。请看下面:
hduser@pc4:~/codes/c/os$ ./a.out
hello //*Entry from keyboard*
hello //Output
hduser@pc4:~/codes/c/os$
但是如果我注释掉Line1,两个子进程没有通信:
hduser@pc4:~/codes/c/os$ ./a.out
hduser@pc4:~/codes/c/os$
hi //*Entry from keyboard*
hi: command not found
hduser@pc4:~/codes/c/os$
这里我无法理解 wait() 的意义。
【问题讨论】:
-
read(fds[0], buf, sizeof(buf)+1);是未定义的行为。它将 201 个字节读入一个 200 字节的数组中。 -
调试的第一步是测试每个系统调用以查看失败的原因。写入标准错误。我也会写进度报告。你应该用半现代的 C(至少 C99)编写;这需要
<unistd.h>和main()的正确声明。 -
首先,'pid' 被定义为在
unistd.h头文件中定义的 'pid_t',发布的代码丢失了。 -
这两行:
scanf("%s", &buf); write(fds[1], buf, sizeof(buf)+1);有几个问题: 1) 始终检查 scanf() 的返回值(不是参数值)以确保操作成功。 2) 使用 %s 输入/格式参数时,始终包含一个长度修饰符 (sizeof(buf)-1),这样用户就不会溢出缓冲区。 3) 要发送的字节数永远不会比缓冲区长(通常更短)建议:`write(fds[1], buf, strlen(buf)+1);' -
发布的代码存在严重的逻辑问题。
fork()函数可以返回 3 种值:发生错误时为 -1,在子进程中执行时为 0,在父进程中执行时为某个正数。发布的代码未能检查对 fork() 的调用的错误情况