Напомним другой ответ, когда вы используете stdio, вы работаете с буфером, который не является реальным файлом. Этот буфер должен быть скопирован из фактического файла (через вызов OS read
), если вы читаете, и он должен быть скопирован в фактический файл (через вызов OS write
), если вы пишете. Если вы слишком поспешно переключаетесь, скажем, с записи на чтение, код stdio не осознает, что он должен очистить записанный буфер и перезагрузить буфер для чтения.
С другой стороны, при использовании системных вызовов read
и write
все иначе. Во-первых, вы можете читать и записывать устройство (например, последовательный порт или сетевой поток TCP), и в этом случае, очевидно, нет проблем с возвратом назад и между чтением и записью.
Но даже если вы используете системные вызовы read
и write
для чтения и записи файла, вы обращаетесь к файлу - или, по крайней мере, к представлению ОС о файле - напрямую. Ни одна из проблем, упомянутых для буферов stdio, не применяется.
(По иронии судьбы ОС обычно также работает с буферизованной копией одного или нескольких блоков файла. Но реализация совершенно иная, и не возникает проблем при переключении между чтением и обратно. и писать.)
Как объяснено в другом ответе, процедуры stdio могли бы быть написаны для поддержки чередующегося ввода-вывода, но не в интересах простоты и эффективности.
Почему так? Еще одна часть загадки заключается в том, что в первые дни C и Unix системные вызовы были чрезвычайно дорогими. Системный вызов может занять в 10 или 100 раз больше, чем обычный вызов функции. Таким образом, было действительно важно избегать ненужных системных вызовов, и библиотека stdio была большой частью этого. Для заполнения буфера требуется один вызов read
, а затем вы можете совершать множество небольших вызовов для извлечения отдельных (или небольшого числа) символов из буфера без дополнительных затрат. Точно так же во время записи вы можете сделать много маленьких вызовов, чтобы написать небольшое количество символов, а затем есть только один дорогой write
вызов для очистки буфера. Если бы поддержка stdio поддерживала чередование операций чтения и записи - что не рассматривалось как важный вариант использования - потребовалось бы больше системных вызовов, или больше тестов, или большего количества кода (или всех трех), и в целом это было бы дороже, чем это стоило.
(Сегодня системные вызовы гораздо менее неэффективны, поэтому, если бы сегодня C и Unix разрабатывались с нуля, различие между системными вызовами read
и write
и входными и выходными вызовами stdio могло бы сработать по-другому.)