首页 文章

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

提问于
浏览
3

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

    在读取之后,您需要在打印之前添加终止 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页面......

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

  • 3

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

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

    因此,请务必检查 readwrite 调用的返回值,并准备好处理比预期少于(或更多 read )的值 .

相关问题