Буферизируется ли с помощью stdio.h async? - PullRequest
2 голосов
/ 21 февраля 2012

Я понимаю, что одним из преимуществ использования stdio.h FILE перед прямым read() / write() является буферизация, обработка прерываний и т. Д. Так что, как я понимаю, все fwrite() буферизуются пока я не сделаю fclose(). Все идет нормально. Теперь, когда я выполняю fclose(), я буду блокировать, пока данные не будут сброшены на диск, или fclose() сразу же вернется после передачи данных в ОС и разрешения их сброса на диск в свободное время?

Ответы [ 2 ]

3 голосов
/ 21 февраля 2012

Есть буферизация на многих уровнях, это зависит от ОС и многих других вещей.

Обычно в FILE * находится внутренний буфер в вашем приложении, который либо выгружается в файл (или на любое устройство, к которому подключен FILE *)

  • когда внутренний буфер FILE * заполнен
  • когда вы пишете новую строку (в случае строки с буферизацией FILE *)
  • при закрытии ФАЙЛА *
  • при вызове fflush ()
  • ФАЙЛ * также может быть небуферизован

В случае обычного дискового файла большинство ОС имеют буферизацию в ядре, поэтому Буфер FILE * включает в себя более или менее простую копию памяти из буфера вашего приложения в ядре ОС, и ядро ​​позаботится о том, чтобы записать его в текущий файл на досуге асинхронно, что приведет к возврату fclose () "прямо сейчас".

Могут возникнуть обстоятельства, когда ОС сначала придется выполнить некоторую служебную работу, прежде чем данные будут скопированы в буферы ОС / ядра, например, может потребоваться сброс данных в физический файл, чтобы освободить место для дополнительных данных, выделить место в файле, чтобы обеспечить место, и т. д., чтобы он не возвращался мгновенно.

Короче, это зависит, и вы не можете это контролировать. Обычно «лучшее», что вы можете сделать, это использовать зависящие от платформы API, которые, по крайней мере, позволяют сбрасывать буферы ОС в физический файл, например API posix fsync () / fdatasync ().

0 голосов
/ 21 февраля 2012

Ваше понимание (хотя бы частично) неверно.

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

Я не думаю, что вызовы обязательно блокируются, в противном случае существуют функции, которые пытаются убедиться, что базовый носитель синхронизирован, например, с записями. Это обычно создает проблемы, когда вы получаете «слишком низкий уровень» и вам приходится иметь дело со сложностями кэшей и буферов как программного обеспечения, так и аппаратного обеспечения, например. жесткие диски.

...