我正在编写一个程序,其中父进程需要能够与另一个子进程通信,因此我编写了一个函数,将子进程的标准输出和输入重定向到管道.

int create_child_piped_io(int* pipe_in, int* pipe_out, const char* program, char* argv[], char* envp[])
{
    int stdin_pipe[2];
    int stdout_pipe[2];
    int child;


    if(pipe(stdin_pipe) < 0)
    {
        return -1;
    }

    if(pipe(stdout_pipe) < 0)
    {
        close(stdin_pipe[0]);
        close(stdin_pipe[1]);
    }
    
    child = fork();
    

    if(child == 0)
    {
        close(stdin_pipe[1]);
        close(stdout_pipe[0]);

        if(dup2(stdin_pipe[0], STDIN_FILENO) < 0)
        {
            close(stdin_pipe[0]);
            close(stdout_pipe[1]);

            exit(errno);
        }

        if(dup2(stdout_pipe[1], STDOUT_FILENO) < 0)
        {
            close(stdin_pipe[0]);
            close(stdout_pipe[1]);

            exit(errno);
        }

        close(stdin_pipe[0]);
        close(stdout_pipe[1]);

        execve(program, argv, envp);

        exit(1);
    }
    else if(child > 0)
    {
        close(stdin_pipe[0]);
        close(stdout_pipe[1]);

        *pipe_in = stdin_pipe[1];
        *pipe_out = stdout_pipe[0];

        return child;
    }
    else
    {
        close(stdin_pipe[0]);
        close(stdin_pipe[1]);
        close(stdout_pipe[0]);
        close(stdout_pipe[1]);


        exit(errno);
    }

    return child;

}


int main()
{
    int input, output;
    char* argv[] = {"program"};
    char* envp[] = {NULL};
    int cpid = create_child_piped_io(&input, &output, "/home/jaden/dev/c++/pipes/program", argv, envp);


    
    char c;


    while(read(output, &c, 1) == 1)
    {
        printf("%c", c);
    }
    printf("done\n");
    int status;
    waitpid(cpid, &status, 0);
    
    close(input);
    close(output);

}

这很好,但我注意到,当从子进程向标准输出写入时,它不会立即被发送到管道.这是子进程将运行的程序.

int main()
{
    // i < 1025 gets sent to pipe after sleep(10)
    // i > 1025 send first 1024 bytes to pipe immediately
    for(int i = 0; i < 1024; i++)
    {
        write(1, "a", 1);
    }
    
    sleep(10);
    return 0;
} 

只有在子进程结束后,输出才会被发送到管道.我try 发送不同数量的数据.事实证明,每次我向stdout写入超过1024个字符时,它都会被发送到管道中.这让我相信它正在被缓冲.我不明白为什么会这样,因为管道也是内存中的缓冲区,所以它只是缓冲缓冲区.如果这是标准行为,有没有办法将其关闭,因为我希望在写入数据后尽快获取数据.

我正在使用linux mint 20.3.

推荐答案

你的问题是:

    while(read(output, &c, 1) == 1)
    {
        printf("%c", c);
    }

当您使用系统调用进行阅读时,您正在使用连接到终端的printf()通过glibc stdio进行书写.输出为Line-Buffered.如果您将代码更改为使用系统调用编写,例如.

    while(read(output, &c, 1) == 1)
    {
        write (1, &c, 1);
    }

神秘的缓冲消失了.

正如@ShadowRanger所指出的,如果您需要stdio.h函数提供的格式,那么您可以使用setvbuf()将连接到终端时stdout的正常line-buffering更改为无缓冲.e、 g.setvbuf(stdout, NULL, _IONBF, 0);这将通过printf()等实现输出..以无缓冲的方式使用.见man 3 setbuf

C++相关问答推荐

单指针和空参数列表之间的函数指针兼容性

如何在C中通过套接字自定义数据类型读取原始变量?

如何在不使用其他数组或字符串的情况下交换字符串中的两个单词?

当输入负数时,排序算法存在问题

如何在STM8项目中导入STM8S/A标准外设库(ST VisualDeveloper)?

用C++从外部ELF符号读取值

用C语言计算文本文件中的整数个数

如何仅使用软件重新初始化STM32微控制器中的USB枚举?

正数之和是负数

收到不兼容的指针类型警告,因为函数的返回不是空*,而是 struct 指针

循环中的静态变量与块中的变量和循环

计算SIZE_MAX元素的长数组的大小

即使我在C++中空闲,也肯定会丢失内存

C中的空指针是什么(_N)?

我错误地修复了一个错误,想了解原因

struct 中的qsort,但排序后的 struct 很乱

将数组中的所有元素初始化为 struct 中的相同值

GnuCobol 使用 double 类型的参数调用 C 函数

cs50拼写器分配中的无限循环

如何修复数组数据与列标题未对齐的问题?