Я знаю, что интерфейс системных вызовов реализован на низком уровне и, следовательно, зависит от архитектуры / платформы, а не от «общего» кода.
Тем не менее, я не могу ясно увидеть причину, по которой системные вызовы в 32-битных ядрах Linux x86 имеют числа, которые не сохраняются одинаковыми в аналогичной архитектуре Linux 64-битной x86_64? Какова мотивация / причина этого решения?
Мое первое предположение состояло в том, что основной причиной было сохранение 32-разрядных приложений в системе x86_64, чтобы через разумное смещение номера системного вызова система знала, что пространство пользователя является 32-разрядным или 64-разрядным. соответственно. Это, однако, не тот случай. По крайней мере, мне кажется, что read (), являющийся системным вызовом номер 0 в x86_64, не может быть согласован с этой мыслью.
Другое предположение состояло в том, что изменение номеров системных вызовов может иметь безопасность / усиление фона, что я не смог подтвердить сам.
Будучи неосведомленным о проблемах реализации зависящих от архитектуры частей кода, я все еще задаюсь вопросом, как изменить номера системных вызовов , когда кажется, что в этом нет необходимости (поскольку даже 16-разрядный регистр будет хранить значительно больше, чем в настоящее время ~ 346 чисел, чтобы представлять все вызовы), поможет достичь чего угодно, кроме нарушения совместимости (хотя использование системных вызовов через библиотеку libc смягчает ее).
источник
Ответы:
Что касается обоснования конкретной нумерации, которая не соответствует какой-либо другой архитектуре [кроме «x32», которая на самом деле является просто частью архитектуры x86_64]: в самые первые дни поддержки x86_64 в ядре linux, до того, как появились Из-за серьезных ограничений обратной совместимости все системные вызовы были перенумерованы, чтобы оптимизировать их на уровне использования кеш-линии .
Я не знаю достаточно о разработке ядра, чтобы знать конкретную основу для этих выборов, но, очевидно, есть некоторая логика выбора перенумеровать все с этими конкретными числами, а не просто копировать список из существующей архитектуры и удалять неиспользуемые. Похоже, что порядок может быть основан на том, как часто они называются - например, чтение / запись / открытие / закрытие. Выход и ответвление могут показаться «фундаментальными», но каждый из них вызывается только один раз за процесс.
Также может происходить что-то, что хранит системные вызовы, которые обычно используются вместе, в одной строке кэша (эти значения являются просто целыми числами, но в ядре есть таблица с указателями на функции для каждого, поэтому каждая группа из 8 системных вызовов занимает 64-байтовая строка кэша для этой таблицы)
источник
fork may seem "fundamental", but [...] called only once per process.
А что? Я понимаю, что вы можете ожидать вызова exit один раз, но вы можетеfork()
fork
что он учитывается дочерним процессом (то есть рассматриваете его как вызов создания процесса), а не родительским процессом, тогда предложение Random832 является правильным.Посмотрите ответ на вопрос «Почему номера системных вызовов отличаются в amd64 linux?» Переполнение стека.
Подводя итог: ради совместимости список системных вызовов стабилен и может только расти. Когда появилась архитектура x86 64, ABI (передача аргументов, возвращаемое значение) стал другим, поэтому разработчики ядра воспользовались возможностью внести изменения, которые давно ожидались.
источник
Короче говоря, потому что кто-то думал, что «совершенно
N+1
несовместимые способы сделать это лучше, чемN
способы». Для исторических арок номера системных вызовов обычно выбирались так, чтобы они соответствовали некоторому устаревшему проприетарному Unix. Но для x86_64 разработчики ядра могли сами выбирать любую нумерацию. Вместо того, чтобы сделать простой выбор и повторно использовать существующую нумерацию, они решили изобрести новый стандарт. Затем они сделали это снова для aarch64 и множества других. Это часто повторяемая модель в разработке ядра Linux.источник