Архитектура операционной системы UNIX



              

Реализация семафоров - часть 2


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

struct semaphore { int val[NUMPROCS]; /* замок---1 элемент на каждый про- /* цессор */ int lastid; /* идентификатор процессора, полу- /* чившего семафор последним */ }; int procid; /* уникальный идентификатор процес- /* сора */ int lastid; /* идентификатор процессора, полу- /* чившего семафор последним */

INIT(semaphore) struct semaphore semaphore; { int i; for (i = 0; i < NUMPROCS; i++) semaphore.val[i] = 0; } Pprim(semaphore) struct semaphore semaphore; { int i,first;

loop: first = lastid; semaphore.val[procid] = 1; /* продолжение на следующей странице */

Рисунок 12.6. Реализация семафорной блокировки на Си

Для начала дадим определение семафора как структуры, состоящей из поля блокировки (управляющего доступом к семафору), значения семафора и очереди процессов, приостановленных по семафору. Поле блокировки содержит информацию, открывающую во время выполнения операций типа P и V доступ к другим полям структуры только одному процессу. По завершении операции значение поля сбрасывается. Это значение определяет, разрешен ли процессу доступ к критическому участку, защищаемому семафором. В начале выполнения алгоритма операции P () ядро с помощью функции Pprim предоставляет процессу право исключительного доступа к семафору и уменьшает значение семафора. Если семафор имеет неотрицательное значение, текущий процесс получает доступ к критическому участку. По завершении работы процесс сбрасывает блокировку семафора (с помощью функции Vprim), открывая доступ к семафору для других процессов, и возвращает признак успешного завершения. Если же в результате уменьшения значение семафора становится отрицательным, ядро приостанавливает выполнение процесса, используя алгоритм, подобный алгоритму sleep (): основываясь на значении приоритета, ядро проверяет поступившие сигналы, включает текущий процесс в список приостановленных процессов, в котором последние представлены в порядке поступления, и выполняет переключение контекста. Операция V () получает исключительный доступ к семафору через функцию Pprim и увеличивает значение семафора. Если очередь приостановленных по семафору процессов непуста, ядро выбирает из нее первый процесс и переводит его в состояние "готовности к запуску".

forloop: for (i = first; i < NUMPROCS; i++) { if (i == procid) { semaphore.val[i] = 2; for (i = 1; i < NUMPROCS; i++) if (i != procid && semaphore.val[i] == 2) goto loop; lastid = procid; return; /* успешное завершение, ресурс /* можно использовать */ } else if (semaphore.val[i]) goto loop; } first = 1; goto forloop; } Vprim(semaphore) struct semaphore semaphore; { lastid = (procid + 1) % NUMPROCS; /* на следующий /* процессор */ semaphore.val[procid] = 0; }

<


Содержание  Назад  Вперед