4

我今天开始在 C 中使用 pipe() 和 fork() 和 exec(),现在我遇到了一个问题:

主程序,创建两个管道和分叉。子进程对另一个程序执行 exec(),该程序现在只是一个测试程序,它从标准输入读取,与其父进程通信并通过标准输出写入结果。主程序应该接收数据,与 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 的“buffer”变量被声明为 char buffer[20] 并且在 read() 之前没有被使用过

先感谢您!

4

2 回答 2

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);
}

所以,重要的是,在使用之前通读任何函数的手册页read,或者实际上是手册页......

或者,使用一些stdio.h函数,它会添加自己终止的字符串0,可能fgets如果逐行读取是可以的。

于 2013-02-13T21:26:58.083 回答
0

管道不跟踪写入之间的“边界”。因此,如果您在管道上进行了多次写入,则来自这些写入的所有数据可能会返回以响应一次读取。因此,如果您发送一个字符串(例如)后跟一个整数,并且您尝试将字符串读入缓冲区,它会将字符串和后面的整数整数都放入缓冲区,看起来像字符串末尾的垃圾, read 返回的大小会更大。

此外,如果管道已满,则写入可能不会写入您要求它写入的所有数据——它可能只写入目前可以容纳的量,而您必须稍后再写入其余的数据。

read因此,请始终检查您的和调用的返回值,write并准备好处理read比您预期的要少(或多于)的情况。

于 2013-02-13T21:49:41.397 回答