Прототип ядра и модулей - PullRequest
2 голосов
/ 01 июля 2011

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

Слово modules немного двусмысленно, правильный термин будет просто для загрузки библиотек, таких какминиатюрная реализация библиотеки C для режима ядра драйверов или стандартных вещей, таких как PIT и клавиатура , которые находятся на IRQ 0& 1 .Метод, которого я пытаюсь достичь, немного самодостаточен;в том аспекте, что модули, которые будет загружать мое ядро, будут использоваться в самом ядре для перехода в режим пользователя .

В качестве примера, мое ядро ​​использует очень мало функций из библиотеки C, который я реализовал сам.Эти функции сами используются при настройке моих GDT, IDT, IRQ, ISR и т. Д. И т. Д. Я хотел бы абстрагировать эти функции в библиотеку, которую ядро ​​может загружать и использовать.Это означает, что само ядро ​​потребует загрузки модуля на самом первом этапе, прежде чем что-либо будет установлено.

Теперь я подумал о нескольких способах сделать это сам, таких как добавление структуры в эту библиотеку с помощьютаблица указателей функций, которым присваивается адрес функций в самой библиотеке.Компилируем библиотеку как файл aout-kludge , загружаем библиотеку в ядро ​​как void * (что нормально, так как у меня есть рабочий распределитель), а затем вычисляем смещениеструктуры, заходя в void указатель, и воссоздавая структуру в ядре.Это не похоже на работу, так как необходимо назначить таблицу указателей функций, что означает, что в самой библиотеке должна быть функция инициализации.Как это будет называться, даже если бы я знал адрес?

Я не знаю, как мне реализовать такой загрузчик, и стоит ли оно того?Я хочу абстрагироваться, насколько это возможно, мое ядро ​​имеет модульную конструкцию.Я также рассчитываю загрузить драйверы и другие вещи с помощью этого метода, я просто не уверен, как бы это реализовать.Я уже пробовал различные методы, и все они потерпели неудачу.Что мне делать?

Ответы [ 2 ]

2 голосов
/ 01 июля 2011

Я бы рекомендовал вам сначала написать динамический загрузчик в пространстве пользователя.Необходимые методы очень похожи, и вы сможете позже адаптировать большую часть кода к пространству ядра.Кроме того, не используйте a.out и не создавайте свою собственную «таблицу указателей функций» - используйте более современный формат, такой как ELF .Инструменты времени компиляции уже существуют, так что это сэкономит вам много усилий;Вы можете просто написать соответствующий скрипт компоновщика и собрать прямо из Linux GCC.

Как это происходит, ядро ​​Windows делает нечто очень похожее на то, что вы говорите - ядро ​​Windows (ntoskrnl.exe) является исполняемым файлом PEсвязывание файлов в подпрограммах из различных библиотек DLL (PSHED.dll, HAL.dll, KDCOM.dll, CLFS.sys и Cl.dll в моей системе).В этом случае программа NTLDR загружает все файлы, необходимые для ntoskrnl.exe, в память, а загрузочная заглушка в ntoskrnl.exe выполняет динамическое связывание.Позже этот же динамический компоновщик можно использовать и для загрузки других драйверов.

0 голосов
/ 24 октября 2017

Реализация модулей ядра не является тривиальной задачей. Это немного сложно, и вам нужно будет прочитать документацию ELF для кодирования. Я постараюсь дать вам некоторое представление здесь -

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

CHAR VariableName[20];

Например, в приведенном выше коде будет создан символ данных с именем «VariableName». После «изобретения» динамических / совместно используемых библиотек необходимо загрузить таблицу символов (набор символов в двоичном формате), чтобы разрешить ссылки из исполняемого файла в библиотеках. Но в таблице символов содержится много отладочных символов и ненужных символов.

Symbol: Main.c

Например, в таблице символов даже символ исходного файла C будет присутствовать для отладки. Но это не требуется для разрешения ссылок во время выполнения. Здесь в игру вступает понятие динамических символов.

Динамическое связывание относится к разрешению ссылок между двоичными файлами. Динамический компоновщик будет использовать динамическую таблицу символов (которая должна быть загружена и «обычная» таблица символов не должна) для разрешения ссылок, которые исполняемый файл делает в библиотеке.

Теперь в ядре ядра, которое является исполняемым файлом, нет ссылок на общие библиотеки (модули ядра). Но общие библиотеки ссылаются на исполняемый файл. Таким образом, исполняемый файл должен содержать динамические символы для разрешения ссылок в модулях ядра. Это противоречит случаю в пространстве пользователя. Таким образом, если вы используете ld,

-pie -T LinkerScript.ld
Опция

должна использоваться для создания динамической таблицы символов в исполняемом файле ядра.

И вам следует создать файл LinkerScript.ld -

/* File: LinkerScript.ld */
PHDRS {
  kernel PT_LOAD FILEHDR;/* This declares a segment in which your code/data is.*/
  dynamic PT_DYNAMIC;/* Segment containing the dynamic table (not DST). */
}

SECTIONS {
    /* text, data, bss sections must be implemented already */
    .dynamic ALIGN(0x1000) : AT(ADDR(.dynamic) - KERNEL_OFFSET)
    { 
       *(.dynamic) 
    } :dynamic/* add :kernel to text, data, bss*/
}

с вышеуказанной структурой. Убедитесь, что ваши разделы .text, .data & .bss уже присутствуют и: ядро ​​добавлено в конец дескриптора раздела.

Для получения дополнительной информации прочитайте документацию ELF и руководство по LD (для понимания сценария компоновщика).

...