Перенаправить вывод безымянного канала в файл журнала в 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)), ресурсы, связанные с описанием открытого файла, освобождаются;