Ядро ОС Linux

       

Как Linux использует пpеpывания и исключения.


В Linux, запуск системного запpоса вызывается маскиpуемым пpеpыванием, или-же пеpедачей класса исключения, обусловленной инстpукцией int 0x80. Мы используем вектоp 0x80 для пеpедачи контpоля ядpу. Этот вектоp устанавливается во вpем инициализации, сpеди дpугих важнейших вектоpов таких, как вектоp таймеpа.

В веpсии Linux 0.99.2 пpисутствует 116 системных вызовов. Документацию по ним можно найти непосpедственно в самой документации по Linux. Во вpемя обpащения пользователя к системному вызову, пpоисходит следующее:

- Каждый вызов определяется в libc. Каждый вызов внутри библиотеки libc в общем-то представляет собой макрос syscallX, где X - число параметров текущей подпрограммы. Некоторые системные вызовы являются более общими, нежели другие из-за изменяющегося по длине списка аргументов, но два эти типа ничем концептуально не отличаются друг от друга - разве что количеством параметров. Примерами общих системных вызовов могут служить вызовы open() и ioctl().

- Каждый макрос вызова поддерживается ассемблерной подпрограммой, устанавливаемой границы стека вызовов и запускаемой вызов _system_call() через прерывание, пользуясь инструкциями $0x80. К примеру вызов setuid представлен как:

_syscall1(int,setuid,uid_t,uid); Что расширяется в : _setuid subl $4,%exp pushl %ebx movzwl 12(%esp),%eax movl %eax,4(%esp) movl $23,%eax movl 4(%esp),%ebx int $0x80 movl %eax,%edx test1 %edx,%edx jge L2 negl %edx movl %edx,_errno movl $-1,%eax popl %ebx addl $4,%esp ret L2: movl %edx,eax popl %ebx addl $4,esp ret

Определение макросов для syscallX() вы можете найти в /usr/include/linux/unistd.h а библиотека системных вызовов пользовательского пространства находится в /usr/src/libc/syscall

- С этой точки зрения системный код вызова не запущен. Он не запускается до запуска int $0x80 осуществляющего переход на ядровую _system_call(). Эта процедура общая для всех системных вызовов. Она обладает возможностью сохранения регистров, проверки на правильность запускаемого кода и затем передачи контроля текущему системному вызову со смещениями в таблице _sys_call_table. Она также может вызвать _ret_from_sys_call(), когда системный вызов завершается, но еще не осуществлен процесс перехода в прстранство пользователя.

Фактический код компонентов sys_call находится в /usr/src/linux/kernel/sys_call.s. Фактический код множества системных вызовов может быть найден в /usr/src/linux/kernel/sys.c. Остальную часть ищите сами.

- После запуска системного вызова, макрос syscallX() проверяет его на отрицательное возвращаемое значение, и если подобное случается он помещает код ошибки в глобальную переменную _errno, так чтобы он был доступен функции типа perror().



Содержание раздела