- •Раздел 3. Параллельное выполнение программ
- •3.1. Концепция процесса
- •3.2. Средства описания параллелизма
- •3.2.1. Графические средства
- •3.2.2. Языковые средства описания параллелизма
- •3.3. Организация ядра ос
- •3.3.1. Ядро как средство организации виртуальной машины
- •3.3.2. Состояния процесса и структура ядра
- •3.3.3. Дескрипторы процессов
- •3.3.4. Очереди процессов в ядре
- •3.4. Общая характеристика примитивов ядра
- •3.5. Примитивы создания и уничтожения процессов
- •Раздел 3
3.3.3. Дескрипторы процессов
Для управления процессами ЯДРО создает специальную структуру данных, описывающую процесс.
Эта структура данных обычно называется управляющим блоком или дескриптором.
Дескриптор является представителем процесса в ядре и содержит всю информацию, необходимую для управления процессом. Конкретная реализация дескриптора зависит от реализации ядра.
Например, дескриптор может иметь следующее описание:
class TProcess
{
int ssreg;
int spreg;
int* stackaddr;
int stacksize;
int priority;
TProcess (void * procname,int _priority,int _stacksize)
{
priority = _priority;
stacksize = _stacksize;
stackaddr = new int(stacksize);
ssreg = seg(procname);
spreg = off(procname);
}
~TProcess()
{
delete [] stackaddr;
}
}
TProcess * P;
void procname()
{
while (1)
{
…
}
}
int priority = 1;
int stacksize = 256;
int main()
{
P = new TProcess(procname,priority,stacksize);
...
delete P;
}
P – «глобальная» переменная среды, через которую осуществляется доступ к процессу для управления им.
Пример 2. Сегмент состояния задачи в защищенном режиме - TSS, структуру которого мы рассматривали раньше, является дескриптором, или может служить частью его, определенной архитектурой процессора.
Пример 3. Структура типа jmp_buf в СИ, которую мы тоже рассматривали раньше - это тоже дескриптор.
В общем случае дескриптор процесса содержит следующие данные:
Имя - уникальный идентификатор;
Состояние виртуальной и реальной машины: 1. Процессор (регистры, флаги); 2. Память; 3. Списки созданных ресурсов.
Состояние: 1. Активный; 2. Готовый; 3. Блокированный.
Родственные связи: 1. Родитель; 2. Потомки.
Данные для планирования: 1. Приоритет; 2. Указатели на “следующий” и “предыдущий” процессы в очереди; 3. Указатель на очередь, в которой находится процесс.
Важно, что структура дескриптора определяется разработчиком ядра, при этом содержание дескриптора усложняется с усложнением алгоритмов функционирования ядра.
3.3.4. Очереди процессов в ядре
Раз процессов в ядре много, а процессор один, то необходимо некоторое средство упорядочения процессов. В качестве такого средства упорядочения в ядре выступает очередь.
Очередь процессов в ядре - это фактически очередь дескрипторов процессов.
Из программирования известны списковые структуры данных. На этих структурах и основаны очереди процессов.
Три варианта построения очереди можно предложить.
Классический вариант, когда в структуру дескриптора включено поле - указатель на следующий процесс:
Более универсальный вариант
Коллекции - объект, который совмещает в себе достоинства списковой структуры - динамическое изменение размеров и массива - индексный доступ.
Класс «отсортированные коллекции» позволяет учитывать приоритеты процессов.
Например, список - как класс может иметь следующее минимальное описание:
class TList
{
TProcess* first;
TList()
{
}
~TList()
{
}
void insert(TProcess * P);
void remove(Tprocess * P);
}
Здесь перечислен минимальный набор методов объекта “список”. При необходимости это набор легко может быть расширен.
Списки процессов используются для организации планирования загрузки процессора.