Разработка ядра Linux | страница 86
>/*
>* sys_foo - всеми любимый системный вызов.
>*
>* Возвращает размер стека ядра процесса
>*/
>asmlinkage long sys_foo(void) {
> return THREAD_SIZE;
>}
Это все! Загрузите новое ядро. Теперь из пространства пользователя можно вызвать системную функцию >foo()
.
Доступ к системным вызовам из пространства пользователя
В большинстве случаев системные вызовы поддерживаются библиотекой функций языка С. Пользовательские приложения могут получать прототипы функций из стандартных заголовочных файлов и компоновать программы с библиотекой С для использования вашего системного вызова (или библиотечной функции, которая вызывает ваш системный вызов). Однако если вы только что написали системный вызов, то маловероятно, что библиотека >glibc
уже его поддерживает!
К счастью, ОС Linux предоставляет набор макросов-оболочек для доступа к системным вызовам. Они позволяют установить содержимое регистров и выполнить машинную инструкцию >int $0x80
. Эти макросы имеют имя >syscalln()
, где >n
— число от нуля до шести. Это число соответствует числу параметров, которые должны передаваться в системный вызов, так как макросу необходима информация о том, сколько ожидается параметров, и соответственно, нужно записать эти параметры в регистры процессора. Например, рассмотрим системный вызов >open()
, который определен следующим образом.
>long open(const char *filename, int flags, int mode)
Макрос для вызова этой системной функции будет выглядеть так.
>#define NR_open 5
>_syscall3(long, NR_open, const char*, filename, int, flags, int, mode);
После этого приложение может просто вызывать функцию >open()
.
Каждый макрос принимает >2 + 2*n
параметров. Первый параметр соответствует типу возвращаемого значения системного вызова. Второй параметр — имя системного вызова. После этого следуют тип и имя каждого параметра в том же порядке, что и у системного вызова. Постоянная >NR_open
, которая определена в файле >
, — это номер системного вызова. В функцию на языке программирования С такой вызов превращается с помощью вставок на языке ассемблера, которые выполняют рассмотренные в предыдущем разделе шаги. Значения аргументов помещаются в соответствующие регистры, и выполняется программное прерывание, которое перехватывается в режиме ядра. Вставка данного макроса в приложение — это все, что необходимо для выполнения системного вызова >open()
.
Напишем макрос, который позволяет вызвать нашу замечательную системную функцию, и соответствующий код, который позволяет этот вызов протестировать.