5.3. Как Linux устанавливает вектора системных вызовов
Код startup_32 находящийся в /usr/src/linux/boot/head.S начинает всю работу запуская setup_idt(). Подпрограмма устанавливает IDT (таблицу описания прерываний) с 256 записями. Никаких отправных точек прерываний этой программой не загружается, и делается это лишь после разрешения пейджинга и перехода ядра по адресу 0xC0000000. В IDT находится 256 записей по 4 байта каждая, всего 1024 байта.
Когда вызывается start_kernel() (/usr/src/linux/init/main.c) она запускает trap_init() (описае в /usr/src/linux/kernel/traps.c). trap_init() устанавливает таблицу дескрипторов прерываний как показано на рис 4.3
0 - divide_error (ошибка деления)
1 - debug (отладка)
2 - nmi (немаскируемое прерывание)
3 - int3
4 - overflow (переполнение)
5 - bounds (достижение границ)
6 - invalid_op (неверный процесс)
7 - device_not_avaible (обращение к устройству невозможно)
8 - double_fault (двойная ошибка)
9 - coprocessor_segment_overrun (перезапуск сегмента сопроцкссора)
10 - invalid TTS (неверная TTS)
11 - segment_not_present (отсутствие сегмента)
12 - stack_segment (стековый сегмент)
13 - general_protection (общая защита)
14 - page_fault (ошибка чтения страницы)
15 - не используется
16 - coprocessor_error(ошибка сопроцессора)
17 - alignment_check(проверка расстановки)
18-48- не используются
На этот момент вектор прерывания системных вызовов не установлен. Он инициализируется sched_init() (находится в /usr/src/linux/kernel/sched.c). Вызов set_system_gate (0x80,&system_call) устанавливает прерывание 0x80 как вектор параметра system_call().
5.4. Как установить свой собственный системный вызов
Создайте каталог в /usr/src/linux/ для вашего кода.
Поместите нужные вам библиотеки в /usr/include/sys/ и /usr/include/linux/
Поместите ваш отлинкованный модуль в ARCHIVES и подкаталог в строки SUBDIRS высокого уровня создания файла. См fs/Makefile - fs.o.
Поместите #define __NR_xx в unistd.h для присвоения номера вашему системному запросу, где xx - индекс описания вашего вызова. Она будет использована для установки вектора с помощью sys_call_table вызываемого ваш код.
Введите отправную точку для вашего системного запроса в sys_call_table в sys.h. Она будет зависеть от индекса xx в предыдущем пункте. Переменная NR_syscalls будет пересчитана автоматически.
Измените какой-нибудь код ядра в /fs/mm/ для установки инсрументов нужных вашему вызову.
Запустите процесс компановки на высшем уровне для создания вашего кода в ядре
После этого вам останется лишь занести системный вызов в ваши библиотеки, или использовать макрос _syscalln() в программе использующей ваши разработки, для разрешения им доступа к новому системному вызову.
В библиографии содержаться несколько полезных ссылок на книги охватывающие эту тему. В частности полезно будет просмотреть "The 386DX Microprocessor Programmer's Reference Manual" и "Advanced 80386 Programming Techniques" Джеймса Турли.
[ Назад | Оглавление | Далее ]
|