- •И.Н.Акуленок, а.В.Акуленок
- •Часть I. Основы операционной системы unix Утверждено советом университета
- •Введение
- •Глава 1. История создания ос unix
- •Реализации oc unix
- •Unix на платформе Intel
- •Доля компьютеров с ос unix (1993 год)
- •Продажи unix–серверов (III квартал 2007 года)
- •1.1. Первые шаги по созданию unix
- •1.2. Исследовательские версии unix
- •1.3. Основные стандарты
- •1.3.1. Основные задачи стандартизации
- •1.4. Разработчики операционных систем
- •1.4.1. Версии at&t
- •1.4.2. Версии Microsoft/sco
- •1.4.3. Версии университета Беркли
- •1.4.4. Версии компании Sun
- •1.4.5. Версии компании Nowell
- •1.4.6. Популярные версии unix
- •1.4.7. Свободно распространяемые системы unix
- •1.5. Реализация ядра unix
- •1.5.1. Микроядро Mach
- •1.5.2. Микроядро Chorus
- •1.6 Характеристики oc unix
- •1.6.1.Файловая система
- •1.6.2. Многозадачность
- •1.6.3. Многопользовательский режим
- •1.6.4. Мобильность
- •1.6.5. Виртуальная память
- •1.6.6. Связь между задачами
- •1.6.7. Внешние устройства
- •1.6.8. Связь между компьютерами
- •1.6.9. Графический пользовательский интерфейс
- •1.6.10. Безопасность
- •1.6.11. Поддержка баз данных
- •1.6.12. Наличие стандартов
- •1.6.13. Открытость
- •1.6.14. Разработка программного обеспечения
- •1.7. Контрольные вопросы
- •1.8. Тесты
- •Глава 2. Функционирование ос unix
- •2.1. Ядро
- •2.1.1. Функции ядра
- •2.1.2. Структура ядра
- •2.1.3. Файловая подсистема
- •2.1.4. Подсистема управления процессами
- •2.1.5. Подсистема ввода/вывода
- •2.2. Командный процессор Shell
- •2.3. Программы–утилиты
- •2.4. Контрольные вопросы
- •2.5. Тесты
- •Глава 3. Процессы
- •3.1. Контекст процесса
- •3.3. Типы процессов
- •3.3.1. Системные процессы
- •3.3.2. Демоны
- •3.3.3. Прикладные процессы
- •3.4. Атрибуты процесса
- •3.4.1. Идентификатор процесса
- •3.4.2. Идентификатор родительского процесса
- •3.4.3. Приоритет процесса
- •3.4.4. Терминальная линия
- •3.4.5. Реальный и эффективный идентификаторы пользователя
- •3.4.6. Реальный и эффективный идентификаторы группы
- •3.4.7. Идентификатор терминальной группы
- •3.5. Иерархия процессов
- •3.6. Взаимодействие процессов
- •3.6.1. «Отцы», «дети», «сироты», «зомби»
- •3.7. Системные вызовы
- •3.7.1. Механизм создания процесса и запуска программы
- •3.7.2. Графический пример дерева процессов
- •3.8. Связи между процессами
- •3.8.1. Сигналы
- •Сигналы posix 1.1
- •3.8.2. Очереди сообщений
- •3.8.3. Семафоры
- •3.8.4. Совместная память
- •3.8.5. Программные каналы
- •3.8.6. Программные гнезда
- •3.9. Контрольные вопросы
- •3.10. Тесты
- •Глава 4. Файловая система unix
- •4.1. Имена файлов
- •4.2. Структура файловой системы
- •4.2.1. Загрузочный блок
- •4.2.2. Суперблок
- •4.2.3 Дескрипторы файлов
- •4.2.4. Блоки данных и свободные блоки
- •4.3. Типы файлов
- •4.3.1. Обычные файлы
- •4.3.2. Каталоги
- •4.3.4. Символические связи
- •4.3.5. Fifo – Именованные каналы
- •4.3.6. Сокеты
- •4.3.7. Обозначение типов файлов
- •Типы файлов
- •4.4. Дескриптор обычного файла
- •4.5. Дескриптор каталога
- •4.6. Дескриптор специального файла
- •4.7. Системная таблица файлов
- •4.8. Монтирование файловых систем
- •4.9. Демонтирование файловых систем
- •4.10. Проверка и восстановление файловых систем
- •4.11. Журналирование файловых систем
- •4.12. Контрольные вопросы
- •4.13. Тесты
- •Глава 5. Этапы начальной загрузки ос Unix
- •5.1. Загрузка и инициализация ядра
- •5.2. Распознавание и конфигурирование устройств
- •5.3. Создание спонтанных процессов
- •5.4. Выполнение команд оператора
- •5.5. Выполнение командных файлов запуска системы
- •5.6. Переход в многопользовательский режим
- •5.7. Контрольные вопросы
- •5.8. Тесты
- •Глава 6. Обзор командных файлов
- •6.1. Процесс init
- •6.1.1. Формат файла inittab
- •6.1.2. Уровни выполнения
- •Уровни выполнения
- •6.1.3. Дисциплины обработки процесса
- •Дисциплины обработки процесса
- •6.1.4. Запуск и этапы работы процесса init
- •6.2. Процесс rc
- •6.2.1. Сценарии запуска системы Solaris
- •6.3. Процесс cron
- •6.4. Процесс регистрации пользователей
- •6.5. Контрольные вопросы
- •6.6. Тесты
- •Глава 7. Останов системы
- •7.1. Выключение питания
- •7.2. Команда shutdown
- •7.3. Команда halt
- •7.4. Изменение уровня выполнения процесса init
- •Глава 8. Задачи системного администрирования
- •8.1. Инструменты администрирования
- •8.1.1. Администрирование aix
- •8.1.2. Администрирование hp-ux
- •8.1.3. Администрирование Solaris
- •8.1.4. Администрирование Linux
- •8.2. Пользователь root
- •8.2.1. Команда su
- •8.3. Добавление новых пользователей в систему
- •8.3.1. Файл /etc/passwd
- •Идентификаторы пользователей
- •8.3.2. Файл /etc/group
- •8.4. Контрольные вопросы
- •8.5. Тесты
- •Литература
- •Содержание
- •Глава 1. История создания ос unix 6
- •Глава 2. Функционирование ос unix 51
- •Глава 3. Процессы 75
- •Глава 4. Файловая система unix 116
- •Акуленок Ирина Николаевна Акуленок Анатолий Васильевич
- •Часть I. Основы операционной системы unix
3.4.7. Идентификатор терминальной группы
Еще один способ группирования – объединение процессов в терминальную группу. Члены группы получают в качестве атрибута идентификатор терминальной группы TGID, который равен значению PID лидера этой группы. В качестве лидера выступает процесс, который открыл терминал. Управляющий терминал используется для передачи через управляющий процесс (т. е. процесс–лидер) сигналов для всех процессов – членов группы. Сигналы вырабатываются при нажатии определенных клавиш на клавиатуре. Следует отметить, что каждый пользователь, входящий в систему по login, обязательно порождает новые процессы. При этом каждый процесс в контексте пользователя имеет один и тот же идентификатор пользователя UID. Соответствие между UID и login–именем пользователя фиксируется в файле /etc/passwd. Пользователи получают различные привилегии. Имеются суперпользователи с неограниченными возможностями. Процесс суперпользователя (superuser) имеет UID, равный 0, а остальные – целые положительные числа, отличные от 9.
3.5. Иерархия процессов
Процессы образуют иерархические отношения между собой. Ядро предоставляет каждому процессу средства дублирования самого себя с целью создания новых процессов. Существуют понятия «процесс–отец» или родительский процесс и «процесс–сын» или дочерний процесс (child process). Процесс может иметь только одного «родителя», но порождать много «детей», и их отношения лучше всего выражает родственное древо. К примеру, рис. 3.3 показывает отношения процессов P1, Р2, РЗ, Р4, Р5 и P6 (P – это обозначение процесса).
В этом графе существуют следующие отношения:
Р1 порождает два процесса: Р2 и Р4. При этом P1 является «отцом», а Р2 и Р4 являются его «сыновьями».
P2 создает РЗ. При этом Р2 является «родителем» РЗ, а РЗ соответственно его «сыном» и «потомком» P1.
P4 является «родителем» Р5 и Р6; Р5 и Р6 – соответственно «детьми» Р4.
Рис. 3.3. Иерархия процессов
P1 является «дедушкой» P3, Р5 и Р6, Р3, Р5 и Р6 – «внуки» P1. Р3, Р5 и Р6 не имеют порожденных процессов.
3.6. Взаимодействие процессов
«Процесс–сын» наследует все свойства «процесса–отца», включая переменные окружения, текущий рабочий директорий, открытые файлы.
Любой процесс в UNIX порождается с помощью системного вызова fork(), поэтому часто говорят о ветвлении (fork – ветвь). После выполнения fork() оба процесса продолжают выполнение с одной и той же точки.
Любой процесс может завершиться по собственной инициативе с помощью системного вызова exit (status).
3.6.1. «Отцы», «дети», «сироты», «зомби»
Операционная система UNIX, являясь в своей основе средством управления процессами, сама по себе может рассматриваться как система параллельных взаимодействующих процессов с древовидной структурой. Общий прародитель всех процессов в системе – процесс init, находящийся в вершине генеалогического древа. Этот процесс порождается особым образом и далее постоянно присутствует в системе. Все другие процессы порождаются в системе по унифицированной схеме с помощью системного вызова fork().
Сразу после обработки системного вызова fork() происходит установление двусторонней связи между «процессом–отцом» и «процессом–сыном». «Сын» при этом наследует все свойства «отца». Однако существование нового, порожденного процесса как точной копии другого не имеет никакого смысла. Поэтому почти всегда «сын» заменяет программный код «отца» на свой собственный программный код. Эго возможно с помощью системного вызова ехес().
«Процесс–отец» ожидает окончания исполнения «процесса–сына», используя системный вызов wait().
Что происходит в случае завершения процесса? Если процесс издает системный вызов exit(), то он, выражаясь языком пользователей UNIX, становится «процессом–самоубийцей» и порождает в связи со своей смертью целый ряд проблем.
Ведь каждый из завершивших свой жизненный путь процессов имеет своего «родителя», но одновременно он может быть «родителем» других процессов. Поэтому могут остаться «сироты», судьбу которых надо как–то решать. Здесь имеется несколько вариантов:
Вариант нормального окончания.
«Процесс–отец» выдает системный вызов wait() и ждет, когда «процесс–сын» завершит свое выполнение по системному вызову exit(). Однако, если у «сына» были свои «процессы–дети», то чтобы они не остались «сиротами», происходит их «усыновление» прародителем всех процессов init. Главная работа ядра UNIX при этом заключается в переустановлении PPID у «процессов–сыновей». Он становится для них равным единице. Кроме того, всем процессам – членам группы рассылается соответствующий сигнал.
Вариант «ненормального» окончания.
«Процecc–сын» выдает системный вызов exit(), когда существует его «отец» и «отец» не находится в состоянии ожидания wait(). В этом случае связь «отца» с «сыном» продолжает существовать, несмотря на то, что «сын» «умер». Слот «процесса–сына» в таблице процессов сохраняется, и поэтому такой не до конца уничтоженный процесс называют «зомби».
Удалить такой процесс можно только перезапуском операционной системы. Зомби в небольших количествах не представляют опасности, однако если их много, это может привести к переполнению таблицы процессов.
Элемент в системной таблице процессов сохраняется до тех пор, пока родительский процесс не выполнит системный вызов wait(), только после этого освобождается и элемент системной таблицы процессов.
Вариант преждевременного выхода.
«Процесс–отец» заканчивается ранее своих «сыновей». В этом случае происходит реконфигурация генеалогического древа и все «процессы–сироты» перенаправляются постоянно действующему процессу init.
