通过C中的管道进行读/写

时间:2013-02-13 21:17:24

标签: c fork pipe

我今天开始在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()

之前没有被使用过。

提前谢谢!

2 个答案:

答案 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)

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

此外,如果管道已满,写入可能无法写入您要求的所有数据 - 它可能只写入现在适合的数量,您将不得不稍后编写其余的数据。

因此,请务必检查readwrite来电的返回值,并准备好处理低于(或read)的预期值。