Повторный запуск системного вызова, прерванного необработанным сигналом
Если сигнал явно игнорируется процессом, или выполняется его действие по умолчанию, функция do signai о анализирует код ошибки системного вызова, чтобы, в соответствии с табл. 11.11, принять решение об автоматическом повторении неоконченного системного вызова. Если вызов должен быть повторен, функция модифицирует аппаратный контекст regs так, чтобы при возвращении процесса в режим пользователя регистр eip указывал либо на инструкцию int $0x80, либо на sysenter, а регистр еах содержал номер системного вызова:
if (regs->orig_eax >=0) {
if (regs->eax == -ERESTARTNOHAND || regs->eax == -ERESTARTSYS || regs->eax == -ERESTARTNOINTR) { regs->eax = regs->orig_eax; regs->eip -= 2;
}
if (regs->eax == -ERESTART_RESTARTBLOCK) {
regs->eax = NR_restart_syscall;
regs->eip -= 2;
}
}
В поле regs->eax записывается код возврата служебной процедуры системного вызова (см. главу 10). Обратите внимание, что обе инструкции, int $0x8 о и
sys return, имеют длину два байта, и поэтому функция вычитает 2 из eip, чтобы там был адрес инструкции, производящей системный вызов.
Код ошибки erestart restartblock является специальным, потому что в регистр еах записывается номер системного вызова restart syscaii О, и, следовательно, процесс в режиме пользователя не повторяет именно тот системный вызов, который был прерван сигналом. Данный код ошибки используется только системными вызовами, работающими с показаниями часов. При повторном запуске такие системные вызовы должны подстраивать свои параметры режима пользователя. Типичным примером является системный вызов nanosleep о Предположим, процесс делает этот вызов, чтобы приостановить выполнение на 20 мс, а через 10 мс приходит сигнал. Если бы системный вызов был повторен обычным образом, общее время задержки составило бы 30 мс.
Вместо этого служебная процедура системного вызова nanosleep записывает в поле restart biock структуры thread info процесса current адрес специ- альной служебной процедуры, которая будет вызвана при рестарте, и возвращает -erestart restartblock, когда ее работы прерываются. Служебная процедура sys_restart_syscaii всего лишь выполняет служебную процедуру специального вызова nanosieepo, которая регулирует задержку с учетом времени, прошедшего между запуском первоначального системного вызова и его рестартом.
Предыдущая страница | 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 | Следующая страница