Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
avmis.docx
Скачиваний:
1
Добавлен:
27.12.2019
Размер:
428.29 Кб
Скачать

67) Linux: системные вызовы.

Рассмотрим такую полезную вещь, как системные вызовы в ОС Linux. Фактически это интерфейс, который предоставляет ОС (ядро) для осуществления различных высокоуровневых действий: программа делает вызов, например "создать папку" или "перезагрузить компьютер", а ядро заботится о том, как конкретно это сделать (или НЕ сделать, если у программы недостаточно прав).

Всего вызовов насчитывается около 280. Все они имеют номера, которые перечислены в файле unistd.h (его местоположение отличается на разных системах, скорее всего это /usr/include/asm-[x86|x86_64|...]/unistd.h). Кроме того, в динамической библиотеке libc.so.6 имеются обвертки для всех этих вызовов.

В стандарт CL не входит какого-либо способа сделать системный вызов, или вызвать функцию из бинарной библиотеки. Однако, до библиотечных функций в .so можно добраться с помощью FFI. Так что мы могли бы обращатся к libc.so за каждым отдельным вызовом - а их около 300 штук. Вместо этого мы поступим иначе - воспользуемся функцией syscall из libc.so - она делает системный вызов, который делает системные вызовы :) Например - создать папку можно с помощью функции mkdir: mkdir("new path", 0777);

А можно так: syscall(83, "new path", 0777); // где 83 - это номер системного вызова, который создает папку.

У второго варианта есть преимущество - с помощью него можно сделать вызов, только появившийся в ядре, но не описанный в отдельную функцию. Характер возвращаемого значения разный для разных системных вызовов - для одних это просто флаг вышло/не вышло (ноль/не ноль), а для других какое-то значение, имеющее смысл - например дескриптор файла или устройства.

Среди системных вызовов есть как простые, так и достаточно интересные и функциональные. Например fork, для создания точной копии текущего процесса, или exec для запуска программы на исполнение, есть даже system для обрашения к shell-у.

Таким образом, три кита на которых основывается Linux, то есть системные вызовы, библиотечные функции и обособленные программы, каждая из которых выполняет свою роль - всё это доступно в Common Lisp, причём без особого труда.

68) Linux: методы выполнения системных вызовов.

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

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

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

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

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]