Книга: Разработка ядра Linux
Доступ к системным вызовам из пространства пользователя
Доступ к системным вызовам из пространства пользователя
В большинстве случаев системные вызовы поддерживаются библиотекой функций языка С. Пользовательские приложения могут получать прототипы функций из стандартных заголовочных файлов и компоновать программы с библиотекой С для использования вашего системного вызова (или библиотечной функции, которая вызывает ваш системный вызов). Однако если вы только что написали системный вызов, то маловероятно, что библиотека 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
, которая определена в файле <asm/unistd.h>
, — это номер системного вызова. В функцию на языке программирования С такой вызов превращается с помощью вставок на языке ассемблера, которые выполняют рассмотренные в предыдущем разделе шаги. Значения аргументов помещаются в соответствующие регистры, и выполняется программное прерывание, которое перехватывается в режиме ядра. Вставка данного макроса в приложение — это все, что необходимо для выполнения системного вызова open()
.
Напишем макрос, который позволяет вызвать нашу замечательную системную функцию, и соответствующий код, который позволяет этот вызов протестировать.
#define __NR_foo 283
__syscall0()(long, foo)
int main() {
long stack_size;
stack_size = foo();
printf("Размер стека ядра равен %ldn" , stack_size);
return 0;
}
- Пространства имён
- Листинг 10.1. (simpleid.c) Отображение идентификаторов пользователя и группы
- Сохранение информации о пользователях при миграции
- Что делать, если при установке принтера появляется сообщение Невозможно завершение операции. Подсистема печати недоступн...
- Реальный (RID) и эффективный (EUID) идентификаторы пользователя
- 12. Лекция: Создание приложений с графическим интерфейсом пользователя.
- 9.4. Права доступа к squid
- Создание пользователя и группы на рабочей станции
- Глава 29 Доступ к канальному уровню
- 10.5. Транзакции и пути доступа меню
- Настройка доступа пользователей к рабочей книге
- 1.1 Режимы ядра и пользователя Windows