Что такое определенная POSIX буферизация для файла, открытого после закрытия стандартного вывода? - PullRequest
1 голос
/ 04 октября 2019

Допустим, у меня есть следующий код:

close(1);
int fd = open("temp.txt", O_WRONLY | O_CREAT);
if (fork() == 0)
    printf("Message from A\n");
printf("Message from B\n");

Я знаю, что stdout является линейным буфером, и я заметил, что, по крайней мере в моей системе, это работает так, как можно было ожидать.

т.е.

Содержимое temp.txt :

Message from B
Message from A
Message from B

Однако, как POSIX определяет поведение для приведенного выше кода? Сохраняется ли буферизация строки для файлового дескриптора 1 (даже после close())? Это неопределенно? Что-то другое? Я предполагаю, что команда open() всегда будет использовать дескриптор файла 1 для temp.txt в приведенном выше коде.

Кроме того, возможно ли, скажем, только часть "Message from A\n" или "Message from B\n" для записи в буфер, связанный с дескриптором файла 1, перед тем как процессор загрузит другой процесс и перезапишет только что записанное частичное сообщение?

например

Возможно ли эточто родительскому родительскому процессу удается только записать «Message» в буфер до того, как дочерний процесс прервет его, что приведет к следующему содержимому в temp.txt (или что-то подобное):

Message from A
 from B
Message from B

ПРИМЕЧАНИЕ:

Код выше - это то, что было дано мне в задании, которое я имею для одного из моих классов. Я понимаю, что лучше открыть файл и затем вызвать dup2(), а не закрывать дескриптор файла 1, а затем открывать файл.

Ответы [ 2 ]

2 голосов
/ 05 октября 2019

Если стандартный вывод является клеммой, он буферизируется. Если это файл, он не должен быть. Это зависит от платформы / реализации.
Во второй программе-примере вы не видите 1000 строк, потому что вы завершаете дочерние процессы с помощью _exit.

if (pid == 0)
{

    _exit(0);
}

Вместо этого вы должны использовать выход. Разница в том, что exit выполняет такие вещи, как закрытие файлов и очистка потоков, а затем вызывает _exit для фактического завершения. Если вы завершаете дочерние процессы обычным завершением (или просто позволяете им завершаться в конце основного цикла), их выходные данные также должны быть сброшены в файл.

Обновление: соответственно, _exit сбрасывает потоки или нет, определяется реализацией, это, вероятно, причина, по которой Barmar сталкивался с разными результатами в Mac и Linux, но выход всегда сбрасывает. Цитата из ссылки _exit:

Закрытие открытых потоков (без очистки) определяется реализацией

0 голосов
/ 04 октября 2019

POSIX не определяет буферизацию C, это определяется стандартом C.

Буферизация по умолчанию для стандартных потоков ввода и вывода определяется при запуске программы. Изменение FD, связанного с потоком, не влияет на это. Если stdout изначально был связан с терминалом, он будет буферизован строкой, и открытие файла на FD 1 не изменит этого, поэтому он все еще буферизуется при записи в файл.

...