我今天开始在C中使用pipe()和fork()以及exec(),现在我遇到了一个问题:
主程序,创建两个管道和叉子。子进程对另一个程序执行exec(),该程序现在只是一个从stdin读取的测试程序,与其父进行通信并通过stdout结果进行写入。主程序应该返回数据,与SQLite 3数据库通信并使用管道返回数据。问题的这一部分得到了解决,管道正确地打开和关闭,并且有沟通。
然后问题是,在子进程(用exec()调用的那个)中某个点,我有这个:
printf("Strid sent: %s\n", strid);
write(4,strid,sizeof(strid));
printf("Str sent: %s\n", str);
write(4,str,sizeof(str));
父母应该正确阅读这部分内容:
read(select[0],strid, sizeof(strid));
printf("Strid recived: %s\n",strid);
int id = atoi(strid);
printf("Id recived: %d\n",id);
read(select[0],buffer, sizeof(buffer));
printf("Buffer recived: %s\n",buffer);
但我记得那些printf是:
Strid sent: 1
Str sent: start
Strid recived: 1
Id recived: 1
Buffer recived: 7� (and other strange characters)
正如您所看到的,问题在于接收第二个命令(并且该部分按原样复制,其中没有其他代码)。
我不得不说,“缓冲”变量,它接收str,被声明为char缓冲区[20]并且在read()
之前没有被使用过。提前谢谢!
答案 0 :(得分:3)
阅读之后,您需要在打印之前添加终止0
字节,例如
int len = read(select[0], buffer, sizeof(buffer) - 1);
if (len < 0) {
perror("read error");
} else {
buffer[len] = 0;
printf("Buffer recived: %s\n", buffer);
}
所以,重要的是,在你使用之前阅读man page of read
,或任何函数的man page ...
或者,使用一些 stdio.h 函数,它会自行添加字符串0
,如果逐行读取则可能fgets
。
答案 1 :(得分:0)
管道不会跟踪写入之间的“边界”。因此,如果管道上有多个写入,则这些写入的所有数据可能会返回以响应单个读取。因此,如果您发送一个字符串(例如)后跟一个整数,并尝试将字符串读入缓冲区,它将获取字符串和后面的整数整数到缓冲区中,看起来像字符串末尾的垃圾,读取返回的大小会更大。
此外,如果管道已满,写入可能无法写入您要求的所有数据 - 它可能只写入现在适合的数量,您将不得不稍后编写其余的数据。
因此,请务必检查read
和write
来电的返回值,并准备好处理低于(或read
)的预期值。