Linux - статьи


              

в ядре, называется system_call. Процедура,


Точка перехода, в ядре, называется system_call. Процедура, которая там находится, проверяет номер системного вызова, который сообщает ядру -- какую именно услугу запрашивает процесс. Затем, она просматривает таблицу системных вызовов (sys_call_table), отыскивает адрес функции ядра, которую следует вызвать, после чего вызывается нужная функция. По окончании работы системного вызова, выполняется ряд дополнительных проверок и лишь после этого управление возвращается вызывающему процессу (или другому процессу, если вызывающий процесс исчерпал свой квант времени). Код, выполняющий все вышеперечисленные действия, вы найдете в файле arch/<architecture>/kernel/entry.S, после строки ENTRY(system_call).
Итак, если вас одолевает желание изменить поведение некоторого системного вызова, то первое, что необходимо сделать -- это написать вашу собственную функцию, которая выполняла бы требуемые действия (обычно, после выполнения своих действий, в подобных случаях, вызывается первоначальная функция, реализующая системный вызов), затем -- изменить указатель в sys_call_table так, чтобы он указывал на вашу функцию. Поскольку ваш модуль впоследствии может быть выгружен, то следует предусмотреть восстановление системы в ее первоначальное состояние, чтобы не оставлять ее в нестабильном состоянии. Это делается в пределах функции cleanup_module.
Ниже приводится исходный текст такого модуля. Он "шпионит" за выбранным пользователем, и посылать через printk сообщение всякий раз, когда данный пользователь открывает какой-либо файл. Для этого, системный вызов open(), подменяется функцией с именем our_sys_open. Она проверяет UID (User ID) текущего процесса, и если он равен заданному, то вызывает printk, чтобы сообщить имя открываемого файла, и в заключение вызывает оригинальную функцию open() с теми же параметрами, которая открывает требуемый файл.
Функция init_module изменяет соответствующий указатель в sys_call_table и сохраняет его первоначальное значение в переменной. Функция cleanup_module восстанавливает указатель в sys_call_table, используя эту переменную. В данном подходе кроются свои "подводные камни" из-за возможности существования двух модулей, перекрывающих один и тот же системный вызов. Представьте себе: имеется два модуля, А и B. Пусть модуль A перекрывает системный вызов open, своей функцией A_open, а модуль B -- функцией B_open. Первым загружается модуль A, он заменяет системный вызов open на A_open. Затем загружается модуль B, который заменит системный вызов A_open на B_open. Модуль B полагает, что он подменил оригинальный системный вызов, хотя на самом деле был подменен вызов A_open.

Содержание  Назад  Вперед