Интерфейсные процедуры ядра
Хотя системные вызовы применяются, в основном, процессами режима пользователя, они могут быть использованы и потоками ядра, которые не в состоянии вызывать библиотечные функции. Для упрощения объявлений соответствующих интерфейсных процедур в операционной системе Linux определен набор из семи макросов, носящих имена от syscaiio до _syscaii6.
В имени макроса цифра от 0 до 6 соответствует количеству параметров, используемых в системном вызове (не считая номера системного вызова). Эти макросы применяются для объявления интерфейсных процедур, еще не включенных в стандартную библиотеку libc (например, потому что системный вызов Linux еще не поддерживается библиотекой), однако, они непригодны для определения интерфейсных процедур для системных вызовов, принимающих более шести параметров (не считая номера системного вызова), или вызовов, возвращающих нестандартные значения.
Каждому макросу требуется 2 + 2 п параметров, где п — количество параметров системного вызова. Первые два параметра определяют тип возвращаемого значения и имя системного вызова, а каждая следующая пара параметров задает тип и имя соответствующего параметра системного вызова. Например, интерфейсная процедура системного вызова fork о может быть сгенерирована макросом:
_syscallO(int, fork)
А интерфейсная процедура системного вызова write может быть сгенерирована макросом:
_syscall3(int,write,int,fd,const char ,buf,unsigned int,count)
В последнем случае макрос возвращает следующий код:
int write(int fd,const char buf,unsigned int count)
long res;
asm ("int $0x80"
: "=a" ( res)
: "0" ( NR_write), "b" ((long)fd),
"c" ((long)buf), "d" ((long)count));
if ((unsigned long) res >= (unsigned long)-129) {
errno = - res;res = -1;}return (int) res;}
Макрос NR_write получен из второго параметра макроса _syscaii3; он расширяется в номер системного вызова write . При компиляции этой функции будет сгенерирован следующий ассемблерный код:
write:
pushl ebx ; положить ebx в стек
movl 8(esp), ebx ; занести первый параметр в ebx
movl 12(esp), есх ; занести второй параметр в есх
movl 16(esp), edx ; занести третий параметр в edx
movl $4, еах ; занести NR_write в еах
int
$0x80 ; сделать системный вызов
cmpl $-125, еах ; проверить код возврата
jbe .L1 ; если ошибки нет, выполнить переход
negl еах ; дополнить значение еах
movl еах, errno ; поместить результат в errno
movl $-1, еах ; записать -1 в еах
.LI: popl ebx ; снять ebx со стека
ret ; возвратить управление вызвавшей программе
Обратите внимание, как параметры функции write загружаются в регистры процессора до выполнения инструкции int $0x8о. Значение, возвращаемое в регистре еах, должно быть интерпретировано как код ошибки, когда оно лежит в диапазоне от -1 до -129 (ядро предполагает, что максимальный код ошибки, определенный в файле include/generic/ermo.h, равен 129). Если это действительно так, интерфейсная процедура записывает значение -еах в переменную errno и возвращает -1. В противном случае она возвращает значение еах.
Предыдущая страница | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | Следующая страница