Перенаправить вывод безымянного канала в файл журнала в c

Я хочу перенаправить вывод безымянного канала в открытый файл журнала в c, но я не могу этого добиться, мой код выглядит так:

close(fildes[1]); 

FILE * file = fopen(logfile, "w");
int fd = fileno(file);

if (fd == -1) {
bail_out(EXIT_FAILURE, strerror(errno));   
}

/* if (dup2(fd, fildes[0]) == -1) {
      bail_out(EXIT_FAILURE, strerror(errno));   
   } */


/* for testing purposes */
char reading_buf[3];
while(read(fildes[0], reading_buf, 3) > 0) {
  write(fd, reading_buf, 1); 
}


(void)wait(&status);
close(fildes[0]);
break;

труба наполняется, я проверил это с помощью цикла while внизу. но когда я закомментирую вызов dup2, ничто не будет перенаправлено в файл. я думаю, что я не полностью понимаю dup2 и трубы.

Кроме того: если я дублирую конец чтения канала и затем закрою исходные файлы [0], будет ли канал закрыт? или это просто FD, который закрывается. не совсем следует об этом либо..

1 ответ

Решение

Чтобы перенаправить вывод из канала в файл, кто-то должен прочитать с конца чтения канала и записать в файловый дескриптор файла. Это не может быть сделано просто путем дублирования файловых дескрипторов.

Например, скажем, у вас есть труба

int filedes[2];
pipe (filedes);

и файл

FILE *logfile = fopen (logfile_path, "w");
int logfd = fileno (logfile);

Вы можете запустить дочерний процесс, чтобы сделать перенаправление, используя cat команда

int child = fork ();
if (child == 0) {
    // close the write end of the pipe
    close (filedes[1]);
    // make STDOUT point to the log file
    dup2 (logfd, STDOUT_FILENO);
    // make STDIN point to the read end of the pipe
    dup2 (filedes[0], STDIN_FILENO);
    // launch cat
    execlp ("cat", "cat", (char*) NULL);
    // in case of error
    exit (1);
}

Теперь все, что записано в конец записи канала в родительском объекте, будет прочитано дочерним элементом, выполняющим команду cat, и записано в файл.

// close the read end of the pipe, it's not needed in the parent
close (filedes[0]);
// write something
const char *msg = "Hello World!\n";
write (filedes[1], msg, strlen (msg));
// close the write end of the pipe, this will make the child read EOF
close (filedes[1]);

Не забудьте собрать зомби

wait (&status);

и закройте файл

fclose (logfile);

Что касается вашего последнего вопроса, когда дескриптор файла будет дублирован, два из них будут указывать на один и тот же открытый открытый файл. Таким образом, когда один из них закрыт, файл остается открытым, так как к нему можно получить доступ через другой дескриптор.

Это объясняется в close справочная страница:

Если fd является последним файловым дескриптором, ссылающимся на описание открытого открытого файла (см. Open(2)), ресурсы, связанные с описанием открытого файла, освобождаются;

Другие вопросы по тегам