Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лаб.практикумСП.doc
Скачиваний:
39
Добавлен:
31.03.2015
Размер:
5.99 Mб
Скачать

11.9. Контрольные вопросы

  1. Как можно выяснить, что достигнут конец файла?

  2. Что такое дескриптор файла?

  3. Каков самый быстрый способ перемещения на конец файла?

  4. Для чего предназначены флаги чтения /записи?

  5. Для чего предназначены смешанные флаги?

ЛИТЕРАТУРА

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. Часть этого ядра, которая ответственна за генерацию идентификаторов процессов для вновь порождаемых процессов, гарантирует уникальность генерируемых идентификаторов процессов, а это означает невозможность возникновения такой ситуации, при которой два или более процесса имеют одинаковые идентификаторы процесса.