Рис.8.

3.2.3 Дескриптор процесса

Любому процессу как абстрактному понятию присущи, однако, две реальные части:

1. программа развития процесса в активном состоянии;

2. дескриптор процесса.

Динамика процесса определяется динамическими характеристиками дескриптора. В нем отображаются динамически изменяемые связи процесса с другими процессами. Все процессы, находящиеся в текущий момент в одном и том же состоянии, объединяют через дескрипторы в одну списковую структуру, но с учетом приоритетов процессов. По функциональному назначению информация в дескрипторе делится на следующие группы:

1. Идентификация – содержит имя процесса, которое используется в управлении над процессом как над поименованным объектом.

2. Информация о ресурсах, которые затребованы или используются процессом в данный момент.

3. Информация о состоянии процесса, которая определяет текущее состояние и возможность перехода в следующее.

4. Информация о родственных связях, используемых для корректного окончания процесса и установки информационных связей.

5. Информация для учета и планирования процессов, содержащих адресные ссылки на другие процессы, приоритет процесса в очередях, ссылки на средства синхронизации.

В операционной системе UNIX процесс представляет собой:

1. Область данных пользователя, которая в момент существования процесса может быть выделена в оперативной памяти или находиться на внешнем устройстве, если процесс временно вытеснен из оперативной памяти.

2. Дескриптор процесса. Дескрипторы разных процессов объединяются в таблицу, из каждого дескриптора существует ссылка на таблицу пользователя – контекст процессов. Таблица контекстов постоянно находится в оперативной памяти. Таблица пользователя используется только в активном состоянии и вместе с процессом может быть перемещена на диск и не доступна модификации. В дескрипторе операционной системы UNIX содержатся: адресные ссылки на области оперативной памяти, где хранятся области процесса; адресные ссылки на внешнюю память, куда вытесняется процесс, информация для синхронизации процессов, идентификация процессов; породившие его процессы.

3.3.1 Управление процессами в операционной системе UNIX

Управление процессами в UNIX обеспечивается системными функциями: fork, exec. Запуск одной программы из другой реализуется замещением в оперативной памяти выполняемой в данный момент программы, вызвавшей эту функцию, на программу из указанного файла и запуском ее. Функция exec не изменяет идентификатора старого процесса, то есть новый процесс реализуется в рамках старого. В случае успешного завершения запущенного процесса возврата из exec не бывает, а образ памяти вызывающей программы теряется. Управление процессами выполняется следующими дополнительными функциями: nice (устанавливает приоритет процесса), pause (приостанавливает процесс), pipe (организует канал взаимосвязи процессов), А также системными командами: kill (завершить процесс), sleep (приостановить выполнение процесса), nice (запуск команды с низким приоритетом). Системные функции выполняются в рамках того же процесса, что и оболочка UNIX, а команды - из командной строки.

Так как проблема реализации многозадачной операционной системы сводится к реализации в ней запуска одной программы из другой, то в UNIX это реализуется командой exec.

Способы вызова функции exec:

1. С нефиксированным и неизвестным количеством параметров вызова: int execv (name, argv); name - указатель на строку, содержащую имя файла, argv – вектор из указателей на параметры в виде цепочки литер, которые передаются в вызывающую программу. Вектор завершается нулевым указателем.

2. Явное задание параметров вызова: int execl (name, arg0, …, argN, 0).

Каждый из этих способов вызова может быть реализован с выбором пути поиска файла командой path (execlp), с использованием среды, запускающего процесса, который указывает параметр envp: execve (name, argv, environ)

Отказ выполнения команды exec может произойти по следующим причинам:

1) отсутствие или невыполнимость указанного файла;

2) очень большой список параметров;

3) недостаток адресного пространства для нового процесса.

Так как при запуске новой программы с помощью exec управление над старым процессом теряется, то для сохранения экземпляра старой программы используют fork, что порождает две почти идентичные копии процесса - родительского и порожденного. Родительскому процессу fork возвращает номер порожденного процесса, а порожденному – 0. Порожденный процесс наследует все компоненты образа родительского процесса (программу, связанные с ней данные, состояния открытых файлов). Новый процесс имеет собственный сегмент данных и стек. Единственные совместно используемые ресурсы – файлы, которые были открыты до распараллеливания процесса. Вопрос о принадлежности файлов не встает, если родитель ожидает завершения работы потомка, а при их параллельной работе с файлами должны соблюдаться соглашения о доступе. Первопроцесс – процесс, реализующий оболочки системы.

A& - исполнение фоновой команды. Она при помощи fork создает новый процесс и переназначает в нем стандартный ввод на файл с именем /dev/NULL, оставляя за собой ввод с терминала.

Пример использования функций fork и exec:

Proc_id=fork();

if (fork()==0) execlp(“bin/sh”, “sh”, “-c”,commandline,0);

В результате потомок, которому fork возвращает адрес вызываемой функции execlp, выполняет команду commandline и завершается. Так как в родительский процесс fork возвращает не 0, то функция execlp пропускается.

Для управления процессами используются также следующие функции системы UNIX:

wait – системная функция, приостанавливает обратившийся к ней процесс до тех пор, пока не завершится один из его потомков или не будет получен другой сигнал. При нормальном возврате из этой функции возвращается идентификатор завершившегося порожденного процесса. Если порожденных процессов несколько, то, чтобы узнать об их завершении, необходимо обратиться к функции wait несколько раз. Если нет ни одного порожденного процесса, то возвращается код ошибки –1. В случае нескольких потомков порядок завершения не определен, следовательно, для реализации ожидания завершения конкретного процесса выполняется следующий цикл:

int status;//статус завершения

int childpid;//идентификатор потомка

while (wait(&status)!=childpid)

exit – функция добровольного завершения процесса, закрывает все файлы данного процесса, уведомляет родительский процесс, ожидающий завершения порожденного процесса функцией wait. Родительскому процессу передаются младшие 8 бит статуса завершения, причем status=0 – добровольное завершение порожденного процесса, status=1 – аварийное завершение процесса.

3.3.2 Управление процессами в OS/2

Основными объектами диспетчеризации являются процессы и потоки. Система характеризуется четким разделением ресурсов между процессами, что достигается защитой данных и разделением больших программ на более мелкие с определенным взаимодействием. Поток – последовательность команд, которая разделяет общие ресурсы процесса.

Над процессами выполняются такие действия:

· DosExecPmt – создание дочернего процесса.

· DosCWait – ожидание завершения дочернего процесса.

· DosKillProcess – прекращение выполнения дочернего процесса и всех его потомков.

· DosExit – самозавершение процесса.

· DosSetPrty – установка приоритета.

Над потоками выполняются следующие действия:

· DosCreatThreed - создание и запуск потока, принадлежащего к данному процессу.

· DosSusperdThread – приостановка (подвешивание) выполнения одного потока из другого потока того же процесса.

· DosResumeThreed – разрешение продолжения ранее приостановленного потока.

· DosEnterCritSec – запрет на выполнение других потоков данного процесса.

· DosExitCritSec – отмена запрета на выполнение всех других потоков данного процесса

· DosGetPrty – присвоение потоку класса и уровня приоритета исходного потока или некоторого определенного потока.

Функция создания дочернего процесса имеет следующий вид:

DosExecPgm(*FailObjName, FailObjNameLen, ExecType, *Arg, *Env, *RetInfo, *PgmName), где:

*FailObjName – указатель на буфер, используемый при ошибке для возврата имени динамически вызванного блока, приведшего к ошибке. FailObjNameLen – длина этого буфера.

ExecType – определяет способ выполнения нового процесса по отношению к родительскому:

0 - новый процесс выполняется последовательно с родительским, то есть родительский процесс приостанавливается до тех пор, пока не завершится дочерний.

1 - процесс выполняется параллельно с текущим процессом без кода возврата, при этом идентификатор нового процесса запоминается в первом слове RetInfo, а код возврата потомка игнорируется.

2 - процесс выполняется параллельно с текущим процессом без кода возврата, при этом идентификатор нового процесса запоминается в первом слове RetInfo кодом возврата потомка и может быть получен под DosCWait.

3 - трассировка, когда новый процесс выполняется под управлением родительского и не начинается до получения функции DosPTrase.

4 - новый процесс отделяется от родительского, выполняется одновременно с родительским и не допускает использование клавиатуры, мыши и т. д.

5 - замороженная загрузка, программа загружается, подготавливается к запуску и остается в режиме готовности, пока не будет разморожена функцией DosSistemServis.

*Arg – указатель на параметры командной строки.

*Env – указатель на строку окружения. Если передаются параметры родитeльского процесса, то *Env=NULL.

*RetInfo – возвращает информацию о новом процессе: идентификатор и код идентификатора.

*PgmName – имя файла, содержащее программу, запускаемую в начале потомка.

Функция DosExecPgm создаёт новый процесс с одним потоком. Каждый процесс имеет уникальное адресное пространство и является владельцем ресурсов, используемых его потоками. Новый процесс наследует от родителя заголовки файлов, каналов и семафоров. Создание процесса предпочтительнее, чем создание потока в следующих случаях:

1) новый поток слабо связан с остальными и необходим на долгое время;

2) новый поток не участвует в совместном использовании большинства ресурсов;

3) некоторые компиляторы не поддерживают создания нескольких потоков.

Функция уничтожения процесса имеет вид:

DosKillProcess (Scope, //0-указывает на необходимость терминации процесса.

PID // идентификатор терминируемого процесса

)

Пример: программа создает потомка child. exe, дает ему время поработать в качестве асинхронного процесса, родительский процесс засыпает на время SleepTime, а затем просыпается и терминирует потомка:

#include <os2.h>

#include <doscall. h>

#define ExecType 1 //асинхронный режим

#define PRM child. exe

#define SleepTime 1000 //1 секунда

main()

{struct RetInfo ChildInfo;

int i;

printf (“\n запуск программы родителя”);

printf (“\n создать программу потомка”);

DosExecPgm(0l,0,ExecType,0l,0l,&ChildInfo, PRM);

DosSleep(SleepTime);

Printf(“\n пробуждение родителя через одну секунду”);

Printf(“\n ПЕРЕХОД К УНИЧТОЖЕНИЮ ПОТОМКА”);

DosKillProsess(1,ChildInfo. PID);

Printf(“\n потомок уничтожен”);DosExit;

Printf(“\n окончание родительского процесса”);}

Функция изменения приоритетов процессов и потоков имеет следующий вид:

DosSetPrty(Scope, PrtyClass, PrtyDelta, ID), где

Scope – принимает следующие значения:

0 – изменение приоритетов всех потоков текущего процесса; 1 – изменение приоритета всех потоков текущего процесса и их потомков; 2 – изменение приоритета только указанного потока.

PrtyClass – новый класс приоритета:

0 - сохраняется прежний класс.

1 - изменение класса приоритета на низкоприоритетный.

2 - изменение класса приоритета на нормальный.

3 - изменение класса приоритета на высокий.

PrtyDelta: [0,31] – если класс приоритета изменяется;

[-31,31] – относительно текущего класса.

ID – идентификатор в зависимости от значения Scope содержит идентификатор процесса Scope=0 или идентификатор потока, если Scope=1,2. ID=0 – изменение приоритета текущего потока.

3.3.3 Функции управления потоками

Новый поток создается процессом следующей функцией:

DosCreatThreed(&ThreedEntry, &TID, ThreadStack),

где &ThreedEntry – входная точка нового потока; &TID – идентификатор потока; ThreadStack – размер стека нового потока.

Все потоки имеют равные права доступа к ресурсам процесса. Первый поток может управлять сигналами для синхронизации потоков.

Пример: первый поток запускает второй и оба выводят на экран свою цифру со своим номером:

.286

Extern DosCreatThread: far

Extern DosExit: far

Extern VioWriteTTY: far

Print macro msg

Push ds

Push off set msg

Push es msg

Push vioHandle

Call vioWrtTTY

Endm

Dosseg

.model small

.stack 2500

dw 2500 dup (?)

t2 stack dw

t2 od dw

.const

t1 id msg db ‘1’ lt1 id msg equ $t1:dmsg

t1 himsg equ $-t1 byemsg

t2…;lt2…;t2h…;lt2h…;

t2byemsg…;lt2 byemsg…;

Errmsg equ$-Errmsg;

NoErrmsg db ‘NoError’

LNoErrmsg equ $-NoErrMsg;

VioHandle equ 0

MsgCnt equ 8000 d

.code

thread1 proc far

print t1 himsg

push cs

push ds

push off set thread2;

push ds

push off set t2id;

push ds

push off set t2 stack;

call DosCreatThreed;

cmp ax,0

jne Error

print NoErrorMsg;

jmp M1

Error:print ErrMsg

M1:mov cx, MsgCnt

Loop1:print t1 idMsg

Loop loop1

Print t1 byemsg

Push 0

Push 0

Call DosExit

Threed endp

Thread2 proc far

Print t2himsg

Mov cx, msgCnt

Loop2:print t2 idMsg

Loop loop2

Print t2byemsg

Push 0

Push 0

Call DosExit

Threed2 endp

End threed1

Функция терминации текущего процесса или потока имеет вид

DosExit(Scope:word, RetCode:word)

где Scope – принимает следующие значения: 0 – терминация текущего потока;
1 – терминация всех потоков процесса, а значит и самого процесса.

RetCode – код возврата, используемый для идентификации успешности завершения. Возвращается родителю терминируемого процесса.

При терминации процесса закрываются все открытые файлы и освобождаются все ресурсы, которыми владел процесс. Циклическая диспетчеризация осуществляется только между потоками одинакового приоритета. Как только поток более высокого приоритета готов к работе, он активизируется независимо от того, отработал ли текущий поток свой квант времени. Если какой–либо поток не получает процессов в течение долгого времени, которое задается квантом MAXWAIT файла config. sys, OS/2 временно увеличивает его приоритет, чтобы не “уморить” поток. Динамическое изменение приоритетов может быть запрещено параметром PRIORITY.

Рекомендации по изменению приоритетов процессов:

1) программы, не взаимодействующие с пользователем (пакетного типа), помещаются в низкоприоритетный класс;

2) поток, от которого зависят другие потоки, помещается в высокоприоритетный класс;

3) потоки реального времени помещаются в высокоприоритетный класс;

4) увеличивать приоритет процесса или потока следует только на момент выполнения действительно приоритетной работы;

5) желательно разбивать программы на потоки разных приоритетов;

6) избегать назначения высоких приоритетов для потоков, активно использующих процессор, и не опасаться такого назначения для потоков, работающих с внешними устройствами;

7) лучше уменьшать приоритет других потоков, чем повышать приоритет одного.

3.3.4 Управление процессами в операционной системе WINDOWS 95

Управление процессами в операционной системе WINDOWS 95 реализуется с помощью API–функций WINDOWS, важнейшие из которых – CreatProcess и CreatThreed. В WINDOWS 95 запуск одной программы из другой реализуется с помощью функции WinExec. Начиная с версии 3.1,используется функция ShellExecute, которая является функцией WinExec, дополненной эмуляцией диспетчера программ.

Управление процессами реализуется с помощью функций:

CreatProcess – создание дочернего процесса.

Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4