Подтвердить что ты не робот

Почему дескрипторы файлов UNIX не реализованы по своему типу, особенно на С++?

В последнее время я использую большое количество файловых дескрипторов, и мне было интересно, почему они реализованы как целые числа?

Это означает, что их легко путать для других целых чисел, и нет никакого способа узнать, без контекста, что они собой представляют, что они указывают, открыты ли они и т.д.

В C, FILE - непрозрачный тип struct. Многие люди также typedef, например. status_t как целое число, поэтому их функция очевидна. Кажется, лучше всего либо реализовать их как непрозрачный тип, либо (например, на С++) в качестве класса, который может позаботиться о некоторой реализации, а также очистить бит namespace (вызов pipe() или open() кажется настолько безобидным, и это не очевидно, что вы прокладываете или открываете без контекста). Как, например, std::file_descriptor, с конструкторами /factory функции для создания труб или открытия файлов и т.д.

Я надеюсь, что это будет тема для этого сайта; Я попытался сформулировать это как "Почему было принято это конкретное решение?" Если кто-нибудь знает где-нибудь, это будет лучше, пожалуйста, дайте мне знать.

4b9b3361

Ответ 1

Ваш вопрос можно разделить на две части:

Почему дескриптор файла POSIX int?

Как и большинство уже существующих инструментов и библиотек, ответ, вероятно, имеет исторические причины. Ответ Джеймса указывает на это.

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

С другой стороны, такая вещь, как typedef int file_descriptor;, не устранит ни одну из проблем, о которых вы говорили выше:

Это означает, что их легко путать для других целых чисел...

Если вы путаете переменные, у меня плохие новости для вас. Компилятор вам не поможет, так как file_descriptor и int являются одним и тем же типом, поэтому любая операция на одном разрешена на другом.

... и нет никакого способа узнать, без контекста, что это такое, что они указывают, открыты ли они и т.д.

Вы не можете сделать это с помощью FILE. Вот почему у вас есть функции, которые запрашивают запрашиваемую информацию и возвращают ее, как и с помощью FILE. typedef тип не даст вам дополнительной информации.

Почему POSIX не поддерживает С++-оболочку?

Короче говоря, потому что, кроме Microsoft, разработчик операционной системы не любит С++. Windows едва ли даже POSIX, поэтому нет никакой надежды для Microsoft в попытке улучшить что-либо POSIX. Другие операционные системы, совместимые с POSIX, имеют C API как фактический язык системного программирования (отчасти потому, что nm говорит, почти все языки могут связываться с C).

Фактически, С++ популярен среди разработчиков приложений, но не так много среди системных программистов. Комитет POSIX, похоже, не особенно заинтересован в С++. Вот почему вы увидите C и только C решения и аргументы в отношении POSIX API. Также обратите внимание, что POSIX был создан для стандартизации интерфейса UNIX в частности, который был написан на C и одним из его наиболее важных потомков, Linux, также сильно связанный с C.

Ответ 2

История, если ничего другого. Еще в 1970-х годах, вероятно, не представлялось проблемой просто использовать int (и значение было, фактически, индекс в таблицу фиксированного размера). Позже, изменив его к другому типу был бы сломан код.

Ответ 3

Интерфейс Unix описан в терминах языка C, но не менее важно, что в системах есть ABI, а не только API.

Необычные структуры данных, специфичные для языка программирования, усложняют ABI. На уровне ABI у вас есть только типы данных низкого уровня, такие как "32-разрядное целое без знака" и простые агрегаты.

Как говорится, интерфейс Unix использует такие типы, как pid_t и whatnot, так почему бы не один из этих typedef для дескрипторов файлов?

Дескрипторы файлов имеют некоторые известные значения, и когда открыт новый дескриптор файла, всегда используется наименьшее положительное значение, которое доступно. Значения дескриптора файла эффективно действуют как индексы массива в таблицу дескрипторов, и дизайн преднамеренно подобен. Модель программистов файловых дескрипторов состоит в том, что в ядре есть массивная структура. Функция dup2 может фактически дублировать дескриптор файла из одного слота в другой. Такие индексы массива также могут быть int, с отрицательным значением для ошибок сигнализации.

C typedefs не покупают дополнительную проверку типов, но они привносят немного читаемости и абстракции: независимость от определенного целочисленного типа. Тип fd_t может быть int для одной системы и a long для другого. Но так как int выросло почти повсеместно 32 бита шириной несколько десятилетий назад, нет никакой реальной необходимости отвлечь его ради того, чтобы сделать его более широким под тем же именем. Очень необычно, что для программы требуется более двух миллиардов открытых файловых дескрипторов.

В отличие от этого, было бы очень неудобно для разработчиков, если вместо pthread_t использовался простой int.

int дескрипторы оказались трудно усвоить для разработчиков API Socket Windows, которые изобрели SOCKET typedef, значения которых не являются наименьшими доступными положительными целыми числами; только одна из причуд, приводящих к неприятностям переносимости. Тем не менее, существует реальная семантическая разница в этом коде, который опирается на эти дескрипторы, являющиеся малыми значениями в диапазоне, либо не работает, либо ведет себя неэффективно.

Существуют исторические экземпляры Unix, которые были пересмотрены, чтобы заменить простой тип int на некоторый typedef. Например, в функции accept размер удаленной структуры адреса был просто int. Затем он стал socklen_t. Для socklen_t не существует технической необходимости; он был изобретен как решение для групповой поддержки, чтобы преодолеть различия между системами, которые использовали традиционные int и те, чьи сторонники усердно изменили аргумент использования size_t. Хотя эти два типа привели к одному и тому же ABI, проблем не было, до тех пор, пока системы с 64-разрядными size_t и 32 бит int.