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

         

Семафоры - часть 3


где id - дескриптор, возвращаемый функцией semget, oplist - указатель на список операций, count - размер списка. Возвращаемое функцией значение oldval является прежним значением семафора, над которым производилась операция. Каждый элемент списка операций имеет следующий формат:

  • номер семафора, идентифицирующий элемент массива семафоров, над которым выполняется операция,
  • код операции,
  • флаги.

#include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h>

#define SEMKEY 75 int semid; unsigned int count; /* определение структуры sembuf в файле sys/sem.h * struct sembuf { * unsigned shortsem_num; * short sem_op; * short sem_flg; }; */ struct sembuf psembuf,vsembuf; /* операции типа P и V */

main(argc,argv) int argc; char *argv[]; { int i,first,second; short initarray[2],outarray[2]; extern cleanup();

if (argc == 1) { for (i = 0; i < 20; i++) signal(i,cleanup); semid = semget(SEMKEY,2,0777IPC_CREAT); initarray[0] = initarray[1] = 1; semctl(semid,2,SETALL,initarray); semctl(semid,2,GETALL,outarray); printf("начальные значения семафоров %d %d\n", outarray[0],outarray[1]); pause(); /* приостанов до получения сигнала */ }

/* продолжение на следующей странице */

Рисунок 11.14. Операции установки и снятия блокировки

else if (argv[1][0] == 'a') { first = 0; second = 1; } else { first = 1; second = 0; }

semid = semget(SEMKEY,2,0777); psembuf.sem_op = -1; psembuf.sem_flg = SEM_UNDO; vsembuf.sem_op = 1; vsembuf.sem_flg = SEM_UNDO;

for (count = 0; ; count++) { psembuf.sem_num = first; semop(semid,&psembuf,1); psembuf.sem_num = second; semop(semid,&psembuf,1); printf("процесс %d счетчик %d\n",getpid(),count); vsembuf.sem_num = second; semop(semid,&vsembuf,1); vsembuf.sem_num = first; semop(semid,&vsembuf,1); } }

cleanup() { semctl(semid,2,IPC_RMID,0); exit(); }

Рисунок 11.14. Операции установки и снятия блокировки (продолжение)

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

алгоритм semop /* операции над семафором */ входная информация: (1) дескриптор семафора (2) список операций над семафором (3) количество элементов в списке выходная информация: исходное значение семафора { проверить корректность дескриптора семафора; start: считать список операций над семафором из простран- ства задачи в пространство ядра; проверить наличие разрешений на выполнение всех опера- ций;

для (каждой операции в списке) { если (код операции имеет положительное значение) { прибавить код операции к значению семафора; если (для данной операции установлен флаг UNDO) скорректировать структуру восстановления для данного процесса; вывести из состояния приостанова все процессы, ожидающие увеличения значения семафора; } в противном случае если (код операции имеет отрица- тельное значение) { если (код операции + значение семафора >= 0) { прибавить код операции к значению семафо- ра; если (флаг UNDO установлен) скорректировать структуру восстанов- ления для данного процесса; если (значение семафора равно 0) /* продолжение на следующей страни- * це */

<


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