- •Архитектура семейства ос Unix
- •6.1. История и современное состояние
- •6.2. Архитектура Unix
- •6.3. Процессы
- •6.4. Нити
- •6.5. Планирование процессов
- •6.6. Управление памятью
- •6.7. Средства взаимодействия процессов
- •6.8. Файловые системы
- •Файловая система s5
- •Файловая система ufs
- •Файловая система sfs
- •Файловая система Veritas
- •Другие файловые системы Open Unix
- •Файловая система jfs
- •6.9. Интерфейсы Unix
- •6.10. Unix-системы фирмы Caldera
6.5. Планирование процессов
Механизм планирования нитей библиотекой нитей является надстройкой над механизмом планирования процессов (легковесных процессов), реализуемых ОС.
Состояния процессов, которые различаются в ОС Unix, показаны на рисунке 6.3.
Рисунок 6.3 Состояния процесса в ОС Unix |
Новый процесс создается системным вызовом fork (см. ниже) - переход 1 на рисунке 6.3. Если оперативной памяти в системе достаточно, то процесс создается в памяти (выделяется память для размещения адресного пространства процесса) - переход 2. Если памяти недостаточно (только в системе с подкачкой сегментов), то процесс создается на внешней памяти - переход 3. Если процесс создан в памяти, он переходит в состояние готовности к выполнению, из которого может быть запущен на выполнение - переход 4. При запуске процесс начинает выполнение в режиме ядра, но затем "возвращается" (такова специфика выполнения системного вызова fork) в режим задачи - переход 5. Выполняемый в режиме задачи процесс может перейти в режим ядра по внешнему прерыванию или выдав системный вызов (программное прерывание) - переход 6. Выполнение обработчика прерывания или системного вызова происходит в режиме ядра, но в контексте процесса. Выполнение в режиме ядра может прерываться, как было описано выше, но с возвратом в прерванный уровень - переход 7. Если переход в режим ядра произошел по причине прерывания от таймера, и планировщик процессов ОС принимает решение о том, что необходимо запустить другой процесс, то процесс переходит в зарезервированное состояние - переход 8. Зарезервированное состояние в принципе идентично состоянию готовности в памяти, различие между ними состоит в том, что выполнение зарезервированного процесса (когда до него дойдет очередь) возобновляется сразу в режиме задачи - переход 9. Если же переход в режим ядра произошел в связи с выполнением, а это выполнение связано с необходимостью ожидания или планировщик процессов ОС принимает решение о том, что необходимо запустить другой процесс, то процесс переходит в состояние приостановки - переход 10. Когда процесс получит те ресурсы, которых он ожидает, он переводится в состояние готовности - переход 11, из которого он может быть вновь запущен в режиме ядра - переход 4, а из него вернуться в выполнение в состоянии задачи - переход 5. При нехватке памяти приостановленный или даже готовый процесс может быть выгружен на внешнюю память - переходы 12. Процесс, ожидающий ресурса на внешней памяти, там же на внешней памяти может быть переведен в состояние готовности - переход 11. Готовый процесс на внешней памяти (перешедший в состояние готовности из приостановки или созданный на внешней памяти) загружается (подкачивается) в память - переход 13. Когда выполнение процесса завершается (выполнением системного вызова exit), процесс переходит в режим ядра, а из него - в состояние завершения - переход 14. В этом состоянии большинство ресурсов процесса освобождается, но строка в таблице процессов остается, в ней сохраняется некоторая информация о процессе, которая может быть "востребована" и после завершения процесса, например, код завершения процесса.
С самого начала "проект Unix" задумывался как система с разделением времени. Исходная дисциплина планирования процессов, называемая иногда "алгоритмом полураспада", описана нами в разделе 2.3 части I. Там мы, однако, рассматривали только динамическое перевычисление приоритетов и не упомянули о том, что в системе имеются два класса процессов: процессы ядра и пользовательские процессы. Планирование по "алгоритму полураспада" выполняется только для пользовательских процессов. Системные же процессы имеют более высокие приоритеты, и их приоритеты заложены в коде ядра. Так, наивысший приоритет имеет процесс подкачки страниц, следующий - процесс ожидания дискового ввода-вывода и т.д. Даже когда пользовательский процесс выполняется в режиме ядра, он не становится процессом ядра, и никакие динамические добавки к приоритету не могут вывести приоритет пользовательского процесса за тот порог, который разделяет процессы ядра и процессы пользователей. Приоритеты процессов ядра абсолютные: появление процесса ядра, готового к выполнению, прерывает выполнение пользовательского процесса или менее приоритетного процесса ядра.
Дисциплина "алгоритма полураспада" обеспечивает прекрасные показатели справедливости обслуживания, что делает ее удобной для интерактивной работы, но непригодной для выполнения процессов реального времени. Стандарты POSIX и Single Unix Specifications требуют наряду с обеспечением интерактивной работы и обеспечения реального времени. Поэтому в современные клонах ОС Unix дисциплина планирования несколько модифицирована. В системе теперь различаются три класса процессов (в порядке возрастания приоритетов):
процессы разделения времени;
процессы ядра;
процессы с фиксированным приоритетом.
Процессы разделения времени - аналогичны пользовательским процессам в "старой" ОС Unix. Но цели их планирования несколько изменились. Теперь наряду с обеспечением приемлемого времени реакции для интерактивных процессов, дисциплина должна обеспечивать также и хорошую производительность для "счетных" процессов. Для этого алгоритм планирования процессов разделения времени модифицирован изменением размера кванта времени. Для процессов с низким приоритетом размер кванта увеличивается. В соответствии с правилами динамического перевычисления приоритеты тех процессов, которые переходят в состояние приостанова, не исчерпав полученного кванта, повышаются, а тех, которые используют выделенный им квант до конца - понижаются. Это приводит к селекции процессов: интерактивные процессы получают высокие приоритеты, а счетные - низкие. В результате счетный процесс получает квант времени ЦП реже, чем интерактивный, но размер этого кванта для счетного процесса больше.
Процессы ядра - те же, что и в "старой" ОС Unix, и планируются они так же.
Новый класс процессов - процессы с фиксированным приоритетом - во многом похож на процессы ядра. Приоритет для процессов такого класса устанавливается пользователем и не изменяется системой. Сам процесс с фиксированным приоритетом может, однако, изменять свой приоритет во время выполнения. Приоритеты процессов этого класса абсолютные, то есть появление готового к выполнению процесса прерывает выполнение и процесса разделения времени, и процесса ядра, и процессы с фиксированным, но более низким приоритетом. Для процессов с фиксированным приоритетом пользователь может получить гарантированный порядок их выполнения.
Процесс при запуске наследует класс процесса, породившего его, по умолчанию - это класс разделения времени. Привилегированный пользователь может использовать в своем процессе системные вызовы установки фиксированного приоритета.
Основные системные вызовы, обеспечивающие порождение процессов в Unix, описаны нами в разделе 4.3 части I, это:
fork - порождение процесса-потомка,
exec - смена программы процесса,
exit - завершение процесса,
wait - ожидание завершения процесса-потомка.
Аналогичные системные вызовы в отношении нитей:
th_create - порождение нити,
th_exit - смена программы процесса,
th_join - ожидание завершения нити.
