我只想创建2个新的forks(子进程),他们将名称后续。首先,他们需要在管道中使用一些字符串来检查某些东西。我们来看看代码:
char myname[] = "ALOAA";
int main ()
{
int fds[2];
pid_t pid;
pipe(fds);
pid = fork();
if(pid == 0)
{
strcpy(myname, "first");
}
else
{
pid = fork();
if(pid == 0)
{
strcpy(myname, "second");
}
}
if(strcmp(myname, "ALOAA") != 0)
{
char readbuffer[1025];
int i;
for (i = 0; i < 2 ; i++)
{
//printf("%s\n", myname);
close(fds[0]);
write(fds[1], myname, strlen(myname));
while(1)
{
close(fds[1]);
int n = read(fds[0], readbuffer, 1024);
readbuffer[n] = 0;
printf("%s-alihan\n", readbuffer);
if(readbuffer != myname)
break;
sleep(1);
}
//printf("%s\n", myname);
}
}
return 0;
}
所以第一个进程会将她的名字写入管道。然后,将检查管道中是否有新的字符串。第二个也一样。但是我从read()函数得到了空字符串。所以它打印就像那样
-alihan
-alihan
我无法解决问题。
答案 0 :(得分:0)
但是我从read()函数中获取了空字符串[...]我无法解决问题。
@MikeCAT在评论中发现了这个问题,即每个孩子在尝试阅读之前关闭fds[0]
。没有其他文件被分配相同的FD,因此读取失败。你没有测试失败。
不测试读取失败是一个重大问题,因为您的程序不仅无法识别它 - 因此它会显示未定义的行为。出现(至少)两个原因:
read()
将通过返回-1
表示失败,并且您的程序将通过尝试越界写入(readbuffer[-1]
)来响应。
如果我们忽略由(1)产生的UB,我们仍然让程序从完全未初始化的数组readbuffer
读取(因为read()
调用和赋值都不会设置该数组中任何元素的值。)
总的来说,你需要学习检查库函数调用的返回值是否存在错误条件的规则,至少在出错的地方(对于大多数调用来说都是重要的)。例如,您对pipe()
,fork()
和write()
的使用也会出现此问题。在某些情况下,您希望检查printf()
- 族函数的返回值,并且通常要检查输入函数的返回值 - 不只是read()
,而是scanf()
,{ {1}}等等。
暂时,您对fgets()
和read()
的使用不正确。你犯了一个常见的错误:假设(成功时)write()
将可靠地写入指定的所有字节,并且write()
将读取已写入的所有字节,直到指定的缓冲区大小。虽然这通常适用于通过管道交换短消息,但无法保证。通常,read()
可能只执行部分写入,write()
可能只执行部分读取,原因不明,不可预测。
要成功写入,通常必须准备好在循环中重复read()
次调用,使用返回值来确定开始下一次写入的位置(或是否)。要成功读取完整的消息,通常必须准备好类似于循环中重复write()
调用,直到已将所需的字节数读入缓冲区,或者直到满足某些其他终止条件,例如结束正在联系的文件。我认为不会因为许多形式需要提前知道要读取的字节数而丢失。