1 Операционные системы и оболочки Одинцов Игорь Олегович ст. преподаватель кафедры информатики весна 2006
2 Лекция 3 Процессы и алгоритмы работы с ними в централизованных ОС
3 Наша тактика Понятие процесса является одним из основных в современных операционных системах. Мы подробно рассмотрим сущность процессов и алгоритмы работы с ними в централизованных, сетевых и распределенных операционных системах.
4 План лекции Процессы: определение, разновидности, состояния, поддержка многопоточности Коммуникация процессов: простейшие средства (на примере сигналов в ОС Unix) Синхронизация процессов: взаимные исключения и блокировки Синхронизация процессов: низкоуровневые средства (HW) Синхронизация процессов: высокоуровневые средства (SW API) Синхронизация процессов: проблема тупиков Планирование процессов
5 Понятие процесса Процесс это абстракция, описывающая выполняющуюся программу. Процесс это исполнение последовательности действий в среде, включающей собственно выполняющуюся программу, а также связанные с ней данные и состояния (открытые файлы, текущий каталог и т. п.). С точки зрения операционной системы, процесс это единица работы, заявка на потребление системных ресурсов. С точки зрения аппаратной платформы, процесс объект, которому выделяется процессор. Процесс это живая душа программы.
6 Некоторые сведения о процессах Первое упоминание о процессе появилось в 60-е годы XX века в операционной системе MULTICS. Если говорить о соотношении между процессом и программой (несмотря на то, что это понятия из разных областей), то справедливы следующие два утверждения: программа это часть состояния процесса. С этой точки зрения процесс нечто большее, чем просто программа; программа может вызывать более чем один процесс для выполнения работы. С этой точки зрения программа нечто большее, чем процесс. Во многих операционных системах (например, Unix) процессы образуют иерархию. Соответственно, будем называть порожденные процессы потомками данного процесса, а родителя порожденного процесса предком.
7 Основные состояния процесса на процессоре активное состояние, в котором процесс обладает всеми необходимыми ресурсами, в том числе самим процессором; готовность процесс находится в очереди на выполнение; ожидание процесс ожидает завершения события (например, освобождения ресурса); создание выполнение действий, необходимых для создания процесса; остановлен процесс остановлен, как правило, в отладочном режиме; завершение выполнение действий, связанных с успешным завершением процесса; зомби процесс закончен, но предок не принял его завершения.
8 Действия выполняемые при создании процесса присвоение процессу уникального номера (ID); добавление процесса в список процессов, известных системе; определение начального приоритета; формирование блока управления процессом; выделение необходимых ресурсов; …
9 Адресное пространство процесса С каждым процессом связывается его адресное пространство, из которого он может читать и в которое он может писать данные. Адресное пространство содержит: саму программу данные к программе стек программы С каждым процессом также связывается набор регистров, например: счетчика команд (в процессоре) – регистр в котором содержится адрес следующей, стоящей в очереди на выполнение команды. После того как команда выбрана из памяти, счетчик команд корректируется и указатель переходит к следующей команде. указатель стека …
10 Простейшая программа на языке C, порождающая процесс в ОС Windows void main() { STARTUPINFO si; PROCESS_INFORMATION pi; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); ZeroMemory(&pi, sizeof(pi)); if ( !CreateProcess(NULL, "c:\\windows\\notepad.exe", NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi) ) { ErrorExit("Не удалось создать процесс."); } WaitForSingleObject(pi.hProcess, INFINITE); // ждем завершения CloseHandle(pi.hProcess); // освобождаем ресурсы CloseHandle(pi.hThread); }
11 Простейшая программа на языке C, порождающая процесс в ОС Unix void main() { int status; int child_pid, child_status; child_pid = fork(); if ( child_pid == 0 ) { /* находимся в потомке */ execlp("ls", "ls", (char*)0); exit(1); /* оказываемся здесь только в случае неудачного исполнения вызова execlp */ } else if ( child_pid != -1 ) { /* находимся в предке */ status = wait(&child_status); printf(" %d %d \n", status, child_status); }
12 Процессы с поддержкой многопоточности Поток (нить) управления (thread) это исполнение команд программы в естественном порядке. Процессы делятся на традиционные (имеющие один поток управления) и многопоточные (многонитевые). Многопоточность в рамках одного процесса имеет существенные преимущества: Переключение контекста между двумя потоками в одном процессе значительно проще, чем переключение контекста между двумя процессами. Все данные, за исключением стека исполнения и содержимого регистров процессора, разделяются между потоками. Таким образом, многопоточность предоставляет эффективный параллелизм.
13 Реализация потоков в ОС Solaris потоки ядра являются базовыми потоками. Они располагаются в адресном пространстве ядра и непосредственно связаны с процессами; облегченные (легковесные) потоки служат для организации пользователем нескольких потоков управления в адресном пространстве. Каждому облегченному потоку соответствует свой отдельный ядерный поток. Каждый облегченный поток может отдельно планироваться (на каждый процессор по потоку). Облегченные потоки следует рассматривать как диспетчеризуемые сущности; пользовательские потоки, для создания которых пользователь работает со стандартной библиотекой. Пользовательские потоки связываются с облегченными потоками.
14 Пример создания и использования потоков POSIX и Solaris #include … void *sleeping(void *); /* функция, которая будет исполняться как поток */ int i; thread_t tid[NUM_THREADS]; /* массив для хранения номеров потоков */ void main(int argc, char *argv[]) { switch ( *argv[1] ) { case '0': /* POSIX */ for ( i = 0; i < NUM_THREADS; i++ ) pthread_create(&tid[i], NULL, sleeping, SLEEP_TIME); for ( i = 0; i < NUM_THREADS; i++ ) pthread_join(tid[i], NULL); break; case '1': /* Solaris */ for ( i = 0; i < NUM_THREADS; i++ ) thr_create(NULL, 0, sleeping, NULL, 0, &tid[i]); while (thr_join(NULL, NULL, NULL) == 0 ) ; break; } /* switch */ printf("Все %d потоков управления завершены\n", i); } void *sleeping(int sleep_time *) { printf("Поток управления %d приостановлен на %d секунд\n", thr_self(), SLEEP_TIME); sleep(sleep_time); printf("Исполнение потока управления %d возобновлено\n", thr_self()); }
15 План лекции Процессы: определение, разновидности, состояния, поддержка многопоточности Коммуникация процессов: простейшие средства (на примере сигналов в ОС Unix) Синхронизация процессов: взаимные исключения и блокировки Синхронизация процессов: низкоуровневые средства (HW) Синхронизация процессов: высокоуровневые средства (SW API) Синхронизация процессов: проблема тупиков Планирование процессов
16 Коммуникация процессов Коммуникация – передача информации от одного процесса другому Передача может осуществляться следующими способами: Посредством разделяемой памяти Посредством передачи сообщений или потоков данных: Сигналы (только в Unix) это программное средство, с помощью которого может быть прервано функционирование процесса. Почтовые ящики (только в Windows), однонаправленные, возможность широковещательной рассылки. Каналы (трубы) – это псевдофайл, в который один процесс пишет, а другой из него читает. Сокеты (гнезда) – это поддерживаемый ядром механизм, скрывающий особенности среды и позволяющий единообразно взаимодействовать процессам, как на одном компьютере, так и в сети. Удаленный вызов процедур, процесс может вызвать процедуру в другом процессе (в том числе и на другом компьютере), и получить обратно данные. …
17 Сигналы как простейшие средства коммуникации Сигналы (signals) это программное средство, с помощью которого может быть прервано функционирование процесса в операционной системе Unix. Механизм сигналов позволяет процессам реагировать на различные события, которые могут произойти в ходе функционирования процесса внутри него самого или во внешнем мире. Каждому сигналу ставится в соответствие: номер сигнала; символическая константа, используемая для осмысленной идентификации сигнала; принадлежность к одному из пяти классов сигналов; реакция процесса на сигнал: вызов обработчика сигнала; завершение процесса (возможно, с порождением дампа памяти); игнорирование сигнала; приостановка исполнения.
18 Следующие ситуации приводят к генерации сигналов ОС Ядро отправляет процессу сигнал при нажатии пользователем определенной комбинации клавиш на клавиатуре; Возникновение аппаратных особых ситуаций приводит к посылке уведомления ядру операционной системы, которое отправляет сигнал процессу, находящемуся в стадии выполнения; Определенное программное состояние системы может вызвать отправку сигнала.
19 Наиболее интересные типы сигналов Сигналы от оборудования, порождаемые при выполнении процесса в результате возникновения некоторых исключительных условий. SIGFPE (8) исключительная ситуация при выполнении операции с плавающей или фиксированной точкой; SIGILL (4) попытка выполнить неверную машинную команду; SIGSEGV (11) нарушение защиты памяти; SIGBUS (10) ошибка шины (адресации); Программные сигналы, либо генерируемые пользователем с клавиатуры, либо посылаемые одним процессом другому. SIGINT (2) сигнал прерывания от терминала (пользователь нажал комбинацию клавиш + ); SIGQUIT (3) сигнал аварийного завершения работы от терминала (пользователь нажал комбинацию клавиш + ); SIGTERM (15) сигнал программного прерывания, посылаемого по умолчанию командой kill; SIGKILL (9) сигнал программного прерывания, который не может быть ни перехвачен, ни проигнорирован никаким процессом; SIGHUP (1) разрыв связи с терминалом; Сигналы контроля процессов, либо генерируемые пользователем с клавиатуры, либо посылаемые одним процессом другому. Ряд этих сигналов используется отладчиками для посылки сигналов процессу с отлаживаемой программой. SIGSTOP (23) остановка процесса; SIGTSTP (24) остановка процесса пользователем (пользователь нажал комбинацию клавиш + ); SIGCONT (25) продолжение приостановленного процесса; SIGCHLD (18) изменение статуса порожденного процесса.
20 Программа на языке Pascal, исполнение которой приведет к генерации сигнала SIGSEGV program SegmentationViolation; type Pinteger = ^integer; var IntVar: integer; NullPtr: Pinteger; begin NullPtr := nil; { Попытка выполнить следующее присваивание приведет к сигналу SIGSEGV } IntVar := NullPtr^; end.
21 Установка обработчика сигнала прерывания от терминала #include static void reaction(int i) { printf("Вызван обработчик сигнала %d \n", i); exit(i); } void main() { if ( signal(SIGINT, SIG_IGN) != SIG_IGN ) signal(SIGINT, reaction); printf("Перед подачей сигнала с клавиатуры \n"); while ( 1 ) ; printf("После подачи сигнала с клавиатуры \n"); }
22 План лекции Процессы: определение, разновидности, состояния, поддержка многопоточности Коммуникация процессов: простейшие средства (на примере сигналов в ОС Unix) Синхронизация процессов: взаимные исключения и блокировки Синхронизация процессов: низкоуровневые средства (HW) Синхронизация процессов: высокоуровневые средства (SW API) Синхронизация процессов: проблема тупиков Планирование процессов
23 Синхронизация процессов в централизованных архитектурах Процессы называются параллельными, если они существуют одновременно. Могут быть: Независимые Взаимодействующие и нуждающимися в синхронизации Синхронизация процессов использование специальных атомарных операций для осуществления взаимодействия между процессами.
24 Критические ресурсы и участки Критический ресурс это ресурс, допускающий обслуживание только одного процесса за один раз. Если несколько процессов хотят использовать критический ресурс в режиме разделения, то им следует синхронизировать свои действия, чтобы ресурс всегда находился в распоряжении не более чем одного из них. Критические участки это участки процесса, где происходит обращение к критическому ресурсу. Критические участки должны быть взаимоисключаемыми, т. е. в каждый момент времени не более чем один процесс может быть занят выполнением своего критического относительно некоторого ресурса участка. Обеспечение (поддержка механизма) взаимоисключения ключевая задача параллельного программирования. Типичным примером критического ресурса является разделяемая переменная, суммирующая некоторую величину (назовем ее счетчик). Критические участки процессов тогда могут содержать следующий код: счетчик := счетчик + 1.
25 Блокировка Блокировка предотвращение выполнения кем-либо чего-либо. Процесс должен устанавливать блокировку перед входом в критический участок и снимать ее после выхода. Естественно, если участок заблокирован, то другой процесс должен ждать снятия блокировки. Вход взаимоисключения и выход взаимоисключения участки процесса, обрамляющие критический участок и служащие для обеспечения взаимоисключения. Примером входа взаимоисключения может служить блокирование, а выхода разблокирование.
26 Гонки Гонки (race conditions) ситуация, когда два или более процессов обрабатывают разделяемые данные и конечный результат зависит от соотношения скоростей их исполнения.
27 Спасибо! Вопросы?
28 P.S. Экзаменационные вопросы: Процессы: определение, разновидности, состояния, поддержка многопоточности Коммуникация процессов: простейшие средства (на примере сигналов в ОС Unix) Синхронизация процессов: взаимные исключения и блокировки