Есть ли в ядре функция main ()? [закрыто]


52

Я изучаю драйверы устройств и программирование ядра. Согласно книге Джонатана Корбета, main()в драйверах устройств нет функции.

Итак, у меня два вопроса:

  • Почему нам не нужна main()функция в драйверах устройств?
  • Есть ли у самого ядра main()функция?

Может кто-то объяснить это мне?


1
Также этот же пользователь спрашивает здесь: stackoverflow.com/q/18266063/827263
Кейт Томпсон

@KeithThompson ... Да ... Просто потому, что я не получил ответ, что я хочу, поэтому я спросил это здесь.
кто-то

@Shadur ... в любом случае, сейчас оно закрывается ... И у меня нет привилегий перенести это ...
кто-то

Это должно было быть закрыто с другой стороны, у этого есть намного больше представлений :-)
Сиро Сантилли 新疆 改造 中心 法轮功 六四 事件

Ответы:


82

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

Тем не менее, эквивалент main()в коде ядра есть start_kernel(), который вызывается загрузчиком после загрузки образа ядра, распаковывает его в память и настраивает необходимое оборудование и пейджинг памяти. start_kernel()выполняет большую часть настройки системы и в конечном итоге порождает процесс инициализации.

Точка входа в модули ядра Linux - это функция init, которая регистрируется в ядре путем вызова module_init()макроса. Зарегистрированная функция инициализации модуля затем вызывается кодом ядра через do_initcalls()функцию во время запуска ядра.


11
Спасибо за признание истинной цели mainметода в C. (Это слишком распространенное заблуждение, что операционная система делает прямой вызов main, что не соответствует действительности , а в меньшей степени, например, в C ++.) I ' Я бы дал тебе еще один голос, если бы мог.
CVn

1
@ Томас ... Спасибо за этот отличный ответ ....
кто-то

17

Ядро не имеет mainфункции. mainэто концепция языка C. Ядро написано на С и сборке. Код входа в ядро ​​написан сборкой.

Последовательность загрузки организована следующим образом:

  1. BIOS обычно загружает загрузчик с блочного загрузочного устройства. Популярным загрузчиком сейчас является grub.
  2. Grub загружает ядро в ОЗУ возможно с начальным корневым устройством ( initrd). Затем выполняется код по какому-либо адресу.
  3. Образ ядра содержит несколько модулей ядра, например: модули файловой системы, драйверы устройств. Образ ядра использует модуль файловой системы для монтирования корневой файловой системы. Теперь ядро ​​может загружать и запускать все модули ядра с диска.
  4. Ядро выполняет задачи инициализации. Например: пройти через шину PCI и найти все устройства PCI, инициализировать все драйверы устройств.
  5. Наконец, ядро ​​создает процесс 0 и процесс 1 ( initпроцесс), переключает контекст ЦП с кольца 0 на кольцо 3 и запускает процесс инициализации (идентификатор процесса равен 1). Теперь загрузка ядра завершена!
  6. initПрограмма запускает все сценарии инициализации. Все сервисы запущены. Оболочка называется. Пользователи могут войти.

mainФункция является функцией С. На самом деле основной метод не является точкой входа программ на Си. Среда выполнения C вызывает много функций раньше main. GCC имеет расширенную функцию: конструкторы. Функции, объявленные как «конструктор», вызываются раньше main.

Например:

/* This should not be used directly. Use block_init etc. instead. */ 
#define module_init(function, type) \
    static void _attribute__((constructor)) do_qemu_init ## function(void) { \
    register_module_init(function, type); \
} 

Этот макрос из проекта qemu.


Основной метод - это метод ac. Фактически основной метод - это не запись программы c. Среда выполнения C вызвала много методов перед основным методом.
Эдвард Шен

ну, bios обычно загружает загрузчик, и этот загрузчик загружает образ ядра (и, возможно, initrd). Код ядра находится в образе ядра, а не initrd
Стефан Шазелас

GCC имеет расширенную функцию: конструктор. Объявление метода "конструктор" вызывается перед основным методом. Например: / * Это не должно использоваться напрямую. Вместо этого используйте block_init и т. Д. * / #define module_init (функция, тип) \ static void _attribute __ ((конструктор)) do_qemu_init ## function (void) {\ register_module_init (функция, тип); \}
Эдвард Шен

1
initrd.img НЕ является образом ядра. Это набор модулей, загружаемых ядром при загрузке. Изображения ядра обычно имеют имена, начинающиеся с «vmlinuz», но отличаются от дистрибутива к дистрибутиву.
Златовласка

3
Этот ответ переполнен словами «все - это ПК / Linux / i86», и он загружается именно так, а ядро ​​именно так… Почему все думают, что это единственный возможный путь в мире?
Дженс

9

Например, в файле arch / x86 / boot / main.c есть функция main () для подготовки системы к переходу из реального в защищенный режим, но в других архитектурах такого кода нет. Есть хороший обзор, как работает загрузка ядра Linux 2.6.x на платформе x86. Это действительно стоит прочитать.

Согласно документу HOWTO по разработке ядра Linux, ядро ​​Linux

автономная среда C, не зависящая от стандартной библиотеки C, поэтому некоторые части стандарта C не поддерживаются.

что в соответствии со стандартом C, кстати, означает, что

Это определяется реализацией, требуется ли программе в автономной среде для определения «основной» функции.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.