Вызовы syscall

Вызовы syscall

Системные вызовы (часто называемые syscall в ОС Linux) обычно реализуются в виде вызова функции. Для них могут быть определены один или более аргументов (inputs), которые могут приводить к тем или иным побочным эффектам[25], например к записи данных в файл или к копированию некоторых данных в область памяти, на которую указывает переданный указатель. Системные вызовы также имеют возвращаемое значение типа long[26], которое указывает на успешность выполнения операции или на возникшие ошибки. Обычно, но не всегда, возвращение отрицательного значения указывает на то, что произошла ошибка. Возвращение нулевого значения обычно (но не всегда) указывает на успешность выполнения операции. Системные вызовы ОС Unix в случае ошибки записывают специальный код ошибки в глобальную переменную errno. Значение этой переменной может быть переведено в удобочитаемую форму с помощью библиотечной функции perror().

Системные вызовы, конечно, имеют определенное поведение. Например, системный вызов getpid() определен для того, чтобы возвращать целочисленное значение, равное значению идентификатора PID текущего процесса. Реализация этой функции в ядре очень проста.

asmlinkage long sys_getpid(void) {

 return current->tgid;

)

Следует заметить, что в определении ничего не говорится о способе реализации. Ядро должно обеспечить необходимую функциональность системного вызова, но реализация может быть абсолютно свободной, главное, чтобы результат был правильный. Конечно, рассматриваемый системный вызов в действительности является таким же простым, как и показано, и существует не так уж много различных вариантов для его реализации (на самом деле более простого метода не существует)[27].

Даже из такого примера можно сделать пару наблюдений, которые касаются системных вызовов. Во-первых, следует обратить внимание на модификатор asmlinkage в объявлении функции. Это волшебное слово дает компилятору информацию о том, что обращение к аргументам этой функции должно производиться только через стек. Для всех системных вызовов использование этого модификатора является обязательным. Во-вторых, следует обратить внимание, что системный вызов getpid() объявлен в ядре, как sys_getpid(). Это соглашение о присваивании имен используется для всех системных вызовов операционной системы Linux: системный вызов bar() должен быть реализован с помощью функции sys_bar().