- •Введение
- •Лабораторная работа 1.
- •Регистрация пользователя в системе
- •Выход из системы
- •Выполнение простых команд
- •Группирование команд
- •Задание для самостоятельной работы
- •Контрольные вопросы
- •Задание для самостоятельной работы
- •Контрольные вопросы
- •Задание для самостоятельной работы
- •Контрольные вопросы
- •Задание для самостоятельной работы
- •Контрольные вопросы
- •Литература
- •5.3. Задание для самостоятельной работы
- •5.4. Контрольные вопросы
- •Задание для самостоятельной работы
- •Контрольные вопросы
- •Задание для самостоятельной работы
- •Формат файла /etc/passwd
- •Формат файла /etc/shadow
- •Формат файла /etc/group
- •Создание нового пользователя
- •Переключение между пользователями
- •Файлы инициализации пользователей
- •Файлы, регламентирующие работу пользователей
- •Задания для самостоятельной работы
- •Контрольные вопросы
- •9.3. Права доступа к каталогам
- •9.4. Смена прав доступа на файлы
- •9.5. Маска на вновь создаваемые файлы
- •9.6. Дополнительные атрибуты файла
- •9.7. Списки управления доступом
- •Задания для самостоятельной работы
- •Контрольные вопросы
- •10.3. Метасимволы или шаблоны
- •10.4. История команд
- •10.5. Псевдонимы
- •10.6. Перенаправление ввода и вывода
- •10.7. Конвейеры
- •10.8. Приглашение ко вводу
- •10.9. Сценарии оболочки
- •10.10. Задания для самостоятельной работы
- •10.11. Контрольные вопросы
- •11.3. Системный вызов open()
- •11.4. Системный вызов read()
- •11.5. Системный вызов write()
- •11.6. Системный вызов lseek()
- •11.7. Системный вызов close()
- •11.8. Задания для самостоятельной работы
- •11.9. Контрольные вопросы
- •12.3. Системный вызов fork
- •12.4. Системный вызов exit
- •12.5. Системный вызов wait
- •12.6. Системный вызов exec
- •12.7. Системные вызовы наследования пользовательских дескрипторов файла
- •12.8. Задания для самостоятельной работы
- •12.9. Контрольные вопросы
- •13.3. Системный вызов signal
- •13.4. Системный вызов pause
- •13.5. Системный вызов alarm
- •13.6. Управление непредусмотренными событиями
- •13.7. Неименованные каналы
- •13.8. Именованные каналы
- •13.9. Задания для самостоятельной работы
- •13.10. Контрольные вопросы
- •Литература
- •Заключение
- •Учебное издание
- •Системное программирование Лабораторный практикум
11.9. Контрольные вопросы
Как можно выяснить, что достигнут конец файла?
Что такое дескриптор файла?
Каков самый быстрый способ перемещения на конец файла?
Для чего предназначены флаги чтения /записи?
Для чего предназначены смешанные флаги?
ЛИТЕРАТУРА
1. Глас Г., Эйблс К. Unix для программистов и пользователей. / Г. Глас, К. Эйблс – СПб.: БХВ-Петербург, 2004. – 848 с.: ил.
ЛАБОРАТОРНАЯ РАБОТА 12.
СИСТЕМНЫЕ ВЫЗОВЫ ОПЕРАЦИЙ УПРАВЛЕНИЯ ПРОЦЕССАМИ
12.1. Цель работы
Целью работы является изучение системных вызовов, с помощью которых обеспечивается управление процессами в среде ОС UNIX.
12.2. Управление процессами
Процесс Unix – это уникальный экземпляр, работающий или работоспособной программы. Каждый процесс в системе Unix имеет следующие атрибуты:
некоторый код;
некоторые данные;
стек;
уникальный ID процесса (PID).
Когда Unix стартует, в системе существует только один видимый процесс. Этот процесс называется init и имеет PID равный 1. Единственный способ создать новый процесс состоит в том, чтобы продублировать существующий процесс, так что init – предок всех последующих процессов. Когда процесс дублируется, родительский и дочерний процессы фактически идентичны. Код порожденного процесса, данные и стек – это копия родителя.
Дочерний процесс может, однако, заменить свой код кодом другого выполняемого файла, таким образом, отделяя себя от родителя. Например, когда процесс init начинает выполняться, он быстро дублируется несколько раз. Каждый из дубликатов дочерних процессов затем заменяет свой код из исполняемого файла getty, который является ответственным за обработку пользовательского входа в систему. Когда дочерний процесс заканчивается, этот факт сообщается его родителю, чтобы родитель мог предпринять некоторое соответствующее действие. Обычное действие для родительского процесса – приостановка, пока один из порожденных процессов не закончится. Например, когда shell выполняет утилиту в приоритетном режиме, он дублируется в два процесса shell. Дочерний процесс shell заменяет свой код кодом утилиты, тогда как родительский shell ждет завершения дочернего процесса. Когда порожденный процесс заканчивается, первоначальный родительский процесс пробуждается и представляет пользователю следующее приглашение shell. Системные вызовы управления процессами представлены в таблице 12.1.
Таблица 12.1
Системные вызовы управления процессами
Имя |
Описание |
fork |
Дублирует процесс |
getpid |
Получает ID процесса |
getppid |
Получает ID родительского процесса |
exit |
Прекращает процесс |
wait |
Ожидает дочерний процесс |
exec |
Замещает код, данные и стек процесса |
12.3. Системный вызов fork
Системный вызов fork служит для создания нового процесса и имеет следующий формат:
int pid;
pid= fork;
Порожденный процесс представляет собой точную копию своего процесса предка. Последнее означает, что в обоих процессах открыты в одном и том же режиме одни и те же файлы и имеются совершенно одинаковый код и внутренние данные. Единственное отличие между ними заключается в том, что процесс потомок в качестве возвращаемого значения системного вызова fork получает число 0, а процесс предок – целое положительное число. Последнее обстоятельство дает возможность определить, является данный процесс процессом потомком или процессом предком.
Пример. Ниже приведен фрагмент программы на языке Си, иллюстрирующий сказанное.
int pid;
if(pid = fork() !=0) {
if(pid > 0) {
/* процесс предок */
} else {
/* fork завершен аварийно */
}
} else {
/* процесс потомок */
}
Каждый пользовательский процесс имеет уникальный номер, называемый идентификатором процесса и однозначно его специфицирующий. Наличие у процесса идентификатора дает возможность ОС Unix, и любому другому пользовательскому процессу получить необходимую информацию о функционирующих в данный момент процессах. Для того чтобы получить собственный идентификатор процесса, пользовательский процесс должен осуществить системный вызов getpid следующим образом:
int mypid;
mypid= getpid();
Плучить идентификатор процесса предка можно с помощью системного вызова getppid следующим образом:
int ppid;
ppid= getppid();
Итак, идентификатор процесса представляет собой целое положительное число, с помощью которого процесс однозначно идентифицируется ядром ОС Unix. Часть этого ядра, которая ответственна за генерацию идентификаторов процессов для вновь порождаемых процессов, гарантирует уникальность генерируемых идентификаторов процессов, а это означает невозможность возникновения такой ситуации, при которой два или более процесса имеют одинаковые идентификаторы процесса.