Внутреннее устройство ядра Linux 2.4


   зно 2020        

Подсчет значения BogoMips для данного


  • kmem_cache_init(), начало инициализации менеджера памяти.


  • Разрешаются прерывания.


  • Подсчет значения BogoMips для данного CPU.


  • Вызывается mem_init() которая подсчитывает max_mapnr, totalram_pages и high_memory и выводит строку "Memory: ...".


  • kmem_cache_sizes_init(), завершение инициализации менеджера памяти.


  • Инициализация структур данных для procfs.


  • fork_init(), создает uid_cache, инициализируется max_threads исходя из объема доступной памяти и конфигурируется RLIMIT_NPROC для init_task как max_threads/2.


  • Создаются различные кэши для VFS, VM, кэш буфера и пр..


  • Инициализируется подсистема IPC, если имеется поддержка System V IPC. Обратите внимание, что для System V shm, это включает монтирование внутреннего (in-kernel) экземпляра файловой системы shmfs.


  • Создается и инициализируется специальный кэш, если поддержка квот (quota) включена.


  • Выполняется платформо-зависимая "проверка ошибок" ("check for bugs") и, если это возможно, активируется обработка ошибок процессора/шины/проч. Сравнение различных архитектур показывает, что "ia64 не имеет ошибок" а "ia32 имеет несколько дефектов", хороший пример - "дефект f00f" который проверен только для ядра, собранного под процессор ниже, чем 686.


  • Устанавливается флаг, указывающий на то, что планировщик должен быть вызван "при первой возможности" и создается поток ядра init(), который выполняет execute_command, если она имеется среди параметров командной строки в виде "init=", или пытается запустить /sbin/init, /etc/init, /bin/init, /bin/sh в указанном порядке; если не удается ни один из запусков то ядро "впадает в панику" с "предложением" задать параметр "init=".


  • Переход в фоновый поток с pid=0.


  • Здесь важно обратить внимание на то, что задача init() вызывает функцию do_basic_setup(), которая в свою очередь вызывает do_initcalls() для поочередного (в цикле) вызова функций, зарегистрированных макросом __initcall или module_init() Эти функции либо являются независимыми друг от друга, либо их взаимозависимость должна быть учтена при задании порядка связывания в Makefile - ах. Это означает, что порядок вызова функций инициализации зависит от положения каталогов в дереве и структуры Makefile - ов. Иногда порядок вызова функций инициализации очень важен. Представим себе две подсистемы: А и Б, причем Б существенным образом зависит от того как была проинициализирована подсистема А. Если А скомпилирована как статическая часть ядра, а Б как подгружаемый модуль, то вызов функции инициализации подсистемы Б будет гарантированно произведен после инициализации подсистемы А. Если А - модуль, то и Б так же должна быть модулем, тогда проблем не будет. Но что произойдет, если и А, и Б скомпилировать с ядром статически? Порядок, в котором они будут вызываться (иницализироваться) зависит от смещения относительно точки .initcall.init ELF секции в образе ядра (грубо говоря - от порядка вызова макроса __initcall или module_init() прим. перев.). Rogier Wolff предложил ввести понятие "приоритетной" инфраструктуры, посредством которой модули могли бы задавать компоновщику порядок связывания, но пока отсутствуют заплаты, которые реализовали бы это качество достаточно изящным способом, чтобы быть включенным в ядро. А посему необходимо следить за порядком компоновки. Если А и Б (см. пример выше) скомпилированы статически и работают корректно, то и при каждой последующей пересборке ядра они будут работать, если порядок следования их в Makefile не изменяется. Если же они не функционируют, то стоит изменить порядок следования объектных файлов.

    Еще одна замечательная особенность Linux - это возможность запуска "альтернативной программы инициализации", если ядру передается командная строка "init=". Эта особенность может применяться для перекрытия /sbin/init или для отладки скриптов инициализации (rc) и /etc/inittab

    вручную, запуская их по одному за раз


    Содержание  Назад  Вперед