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


Функция group_send_sig_info

Функция group_send_sig_info отправляет сигнал всей группе потоков. Она принимает три параметра: номер сигнала sig, адрес info структуры siginfo t (или одно из специальных значений 0, 1 или 2) и адрес р дескриптора процесса.
Функция выполняет следующие действия:
1. Проверяет корректность параметра sig:
if (sig 64) return -EINVAL;
2. Если сигнал был послан процессом режима пользователя, функция проверяет, разрешена ли эта операция. Сигнал будет доставлен только при выполнении хотя бы одного из следующих условий:
• владелец процесса, пославшего сигнал, имеет соответствующее разрешение (как правило, это просто означает, что сигнал был послан системным администратором, см. главу 20);
• был послан сигнал sigcont, и процесс-получатель находится в одном сеансе с процессом-отправителем;
• оба процесса принадлежат одному пользователю.
Если процессу режима пользователя не разрешено посылать сигнал, функция возвращает код -eperm.
3. Если параметр sig равен 0, функция немедленно возвращает управление, не генерируя сигнал:
if (!sig |I !p->sighand) return 0;
Поскольку ноль не является номером сигнала, он используется процессом- отправителем для проверки наличия у себя привилегий, достаточных для отправки сигнала группе потоков. Функция также возвращает управление, если процесс-получатель в данный момент уничтожается; об этом она узнает, проверяя, освобожден ли дескриптор обработчика сигналов, принадлежащего этому процессу.
4. Получает спин-блокировку p->sighand->sigiock и отключает локальные прерывания.
5. Вызывает функцию handie stop signai о, которая проверяет тип сигнала, поскольку сигналы некоторых типов могут аннулировать другие висящие сигналы, посланные группе потоков. Вызванная функция выполняет следующие действия:
• если группа потоков в данный момент уничтожается (флаг signal group exit в поле flags дескриптора сигнала установлен), функция возвращает управление;
• если параметр sig определяет сигнал sigstop, sigtstp, sigttin или SIGTTOU, функция вызывает функцию rm_f rom_queue (), ЧТОбы удаЛИТЬ сигнал sigcont из очереди висящих совместно используемых сигналов p->signai->shared_pending и из очередей частных сигналов всех членов группы;
• если параметр sig определяет сигнал sigcont, функция вызывает функцию rm_f rom_queue , ЧТОбы удаЛИТЬ СИГНаЛЫ SIGSTOP, SIGTSTP, SIGTTIN
и sigttou (если таковые имеются) из очереди висящих совместно используемых сигналов p->signai->shared_pending. Затем функция удаля-
ет те же сигналы из очередей висящих частных сигналов всех процессов, входящих в группу, и возобновляет выполнение этих процессов:
CTn_from_queue(ОхООЗсОООО, &p->signal->shared_pending); t = р; do {
CTn_from_queue(ОхООЗсОООО, &t->pending); try_to_wake_up(t, TASK_STOPPED, 0); t = next_thread(t);
} while (t != p);
Маска ОхООЗсОООО выделяет четыре стоп-сигнала. При каждой итерации макрос next thread возвращает адрес дескриптора очередного облегченного процесса в группе.
6.Проверяет, проигнорирует ли группа данный сигнал. Если это так, возвращает 0 (успех). Сигнал игнорируется, если удовлетворены все три условия, упомянутые в разд.
7. Проверяет, что сигнал не является сигналом реального времени (sigshared_pending.signal,sig)) return 0;
8. Вызывает функцию send signaio, чтобы поставить сигнал в очередь висящих совместно используемых сигналов. Если функция send signai о возвратит ненулевой код ошибки, описываемая функция завершит работу с тем же кодом ошибки.
9. Вызывает функцию group_compiete_signai, чтобы разбудить один из
облегченных процессов в группе
10. Освобождает спин-блокировку p->sighand->sigiock и включает локальные прерывания.
11. Возвращает 0 (успех).

Функция group compiete signai о перебирает процессы в группе в поисках процесса, который может принять новый сигнал.

Процесс будет выбран, если он удовлетворяет всем следующим условиям:
- процесс не блокирует сигнал;
- процесс не находится ни в одном из следующих состояний: exit zombie,
EXIT_DEAD, TASK_TRACED И TASK_STOPPED (в ПОрЯДКе ИСКЛЮЧеНИЯ ПрОЦеСС MO-
жет быть в состоянии task traced или task stopped, если сигнал является сигналом sigkill);
- процесс не уничтожается, т. е. его флаг pf exiting не установлен;
- либо процесс в данный момент выполняется каким-нибудь процессором, либо его флаг tif sigpending еще не установлен. На практике нет никакого смысла будить процесс, у которого имеются висящие сигналы: вообще говоря, это сделал управляющий тракт ядра, установивший флаг tif sigpending. С другой стороны, если процесс выполняется, его следует уведомить о новом висящем сигнале.
Группа потоков может включать в себя много процессов, удовлетворяющих этим условиям. Функция выбирает один из них, руководствуясь следующими соображениями:
- если процесс, идентифицируемый переменной р (адресом дескриптора, переданным в качестве параметра функции group_send_sig_info()), удовлетворяет всем перечисленным требованиям и, следовательно, может принять сигнал, функция выбирает его;
- в противном случае функция ищет подходящий процесс, перебирая элементы группы, начав с процесса, который принял последний сигнал, посланный группе (p->signal->curr_target).

Если функции group compiete signai удается найти подходящий процесс,она обеспечивает доставку сигнала выбранному процессу. Во-первых, она проверяет, является ли сигнал фатальным. В этом случае уничтожается вся группа путем отправки сигналов sigkill каждому облегченному процессу в группе. Если же сигнал не фатален, функция вызывает функцию signai_ wake upo, чтобы уведомить выбранный процесс о новом висящем сигнале.

Предыдущая страница | 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 без про...

ВведениеЕсли вы цените свое время, умеете считать деньги и знаете стоимость информации, то эта книга...

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

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

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

Копирование при записи В системах Unix первых поколений создание процесса было реализовано довольно...

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

Буферы блоков и головы буферовУ каждого буфера есть дескриптор голова буфера, имеющий тип buffer...