использовать dup2 для перенаправления printf не удалось - PullRequest
0 голосов
/ 06 мая 2019

Код следующий.

1:

Если dup2(fd3, STDOUT_FILENO), string2 будет в log.txt.

Если dup2(g_ctl[0], STDOUT_FILENO), string2 не будет получено g_ctl[1]. string1 и ls -al выход будет получен, почему?

2:

В третьей библиотеке есть некоторый журнал stdout / stderr, при использовании dup2(socket_fd, STDOUT_FILENO) все журналы будут собираться сокетом. Но я также хочу распечатать все журналы одновременно, как это сделать?

#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 Ответ

0 голосов
/ 06 мая 2019

Q1: вам нужно fflush(stdout); после вашего printf.В противном случае printf может буферизовать ваш вывод.Она будет написана, когда ваша программа завершит работу, если она еще не завершилась, но к тому времени ваша нить чтения уже была отменена, поэтому вы не сможете ее прочитать.

Q2: Насколько я знаюединственный способ получить выходные данные, записанные в два файла, - это записать их в оба дескриптора файла.В Unix нет способа "дважды дублировать" дескриптор файла.Даже такая команда, как tee, на самом деле просто вызывает write() дважды для каждого фрагмента прочитанных данных.Вы можете сделать это вручную, либо внутри функции, либо в потоке, но вы должны это сделать.

...