c - 使用 dup2 重定向 printf 失败

标签 c linux printf dup2 socketpair

代码如下。

问题 1:

如果 dup2(fd3, STDOUT_FILENO)string2 将在 log.txt 中。

如果 dup2(g_ctl[0], STDOUT_FILENO)string2 将不会被 g_ctl[1] 接收。 string1ls -al 输出将被接收,为什么?

问题 2:

第三个库有一些stdout/stderr日志,如果使用dup2(socket_fd, STDOUT_FILENO),所有的日志都会被socket收集。但是我也想同时打印所有日志到屏幕,怎么办?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>

static pthread_t g_pid;
static int g_ctl[2] = {-1, -1};

void *_run_loop(void *args) {
    char buf[1024];
    int n;
    while (1) {
        n = recv(g_ctl[1], buf, 1024, 0);
        if (n > 0) {
            fprintf(stderr, "%.*s\n", n, buf);
        }
    }
}

int main(int argc, char const *argv[])
{
    int fd3 = open("./log.txt", O_CREAT | O_RDWR | O_APPEND, 0666);

    int ret = socketpair(AF_UNIX, SOCK_STREAM, 0, g_ctl);
    assert(ret == 0);

    ret = dup2(g_ctl[0], STDOUT_FILENO);
    assert(ret > 0);

    pthread_create(&g_pid, NULL, _run_loop, NULL);

    send(STDOUT_FILENO, "string1", 5, 0);
    system("ls -al");

    printf("string2\n");

    sleep(5);

    return 0;
}

最佳答案

问题 1:您需要在 printf 之后 fflush(stdout);。否则 printf 可能会缓冲您的输出。它会在您的程序退出时写入(如果尚未写入),但到那时您的阅读线程已经被取消,因此您无法阅读它。

Q2:据我所知,将输出写入两个文件的唯一方法是将其实际写入两个文件描述符。在 Unix 中没有办法“双重复制”一个文件描述符。即使像 tee 这样的命令实际上也只是为读取的每个数据 block 调用两次 write()。您可以手动完成,也可以在函数内部或线程中完成,但您必须这样做。

关于c - 使用 dup2 重定向 printf 失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55998454/

相关文章:

linux - 如何获得一个进程的总内存,该进程在 linux 中使用 shell fork 了许多子进程?

c - 在 C 中连接字符串的最谨慎的方法

使用 sscanf 比较字符串,但忽略空格

c - 如何在c中执行外部程序

linux - 如何在 2-3 行匹配模式之前插入一行

bash - bash 中的 Printf 示例不会创建换行符

php - C++ 'php_sprintf' 如何返回这个值?

c - 为什么我的 C 程序显示的 int 与应有的不同

c - 堆栈变量损坏? C

c++ - GDB "cannot open shared object file"问题