管道和fork() - 如何在C语言中通过管道写入一个整数数组?

4

我正在尝试学习C语言中的管道,但是卡住了。我尝试了很多事情,但是无法获得正确的输出。

下一个程序应该显示:

123

但它的输出总是有方向性的(除非我想):

-1845296639

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

int main (int argc, char *argv[]){

    int i;
    int buff[4];
    int f[2];

    if(pipe(f) == -1)
        perror("pipe");

    for(i=0; i<3; i++){ 

        int val = i+1;
        switch(fork()){
            case -1:
                perror("fork");
                break;
            case 0:
                close(f[0]);
                write(f[1], &val, 1);
                exit(0);
                break;
            default:
                break;
        }
    }
    close(f[1]);

    for(i=0; i<3; i++)
        wait(NULL);

    read(f[0], buff, i);
    printf("%d", *buff);

    exit(0);
}

你正在通过管道写入一个单个字节 - 你想要写入sizeof(int)字节。读取时同理。 - user4815162342
你需要使用管道吗?fork的进程共享指针,因此如果您提前分配了空间,则两者都可以使用。 - Dave
2个回答

4
管道将字节从一个位置发送到另一个位置。因此,您需要精确地指定要发送的字节。然后确保您的发送代码准确地发送那些字节,并且接收代码期望准确地那些字节。
如果您希望它能够正常工作而无需正确处理,请执行以下操作:
发件人:
write(f[1], &val, sizeof(int));

接收器:

for (int i = 0; i < 3; ++i)
  read(f[0], &buf[i], sizeof(int));

请注意,printf("%d", *buff);会打印出数组中的第一个元素(零号元素)。

不要修改接收代码为read(f[0], buf, 3 * sizeof(int));。你的write不是原子操作(因为你调用了三次write),所以你不能指望你的read也是原子操作。


1
-1845296639的二进制模式是0x92030201,假设是32位二进制补码int
因此,使用未初始化的缓冲区会得到一个垃圾字节和由fork子进程写入的三个字节。
可能你的平台是小端序,这意味着在内存中,字节为:
0x01 0x02 0x03 0x92

所以写入的字节按照预期顺序到达,尽管期望read(...,...,3)在三个子进程每个写入一个字节后读取三个字节是大胆的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接