Между голым металлом и stdio достаточно места. Вы сказали, что не пишете ядро ОС, но не знаете, работаете ли вы под ОС.
Работая непосредственно на оборудовании без ОС, вы все равно захотите инкапсулировать все свои операции ввода-вывода в модуле, даже если вы формально не определяете интерфейс и структуру драйвера устройства для всех ваших модулей ввода-вывода следить. Это сильно зависит от архитектуры и делает вас ответственным за знание всех деталей взаимодействия с каждым устройством ввода-вывода, которое вы когда-либо можете использовать. Для некоторых устройств это может быстро стать огромной разработкой. Это не проблема для встраиваемых систем, но работать на коммерческом оборудовании таким способом не просто и не рекомендуется.
Работая в ОС, вы, вероятно, не получаете (и не должны получать) доступ к реальным аппаратным регистрам и прерываниям. Если вы разрабатываете пользовательское устройство ввода-вывода, лучше всего привести его в соответствие с существующими стандартами, чтобы вам требовалось как можно меньше пользовательского программного обеспечения низкого уровня. Вот почему вы видите множество пользовательских гаджетов, подключающихся через USB и идентифицирующих себя как HID (Human Interface Devices). Как HID, существующие драйверы USB заботятся о физическом уровне, а поставляемый ОС драйвер HID заботится о логическом интерфейсе, обеспечивая очень простой API доступа высокого уровня к приложению.
Одной из ключевых ролей операционной системы является обеспечение согласованного API ввода-вывода для всех устройств. Как правило, это принимает форму функций open()
, close()
, read()
, write()
и ioctl()
(имена могут различаться, но всегда будет существовать некоторая форма по меньшей мере первых четырех). Однако уровень ОС довольно сырой. Как правило, вызов ОС перенаправляется без особой обработки в драйвер устройства, который затем передает данные на устройство. Обычно низкоуровневые вызовы ОС блокируют вызывающую программу до завершения, и часто они имеют ограничения на размеры буферов, которые имеют смысл. Например, необработанный доступ к дисковому устройству обычно требуется для целого числа дисковых блоков одновременно.
И не забывайте о таких вещах, как файловые системы и сетевые протоколы ... все они сделаны намного более надежными и совместимыми благодаря инкапсуляции в операционной системе.
Даже если допустимо вызывать read()
и write()
для отдельных символов, это обычно не самая лучшая возможная производительность. Вызовы операционной системы относительно дороги, и если вы можете прочитать несколько символов за один вызов, ваша производительность может возрасти.
Это источник библиотеки stdio для C и различных других библиотек буферизации в других средах. Библиотека stdio предоставляет уровень буферизации, который изолирует код C от размера блока базового оборудования. Даже в полностью домашней операционной системе, где у вас есть полный контроль над всеми устройствами, что-то вроде C stdio все равно будет ценно.
Написание собственной замены stdio - очень ценное упражнение, даже если вы не используете его в производственном коде, и я рекомендую его всем, кто хочет узнать о том, что на самом деле происходит между printf()
и scanf()
и терминал или файлы.
Одним ценным ресурсом является книга Стандартная библиотека C П. Дж. Плаугера. В нем автор представляет реализацию полной библиотеки времени выполнения C, указанной в стандарте ANSI. Его обсуждение конкретных вариантов реализации, которые он сделал, является ценным и касается контекста этого вопроса, а также интересно узнать, почему были определены некоторые из стандартных функций библиотеки.