Проверка необходимости перепланирования
Флаги в дескрипторе thread info говорят о том, что перед возобновлением прерванной программы должна быть выполнена дополнительная работа.
work_pending:
testb $ (1«TIF_NEED_RESCHED) , %cl jz work_notifysig work_resched:
call schedule cli
jmp resume_userspace
Если имеется висящий запрос на переключение процессов, вызывается функция schedule о, выбирающая, какой процесс должен быть выполнен. Когда возобновится выполнение предыдущего процесса, совершается переход на метку resume_userspace.
Обработка висящих сигналов, режима virtual-8086 и пошагового режима
В этом случае, помимо переключения процессов, должна быть проделана дополнительная работа:
work_notifysig:
movl esp, еах testl $0x00020000, 0x30(esp) je If work_notifysig_v86: pushl ecx call save_v86_state popl ecx movl eax, esp,xorl edx, edx call do_notify_resume jmp restore_all
Если управляющий флаг vm в регистре ef lags программы в режиме пользователя установлен, вызывается функция save_v86_state, которая строит структуры режима виртуального 8086 в адресном пространстве режима пользователя. Затем вызывается функция do notify resume о, которая позаботится о сигналах, ожидающих доставки в пошаговом режиме. Затем, чтобы возобновить прерванную программу, совершается переход на метку restore all.
Синхронизация в ядре
Можно считать ядро неким сервером, отвечающим на запросы. Эти запросы поступают либо от процесса, выполняемого процессором, либо от внешнего устройства, генерирующего запрос на прерывание. Мы проводим эту аналогию, чтобы подчеркнуть, что фрагменты кода ядра выполняются не последовательно, а вперемешку. В результате между ними может возникнуть конкуренция за ресурсы, и эту ситуацию следует контролировать с помощью соответствующих приемов синхронизации. Мы начнем эту главу с разъяснений, когда и до какой степени запросы к ядру выполняются перемежающимся способом. Затем мы представим читателю базовые примитивы синхронизации, реализуемые ядром, и опишем их применение в наиболее типичных случаях. В конце главы мы приведем несколько практических примеров.
Как ядро обслуживает запросы
Чтобы лучше понять, как выполняется код ядра, представим себе ядро в виде официанта, который должен удовлетворять запросы двух типов: поступающие от клиентов и исходящие от некоторого ограниченного количества менеджеров. Официант придерживается следующих правил:
1. Если менеджер зовет официанта, когда тот свободен, официант выполняет его указания.
2. Если менеджер зовет официанта, когда тот обслуживает клиента, официант оставляет клиента и выполняет указания менеджера.
3. Если менеджер зовет официанта, когда тот выполняет указания другого менеджера, официант приостанавливает выполнение указаний первого
менеджера и приступает к выполнению указаний второго. Когда он выполнит указания второго менеджера, он вернется к указаниям первого.
4. Один из менеджеров может приказать официанту оставить клиента, обслуживаемого в настоящий момент.
5. Выполнив указания всех менеджеров, официант может временно приостановить обслуживание своего клиента и перейти к новому.
Действия, выполняемые официантом, соответствуют коду, выполняемому процессором в режиме ядра. Когда процессор работает в режиме пользователя, считается, что официант свободен.
Указания менеджеров соответствуют прерываниям, а запросы клиентов — системным вызовам или исключениям, возбуждаемым процессами в режиме пользователя. что процесс режима пользователя, обращающийся к ядру с запросом, должен выдать соответствующую инструкцию (в архитектуре 80x86 это инструкция int $0x80 или sysenter). Такие инструкции возбуждают исключение, заставляющее процессор переключиться из режима пользователя в режим ядра. Далее в этой главе мы общим термином "исключение" обозначаем как системные вызовы, так и обычные исключения.
Внимательный читатель уже связал первые три правила официанта с вложенностью управляющих трактов ядра. Четвертое правило соответствует одной из интереснейших функциональных возможностей, появившейся в ядре Linux, а именно — вытеснению в ядре.
Предыдущая страница | 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 | Следующая страница