Русский
Русский
English
Статистика
Реклама

Перевод Заметки о Unix С-функция main() одно из мест, где видны различия между API пользовательского пространства и ядра Unix

В современных Unix-дистрибутивах часто проводят формальную границу между API, предоставляемыми пользовательскому пространству ядром, и Unix API, которые предоставляет программам стандартная библиотека, под которой подразумевается стандартная библиотека C. Кое-кого, включая меня, это не вполне устраивает (я уже писал на эту тему). Но, независимо от того, что я об этом думаю, в Unix уже давно существует одно место, в котором видна разница между обычным API, которым пользуются все, и API, который реализован в ядре. Я говорю о традиционной точке входа в программы, написанных на языке C, о функции main(), с которой начинается выполнение таких программ.



Все знакомы с простой формой функции main(), в которой используются аргументы argc и argv. Такая функция вызывается с передачей ей количества аргументов и массива строк. При несколько более продвинутом способе работы с этой функцией применяется ещё и третий аргумент envp. Он представляет собой массив переменных окружения. Этот формат существует в Linux очень давно. Версия main() с двумя аргументами существует, как минимум, со времён exec(2) Research Unix V4. А форма этой функции с третьим аргументом, похоже, появилась в exec(2) V7.

Но это, на самом деле, не реальная точка входа в программу, которую ядро Unix V7 использует при запуске программы. Реальная точка входа имеет API, отличный от main(). Обычно C-программы в V7 начинают работу с метки, имеющей символическое имя start. Самая простая версия ассемблерного кода, в котором это используется, представлена в файле crt0.s, и тут, очевидно, выполняется некий объём подготовительной работы. Есть и другие версии подобного кода, их можно найти здесь. Тут выполняется больше вспомогательных операций, например подготовка к профилированию кода.

(В Research Unix V6 тоже был файл crt0.s, но несколько иной. Полагаю, тут, например, нет циклов. Если бы я понимал язык ассемблера PDP-11, то я лучше бы разобрался с тем, что тут, на самом деле, происходит.)

В V7 между API пользовательского пространства для main() и API ядра имеется лишь небольшая разница. В актуальных дистрибутивах Unix там часто происходит очень много всего, особенно тогда, когда пользуются динамическими загрузчиками и чем-то вроде вспомогательного вектора, который имеется в некоторых дистрибутивах. Я подозреваю, что самую простую современную версию этого механизма можно найти в musl libc для Linux, где crt1.c и функции libc для подготовки к работе main() сравнительно просты.

(Некоторый код тут присутствует из-за того, что среда выполнения C нуждается в предварительной настройке (и да, в современном C есть среда выполнения), но определённый объём этого кода предназначен для согласования того, как ядро вызывает программы, с тем, как хочет быть вызвана функция main(). Например, обратите внимание на то, что функция musl libc для запуска main() не вызывается с передачей ей argc в виде явно заданного аргумента. Она извлекает argc из памяти.)

Примечание: V7 и адрес данных 0


В конце каждой версии файла crt0.s V7 есть код, который поначалу меня озадачил:

.data.=.+2  / loc 0 for I/D; null ptr points here.

Оказалось, что он резервирует два байта в начале раздела данных. Unix V7 работает на компьютерах PDP-11, которые поддерживают разделение адресного пространства инструкций и данных. В результате раздел данных начинается с адреса (данных) 0. Резервирование двух байтов в начале адресного пространства позволяет обеспечить то, что ни переменную, ни что-то другое в разделе данных нельзя расположить по адресу 0. В результате NULL в C всегда отличается от действительных указателей.

Приходилось ли вам сталкиваться с различиями API пользовательского пространства и ядра Unix?

Источник: habr.com
К списку статей
Опубликовано: 03.03.2021 12:06:10
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Блог компании ruvds.com

Настройка linux

Системное администрирование

Unix

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru