Исторически интерфейс устройств был статическим и простым. Устройства определялись при загрузке системы и впоследствии не изменялись. Типичный дисковый драйвер мог быть написан с использованием нескольких сотен строк кода. По мере развития системы сложность систем ввода/вывода возросла с добавлением новых возможностей. Устройства могли появляться, а затем исчезать при работе системы. С возрастанием сложности и разнообразия шин ввода/вывода маршрутизация запросов ввода/вывода стала сложной.
У аппаратных устройств есть имена файлов, и пользователь может получить к ним доступ с помощью тех же системных вызовов, которые используются для обычных файлов. Ядро может отличить специальный файл устройства или специальный файл, и оно может определить, на какое устройство он ссылается, но большинству процессов не нужно это различие. Доступ к терминалам, принтерам и устройствам с магнитной лентой осуществляется так, как если бы все они были потоками байтов, подобно дисковым файлам FreeBSD.