• Николина гора можно

    По выгодной цене николина гора можно на выгодных условиях.

    www.tweed.ru

  • Культиваторы нева

    культиваторы нева

    profinstrument.su





Linux Kernel (Ядро линукса) (часть 2)


Доставка сигнала

Мы предполагаем, что ядро обнаружило поступление сигнала и вызвало одну из функций, описанных в предыдущих разделах, чтобы подготовить дескриптор процесса, который, предположительно, будет принимать сигнал. Однако если данный процесс не выполнялся в тот момент, ядро отложило доставку сигнала. Сейчас мы обсудим действия, выполняемые ядром для обеспечения обработки процессом висящих сигналов.

Как было сказано в главе 4, ядро проверяет флаг tif sigpending процесса прежде, чем разрешит процессу возобновить работу в режиме пользователя. Так ядро проверяет наличие висящих сигналов всякий раз, когда оно завершает обработку прерывания или исключения.

Чтобы обработать незаблокированные висящие сигналы, ядро вызывает функцию do signai , которая принимает два параметра:
-regs — адрес области стека, в которой сохраняется содержимое регистров режима пользователя текущего процесса;
- oidset — адрес переменной, в которой функция сохранит битовый массив, представляющий собой маску заблокированных сигналов. Этот параметр равен null, если сохранять массив-маску нет необходимости.

При описании функции do signaio мы основное внимание уделили общим механизмам доставки сигналов. Реальный код перегружен обработкой ситуаций параллельного обращения и других специальных случаев, например, "зависания" системы, генерирования дампов, остановки и уничтожения целых групп потоков и т. д. Мы не станем вдаваться в обсуждение этих подробностей.

Как уже было сказано, функция do signaio обычно вызывается, лишь когда процессор собирается возвратиться в режим пользователя. По этой причине, если обработчик прерывания вызывает функцию do signai , она просто возвращает управление:
if ( (regs->xcs & 3) != 3) return 1;
Если параметр oidset равен null, функция инициализирует его адресом поля
current->blocked:
if (!oidset)
oidset = ¤t->blocked;
Важнейшей частью функции do signaio является цикл, многократно вызывающий функцию dequeue signaio, пока не будут обработаны все незаблокированные висящие сигналы в очередях частных и совместно используемых висящих сигналов. Код возврата функции dequeue signai о хранится в локальной переменной signr. Если он равен 0, это означает, что в очередях не осталось ни одного висящего сигнала, и функция do signaio может закончить работу. Если возвращается ненулевое значение, какой-то висящий сигнал ждет обработки. Функция dequeue signai о вызывается снова после того, как функция do signai обработает текущий сигнал.

Функция dequeue signai о сначала рассматривает все сигналы в очереди частных висящих сигналов, начиная с сигнала с наименьшим номером, а затем — сигналы в очереди совместно используемых сигналов. Она обновляет структуры данных, отмечая тот факт, что сигнал больше не является висящим, и возвращает его номер. Эта задача включает в себя сброс соответствующего бита В ПОЛе current->pending.signal ИЛИ current->signal-> shared pending. signal И ВЫЗОВ функции recalc sigpending , обновляющей значение флага tif_sigpending.

Рассмотрим, как функция do signaio обрабатывает висящий сигнал, номер которого возвращен функцией dequeue signaio. Вначале она проверяет, отслеживается ли процесс current (процесс-получатель) каким-нибудь другим процессом. В этом случае функция dosignaio вызывает функции
do_notify_parent_cidstop и schedule о, чтобы сообщить отслеживающему процессу об обработке сигнала.

Затем функция do signaio записывает в локальную переменную ка адрес структуры k sigaction сигнала, подлежащего обработке:
ka = ¤t->sig->action[signr-1];
В зависимости от содержимого структуры, возможен один из трех сценариев: игнорирование сигнала, выполнение действия по умолчанию и вызов обработчика сигнала.

Когда добавленный сигнал игнорируется явно, функция do signaio просто переходит на новый шаг цикла и, следовательно, рассматривает следующий висящий сигнал:
if (ka->sa.sa_handler == SIG_IGN) continue;
В следующих двух разделах мы опишем, как выполняется действие по умолчанию, а также как выполняется обработчик сигнала.
Выполнение действия по умолчанию по обработке сигнала
ЕСЛИ ПОЛе ka->sa.sa_handler содержит SIG DFL, функция do_signal() должна выполнить действие по умолчанию для данного сигнала. Единственным исключением является ситуация, в которой принимающим процессом является init. В этом случае сигнал просто отбрасывается, как описано в разд. "Действия, выполняемые при доставке сигнала"ранее в этой главе:
if (current->pid == 1) continue;
Для других процессов сигналы с действием по умолчанию игнорировать” обрабатываются достаточно легко:
if (signr==SIGCONT | | signr==SIGCHLD | |
signr==SIGWINCH | | signr==SIGURG) continue;
Сигналы с действием по умолчанию "остановить” способны остановить все процессы в группе. С этой целью функция do signai о переводит процессы в состояние task stopped и затем вызывает функцию schedule () (см. главу 7):
if (signr==SIGSTOP || signr==SIGTSTP ||
signr==SIGTTIN || signr==SIGTTOU) { if (signr != SIGSTOP &&
is_orphaned_pgrp(current->signal->pgrp)) continue; do_signal_stop(signr);}

Существует тонкое различие между сигналом sigstop и другими сигналами: sigstop всегда останавливает выполнение группы потоков, а прочие сигналы делают это, только когда группа не является "осиротевшей группой процессов”. Стандарт POSIX гласит, что группа процессов не является осиротев- шей”, пока в ней есть процесс, имеющий родителя в другой группе процессов, но в том же сеансе. Таким образом, если процесс-родитель уничтожен, но пользователь, запустивший его, не вышел из системы, группа процессов не считается осиротевшей”.

Функция do signal stopO проверяет, является ли процесс current первым останавливаемым процессом в группе. Если это так, функция производит групповую остановку”, а именно — записывает в поле group stop count дескриптора сигнала положительное число и пробуждает все процессы в группе. Каждый такой процесс проверяет это поле и обнаруживает, что происходит остановка группы. Тогда он изменяет свое состояние на task stopped и вызывает функцию schedule . Кроме ТОГО, функция do signal stopO посылает сигнал sigchld процессу-родителю лидера группы, если этот родитель не установил флаг sa_nocldstop для сигнала sigchld.

Сигналы, у которых действием по умолчанию является Выполнить дамп”, могут создать файл core в рабочем каталоге процесса. Этот файл будет хранить все содержимое адресного пространства процесса и регистров процессора. После того как функция do signai создаст такой файл, она уничтожит группу потоков. У остальных восемнадцати сигналов действием по умолчанию является Завершить выполнение”, которое сводится к уничтожению группы потоков. Чтобы уничтожить всю группу потоков, функция вызывает функцию do group exit , выполняющую корректный групповой выход”

Предыдущая страница | 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 | Следующая страница




Возможно, Вас также заинтересует:

ОС Knoppix - это Linux без проблем

ВведениеЕсли вы цените свое время, умеете считать деньги и знаете стоимость информации, то эта книга для вас. А так как к книге прилагается компакт- диск с готовой к работе операционной системой Knoppix Live CD, то лишь достаточно вставить его в привод и перегрузить компьютер,...

Linux Kernel (Ядро линукса) (часть 1)

Спин-блокировкаСпин-блокировка необходима в многопроцессорной системе, потому что могут возникнуть другие прерывания того же типа, и другие процессоры могут приступить к их обработке. Без спин-блокировки к главному дескриптору прерывания могли бы обратиться сразу несколько процессоров. Как мы...

Linux Kernel (Ядро линукса) (часть 2)

Копирование при записи В системах Unix первых поколений создание процесса было реализовано довольно неуклюже: получив системный вызов fork о, ядро в буквальном смысле дублировало все адресное пространство родителя и присваивало копию процессу-потомку. Такая операция...

Linux Kernel (Ядро линукса) (часть 3)

Буферы блоков и головы буферовУ каждого буфера есть дескриптор голова буфера, имеющий тип buffer head. Этот дескриптор содержит всю информацию, необходимую ядру для работы с блоком, так что перед обработкой блока ядро обязательно проверяет голову...