microbik.ru
1

Процессы и нити.


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

Для того чтобы программа была запущена на выполнение ОС сначала создает окружение или среду исполнения задачи, куда соответственно относятся:


  1. Дескриптор задачи (в данный дескриптор включается идентификатор процесса, атрибуты безопасности, приоритет процесса, состояние процесса и некоторые другие параметры);

  2. Контекст процесса (содержит необходимую информацию для возобновления работы процесса (значение регистров, дескрипторы открытых файлов, сведения о ошибках и т.д. ));

  3. ОЗУ куда помешается образ задачи и данных необходимые для ее исполнения;


После подготовке окружения операционная система производит настройку адресов задачи на конкретные адреса ОЗУ загрузку задачи в ОЗУ и передает управления ее использованием диспетчеру задач.

Созданное окружение и образ задачи называется процессом, то есть процесс - это совокупность данных ядра системы необходимых для описания образа программы в памяти и управления ее исполнением. Выполнение процесса заключается в точном исполнении инструкции записанных в программе, которые никогда не пересекается с инструкциями другого процесса. То есть инструкции и данные процессов изолированы друг от друга. В то же время существуют технологии, обеспечивающие обмен данными между процессами.


  1. Разделяемая память;

  2. Сигналы;

  3. Каналы;

  4. Сообщения;

  5. Семафоры;

  6. Просто файлы;

  7. Устройства;


Процессы подразделяются на типы:


Системные процессы – это процессы являются частью ядра операционной системы и всегда располагаются в ОЗУ. Как правило, эти процессы не имеют выделенных файлов программ и запускаются при загрузке системы. Они имеют доступ к данным, которые изолированы от всех иных процессов.

Демоныэто не итеративные процессы, которые запускаются обычным способом и выполняются в фоновом режиме. Обычно они запускаются после инициализации ядра и обеспечивают работу подсистем ОС.

^ Прикладные процессы – это все остальные процессы, выполняемые в системе. Они, как правило, могут исполняться, как в итеративном, так и фоновом режиме и связаны с сеансом работы пользователя.

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

Процесс при выполнении может породить несколько дочерних процессов и наиболее сложные "серверные" программы так и поступают, порождая процессы для каждого процесса "клиента". Каждый процесс имеет собственный идентификатор (PID) и идентификатор породившего его процесса (PPID). В UNIX системах поддерживаются отношения родитель - потомок (поэтому окружение родителя почти полностью соответствует окружению потомка рис 1) в WINDOWS NT это отношение не поддерживается (хотя некоторую информацию о родителе имеет потомок, а информацию о потомке имеет родитель)


PID=10

PPID=1






PID=20

PPID=10


PID=30

PPID=20


PID=20

PPID=10





PID=10

PPID=1



Поскольку создание нового процесса достаточно трудоемкая для ВС задача, да и полное адресное разделение дочернего и родительского процесса не всегда необходимо то многие ОС поддерживают нити управления. Нити это облегченный вариант создания более-менее независимого мини процесса. Каждая нить выполняется строго последовательно и имеет свой собственный программный счетчик и стек. Нити разделяют процессор так, как это делают процессы (разделение времени) но располагаются в адресном пространстве основного процесса.







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

^ Диспетчерская обработка: Серверный процесс при получении запроса на обработку создает нить и передает ей запрос (динамический вариант) или выбирает из пула ранее созданных нитей свободную (статический вариант) и передает ей запрос. Поскольку выполнение нитей происходит независимо, то очередь запросов не простаивает в ожидании ответов.

^ Конвейерная обработка: Процесс, получив запрос на обработку, передает его первой нити, которая, выполнив предварительную обработку, передает результаты следующей нити и так далее.

^ Командная обработка: Каждая нить обрабатывает только запрос одного типа, при поступлении запроса конкретного типа его подхватывает нить специализирующая на этом типе запросов и обрабатывает его.

В многозадачной операционной системе каждый процесс может находиться в одном из трех основных состояний:

Выполнение - это активное состояние процесса, инструкции которого в настоящий момент исполняет процессор;

Ожидание - это пассивное состояние процесса, в которое он переведен по некоторым причинам (не хватает ресурсов или процесс перешел сам в состояние ожидания). Инструкции данного процесса в настоящий момент не исполняются процессором.

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

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

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

Процессы системного класса используют стратегию фиксированных приоритетов. Системный класс зарезервирован для процессов ядра. Уровень приоритета процессу назначается ядром и никогда не изменяется. Заметим, что пользовательский процесс, перешедший в системную фазу, не переходит при этом в системный класс приоритетов.

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

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


Для создания процесса в WINDOWS используется функция API:


BOOL CreateProcess(LPCTSTR lpApplicationName, LPTSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCTSTR lpCurrentDirectory, LPSTARTUPINFO lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation );


^ LPCTSTR lpApplicationName – указатель на С-строку содержащею путь и имя исполняемого файла;

LPTSTR lpCommandLine – указатель на С-строку содержащею командную строку выполнения программы с параметрами если необходимо;

^ LPSECURITY_ATTRIBUTES lpProcessAttributes – дескриптор безопасности нового процесса (NULL – наследуется дескриптор порождающего процесса);

LPSECURITY_ATTRIBUTES lpThreadAttributes - дескриптор безопасности главного потока процесса (NULL – наследуется дескриптор порождающего процесса);

^ BOOL bInheritHandles – ключ наследования открытых файловых дескрипторов (true – наследует);

DWORD dwCreationFlags – дополнительные флаги создания процесса:

  • CREATE_DEFAULT_ERROR_MODE - не наследуется обработка ошибок порожденного процесса;

  • CREATE_NEW_CONSOLE – не наследуется консоль порожденного процесса;

  • CREATE_NEW_PROCESS_GROUP – создается новая группа процессов (данный процесс выступает как корневой);

  • CREATE_SEPARATE_WOW_VDM – процесс запускается в отдельно виртуальной машине DOC;

  • CREATE_SHARED_WOW_VDM - процесс запускается в разделяемой виртуальной машине DOC;

  • CREATE_UNICODE_ENVIRONMENT – для процесса создается среда UNICODE;

  • DETACHED_PROCESS – процесс отключается от консоли повадившего его процесса:

  • HIGH_PRIORITY_CLASS – задает высокий приоритет исполнения;

  • IDLE_PRIORITY_CLASS - задает низкий приоритет исполнения;

  • NORMAL_PRIORITY_CLASS –обычный приоритет исполнения;

  • LPVOID lpEnvironment – указатель на С-строку окружения;

  • LPCTSTR lpCurrentDirectory – указатель на С-строку текущего каталога;

  • LPSTARTUPINFO lpStartupInfo – указатель на структуру STARTUPINFO

  • LPPROCESS_INFORMATION lpProcessInformation - указатель на структуру PROCESS_INFORMATION

Структура PROCESS_INFORMATION содержит информацию о дескрипторах как родительского, так и дочернего процесса.


typedef struct _PROCESS_INFORMATION {

HANDLE hProcess;

^ HANDLE hThread;

DWORD dwProcessId;

DWORD dwThreadId;

} PROCESS_INFORMATION;


typedef struct _STARTUPINFO { // si

DWORD cb;

LPTSTR lpReserved;

LPTSTR lpDesktop;

LPTSTR lpTitle;

DWORD dwX;

DWORD dwY;

DWORD dwXSize;

DWORD dwYSize;

DWORD dwXCountChars;

DWORD dwYCountChars;

DWORD dwFillAttribute;

DWORD dwFlags;

WORD wShowWindow;

WORD cbReserved2;

LPBYTE lpReserved2;

HANDLE hStdInput;

HANDLE hStdOutput;

HANDLE hStdError;


} STARTUPINFO, *LPSTARTUPINFO;


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

  • Идентификатор пользователя и группы

  • Переменные окружения;

  • Диспозицию сигналов и их обработчики;

  • Ограничения, наложенные на процесс;

  • Текущий и корневой каталог;

  • Маску файлов;

  • Файловые дескрипторы и указатели;

  • Терминал;

Различия между родителем и потомков выражаются в уникальности PID и разных PPID, дочерний процесс свободен от сигналов ожидающих доставки и значения функции fork() различно для родителя (PID потомка)и потомка (=0)

Main()

{

int pid;

pid=fork();

if(pid==-1) {prinff(“\n Error fork”); exit(1);

if(pid==0) {printf(“\n children”); ……}

else{printf(“\n parent”);…..}

}