- •Реализация потоков в простренстве пользователя
- •Реализация потоков в ядре:
- •Строгое чередование
- •Примитивный межпроцессного взаимодействия
- •Планирование
- •Алгоритм - наименьшее время выполнения .
- •Планирование в интерактивных системах.
- •Управление памятью.
- •Управление памятью с помощью видовых массивов.
- •Управление памятью с помощью связанных списков.
- •Подкачка.
- •Виртуальная память.
- •Функционирование менеджера памяти.
- •Прямой доступ к памяти
Строгое чередование
while(1)
{ while(turn);
goto_crit();
turn=1;
noncrit ();
}
while (1)
{ while(!turn);
goto_crit();
turn=0
noncrit ();
}
переменная торн отслеживает чья очередь входить в критическую область. Первый процесс выходит их критической области, переменная торн равна 1. И оба процесса находяться в некритической области. Если первый процесс быстро завершит работу в некритической области и веернется к началу цикла, то он будет заблокирован 2ым процессом. Эта ситуация нарушает третее условие. Этот процесс не может быть быть блокирован другим процессом в критической области.
Активное ожидание - постоянная проверка значения переменной в ожидании некоторогго значения. Спин блокировка - блокировка, использующая активное ожидание.
Алгоритм Петерсона
#define n 2
int turn, interested [n];
void goto_crit (int proc)
{ int other;
other=1 - proc;
interested [proc]=TRUE;
turn=proc;
while (turn==proc&interested[proc]==TRUE);
}
void leave_crit
(int proc)
{
interested[proc]=FALSE;
}
команда TSL (test and set lock)
решение проблемы взаимного исключения с помощью команда тсл требует поддержки процессором такой команда. Принцип действия: в регистр считывается переменная блокировки а в эту переменную записывается некоторое ненулевое значение. Гарантируется, что операция чтения и сохранения недилимы. Если переменная лок управляет доступом к критическому ресурсу и значение переменной равно нулю, то любой процесс может обратиться к критическому ресурсу измениа значение лок на 1,а после выхода вкрнуть в нулевое значение команды mov.
Goto_crit ()
{: loop
tsl rx, lock
cmp rx, 0
je loop
}
leave_crit ()
{
mov lock, 0
}
недостаток: активное ожидание.
Примитивный межпроцессного взаимодействия
проблема инверсии приоритета:
алгоритмы с использованием активного ожидания кром бесцельного расхода времени процессора могут иметь некоторые неожиданные последствия. Допустим есть 2 процесса: процесс аш с высоким приоритетом и процесс эль с низким. По правилам клонирования процесс аш запускается как только оказывается в состоянии готовности и переключение на процесс эль во время его работы не происходит. Допустим эль в критической области. Происходит переключение контекста. Процесс аш попадает в состояние активного ожидания. В этом случае процесс эль никогда не сможет выйти из критической области, а процесс аш нафсегда останется в активном ожидании. Эта ситуация называется проблемой инверсии приоритета. Для решения этой проблемы используются приметив межпроцессорного взаимодействия. Эти примитивы блокируют процессы в случае запрета на вход в критическую область.
Проблема производителя-потребителя примитив sleep wake. Существует программа производитель и программа потребитель, а также совместно используемый буфер ограниченного размера, который является критическим ресурсом. Ошибки возникают при попытке записи производителем в полный буфер либо считыванием потребителя из пустого буфера. Решение этой проблемы с помощью примитивов слип и вэйк.
#define n 10
int count=0
void producer (void)
{int item;
while (1)
{ item=produce ();
if (coutn==n) sleep ();
insert_item (item);
count++;
if (count==1) wake(consumer);
}
void consumer (void)
{ int item;
while (1)
{ if(!count) sleep();
item=remove_item();
count --;
if(count==n-1)
wake (produser);
consume_item (item);
}
}
проблема состояния состязания не решена так как не ограничен доступ к переменной коунт. Во первых возможен одновременный доступ к буферу, во вторых допустим буфер пуст. Потребитель счтывает нулефое значение переменной коунт после этого происходит переключение контекста. Производитель записывает элемент в пустой буфер считывает значение счетчика 1 и отправляет сигнал на пробуждение потребителя. Проблема состоит в том что потребитель еще не находиься в состоянии сна, следовательно сигнал пропадает. При переключении контекста потребитель отправляется в вечный сон и после заполнения буфера туда же отправляется производитель. Проблема пропадания сигнала решается добавлением бита ожидании активации. Если сигнал пробуждения послан в холостую то этот бит устанавливается. При попытке процесса уйти в состояние ожидания бит сбрасывается но процесс остается активным. Увеличение числа процессов повлечет за собой увеличение числа активации.
Семофоры.
Семофоры - специальный тип переменных, значение которых может быть нулем либо другим полоожительныи числом. Они предназначены для подсчета сигналов запуска, сохраненных на будущее. С семофорами связано две операции. Ап и довн.
Операция довн сравниввает значение симофора с нулем. Если симофор больше нуля довн уменьшает значение симофора и возращает управление процессу. Если симофор равен нулю то процесс переводиться в состояние блокировки.
Операция ап увеличивает значение симофора. Если с симофором связаны 1 или несколько ожидающих процессов системой выбирается 1 из них и ему разрешается завершить свою операцию довн. Операции ап и довн выполняются как единое целое неделимое действие. Это гарантирует что после начало и до завершения ни 1 процесс не получит доступа к симофору.
#define n 100
typedef int semaphore,
semaphore mutex=1,
semaphore empty=n,
semaphore full=0
void produccer (void)
{int item,
while (1) {item=produce(),
down(&empty);
down(&mutex);
insert(item);
up(&mutex);
up(&full);
}}
void consumer (void)
{int item;
while(1)
{down(&full);
down(&mutex);
item=remove();
up(&mutex);
up(&empu);
consume (item);
}}
симофоры исходное значение которых равно 1 используемые для исключения одновременного нахождения в критической области более одного процесса называются двоичными симофорами.
Mutex - упрощенная версия симофора не способная считать а только управлять исключением одновременного доступа к критическим ресурсам. Простота реализации и эффективность делают мютексы полезными в случае реализации потоков в пространстве пользователя.
Mutex_lock:
tsl rx, mutex
cmp rx, 0
je ok
call thread_yield
jmp mutex_lock
ok: ret
-----------
mutex_unlock:
mov mutex, 0
ret
в отличие от активного ожидания реализация взаимного исключения с помощью мютексов предполагает добровольную блокировку потока и передачу управления к другому потоку.
Мониторы.
Реализация взамного исключения с помощью симофора предполагает детальную разработку с целбю не допустить взаимной блокировки. Для улучшения ситуации взаимоблокировки был предложен примитив синхронизации более высокого уровня, так называемый монитор. Монитор - набор структур переменыых и других структур данных обьединенных в особый модуль. Процессы могут вызывать процедуры монитора. Но у процидур объявленных вне монитора нет прямого доступа к его внутренним структурам. Реализации взаимных исключений способствуют такое свойство монитора что при обращении к монитору в любой момент времени активным может быть тока 1 процесс. Обычно первые несколько команд проверяют нет ли в мониторе активного процесса. Если есть то вызывающий процесс входит в состояние ожидания. Поскольку взаимные исключения обеспечивает компилятор а не программист вероятность ошибки гораздо меньше. Для блокировки процессов не способны продолжить свою деятельность были введены переменная состояния и операции вайд и сигнал.
Monitor prod_cohs
{ condition full, empty;
int count;
void insert (int item)
{ if (cout==n) wait (full);
insert_item(item);
count++;
if (count==1) signal (empty);
}
int remove (void)
{ if (!count)
wait (empty);
return (remove_item);
count--;
if (count==n-1)
signal (full);
}}
void produser (void)
{ while (1)
{ item=produce_item();
prod_cons.insert();
}
}
void consumer (void)
{ while (1)
{item=pred_cous.remove();
consume_item(item);}
}
