Операционные системы. Кручинин А.Ю. - 9 стр.

UptoLike

Составители: 

9
обозначения, поскольку тем, кто не знает датского языка, эти обозначения ничего не
говорят (да и тем, кто знает язык, говорят немного). Впервые обозначения down и up
появились в языке Algol 68.
Как показано в листинге 2, проблему потерянных сигналов запуска можно
решить с помощью семафоров. Очень важно, чтобы они были реализованы
неделимым образом. Стандартным способом является реализация операций down и
up в виде системных запросов, с запретом операционной системой всех прерываний
на период проверки семафора, изменения его значения и возможного перевода
процесса в состояние ожидания. Поскольку для выполнения всех этих действий
требуется всего лишь несколько команд процессора, запрет прерываний не приносит
никакого вреда. Если используются несколько процессоров, каждый семафор
необходимо защитить переменной блокировки с использованием команды TSL,
чтобы гарантировать одновременное обращение к семафору только одного
процессора. Необходимо понимать, что использование команды TSL
принципиально отличается от активного ожидания, при котором производитель или
потребитель ждут наполнения или опустошения буфера. Операция с семафором
займет несколько микросекунд, тогда как активное ожидание может затянуться на
существенно больший промежуток времени.
#define N 100 /* количество сегментов в буфере */
typedef int semaphore; /* семафоры - особый вид целочисленных переменных */
semaphore mutex = 1; /* контроль доступа в критическую область */
semaphore empty = N; /* число пустых сегментов буфера */
semaphore full = 0; /* число полных сегментов буфера */
void producer(void)
{
int item;
while (TRUE) { /* TRUE - константа, равная 1*/
item = produce_item(); /* создать данные, помещаемые в буфер */
down(&empty); /* уменьшить счетчик пустых сегментов буфера */
down(&mutex); /* вход в критическую область */
insert_item(item); /* поместить в буфер новый элемент */
up(&mutex); /* выход из критической области */
up(&full); /* увеличить счетчик полных сегментов буфера */
}
}
void consumer(void)
{
int item;
while (TRUE) { /* бесконечный цикл */
down(&full); /* уменьшить числа полных сегментов буфера */
down(&mutex); /* вход в критическую область */
item = remove_item(); /* удалить элемент из буфера */
up(&mutex); /* выход из критической области */
up(&empty); /* увеличить счетчик пустых сегментов буфера */
consume_item(item); /* обработка элемента */
}
}
Листинг 2 Проблема производителя и потребителя с семафорами
обозначения, поскольку тем, кто не знает датского языка, эти обозначения ничего не
говорят (да и тем, кто знает язык, говорят немного). Впервые обозначения down и up
появились в языке Algol 68.
      Как показано в листинге 2, проблему потерянных сигналов запуска можно
решить с помощью семафоров. Очень важно, чтобы они были реализованы
неделимым образом. Стандартным способом является реализация операций down и
up в виде системных запросов, с запретом операционной системой всех прерываний
на период проверки семафора, изменения его значения и возможного перевода
процесса в состояние ожидания. Поскольку для выполнения всех этих действий
требуется всего лишь несколько команд процессора, запрет прерываний не приносит
никакого вреда. Если используются несколько процессоров, каждый семафор
необходимо защитить переменной блокировки с использованием команды TSL,
чтобы гарантировать одновременное обращение к семафору только одного
процессора. Необходимо понимать, что использование команды TSL
принципиально отличается от активного ожидания, при котором производитель или
потребитель ждут наполнения или опустошения буфера. Операция с семафором
займет несколько микросекунд, тогда как активное ожидание может затянуться на
существенно больший промежуток времени.

#define N 100               /* количество сегментов в буфере */
typedef int semaphore;      /* семафоры - особый вид целочисленных переменных */
semaphore mutex = 1;        /* контроль доступа в критическую область */
semaphore empty = N;        /* число пустых сегментов буфера */
semaphore full = 0;         /* число полных сегментов буфера */
void producer(void)
{
  int item;
  while (TRUE) {            /* TRUE - константа, равная 1*/
     item = produce_item(); /* создать данные, помещаемые в буфер */
     down(&empty);          /* уменьшить счетчик пустых сегментов буфера */
     down(&mutex);          /* вход в критическую область */
     insert_item(item);     /* поместить в буфер новый элемент */
     up(&mutex);            /* выход из критической области */
     up(&full);             /* увеличить счетчик полных сегментов буфера */
  }
}
void consumer(void)
{
  int item;
  while (TRUE) {            /* бесконечный цикл */
     down(&full);           /* уменьшить числа полных сегментов буфера */
     down(&mutex);          /* вход в критическую область */
     item = remove_item(); /* удалить элемент из буфера */
     up(&mutex);            /* выход из критической области */
     up(&empty);            /* увеличить счетчик пустых сегментов буфера */
     consume_item(item); /* обработка элемента */
  }
}
          Листинг 2 – Проблема производителя и потребителя с семафорами
                                                                                   9