СибГУТИ Лабораторная работа 3 Операционные системы скачать бесплатно
Задание
Написать программу, которая будет эмулировать параллельную работу некоторых потоков. Потоки должны работать циклически. В качестве модели использовать схему “производитель – потребитель”. Один поток (производитель) может помещать случайные (или какие-то определенные – например, только четные числа или квадраты целых чисел и т.п.) числа в буфер (массив заданного размера), для наглядности поток-производитель должен эти числа выводить на экран. Другой поток (потребитель) забирает числа из этого буфера. Для контроля также выполнять вывод на экран чисел, взятых потоком-потребителем из буфера. Вывод разными потоками выполнять в разные строки и/или разным цветом; дополнительно выводить на экран индикатор того, какой именно поток работает в настоящий момент, а также содержимое буфера и текущий процент его заполненности.
На экране параллельная работа потоков может быть представлена следующим образом:
Верхняя строка (производитель): ячейка для вывода текущего сгенерированного числа, признак активности потока (слово, символ, цвет), сообщение о переполнении буфера в случае этого события. Возможно, ещё какая-то полезная информация, например, номер заполняемой ячейки.
Нижняя (или вторая) строка (потребитель): ячейка для вывода текущего прочитанного числа, признак активности потока (слово, символ, цвет), сообщение о пустом буфере в случае этого события. Возможно, информация о номере считываемой из буфера ячейки.
В середине экрана: сам буфер, в который числа добавляются потоком-производителем и из которого считываются (удаляются или перекрашиваются, попадая при этом в его ячейку в нижней строке экрана) потоком-потребителем. Считывание чисел можно производить по принципу стека или очереди. При считывании по принципу очереди после завершения работы потребителя какое-то количество чисел из начала буфера исчезнет, следовательно, буфер будет перемещаться по экрану и в какой-то момент его потребуется переписать заново, от начала.
Отдельной строкой или в углу экрана отображать процент заполненности буфера.
Предусмотреть обработку критических ситуаций:
1) Случай, когда потребителю предоставлено управление, а буфер данных пуст – тогда активный поток должен напрямую отдать управление производителю, а сам уйти в режим ожидания. При этом вопрос с квантом времени для производителя может быть решён по-разному. Например, остаток недоработанного потребителем кванта может быть передан производителю, либо ему может быть выделен новый квант времени.
2) Случай, когда управление предоставлено производителю, а буфер полон и записывать результаты некуда – поток-производитель должен заблокироваться до появления свободного места в буфере и запустить поток-потребитель. Вопрос с квантом может решаться аналогично.
Для того чтобы было возможно пронаблюдать работу потоков в замедленном режиме, в каждом из потоков следует поставить дополнительную задержку (стандартный delay), величину которой задавать с клавиатуры при запуске программы, в качестве параметра командной строки. При запуске без параметров выводить сообщение примерного вида: “Программа запущена со стандартной задержкой, величина которой =…” и формат запуска программы для задания желаемой задержки.
Потоки при работе чередуются случайным образом; регламентировать их работу с помощью таймера (выделять каждому кванты времени, величина которых тоже случайна – в некотором диапазоне). При этом может складываться ситуация, что один и тот же поток несколько раз подряд получит управление. Таймер по окончании выделенного потоку кванта времени изменяет статус этого потока с активного на пассивный, в результате чего внутренний цикл этого потока должен завершиться.
Внутри обработчика прерываний таймера не может находиться вызовов процедур – потоков! Вызовы процедур должны происходить в бесконечном цикле в основной программе. В обработчик прерываний таймера вообще нельзя включать никакие действия, требующие длительного выполнения, например, вызовы циклических процедур, или процедур, работающих с графикой или с диском.
Для выхода из программы предусмотреть какую-то специальную клавишу или комбинацию клавиш (выбор по желанию программиста), информация о ней должна быть известна пользователю – помещена на экране. При нажатии этой клавиши происходит окончание работы потока-производителя, а поток-потребитель закончит свою работу, только когда буфер будет исчерпан, т.е. выработанная информация будет полностью использована.
Описание параметров программы
Программа принимает три или пять параметров:
1. величину задержки при работе потоков (от 0 до 32767). Задержка измеряется в миллисекундах.
2. количество потоков (от 2 до 10).
3. Функции потоков:
0 - определяются случайным образом;
1 - все потоки – производители;
2 - все потоки – потребители.
4. приоритет потока производителя (от 1 до 100. 100 – самый высокий приоритет).
5. приоритет потока потребителя (от 1 до 100. 100 – самый высокий приоритет).
Параметры должны быть целочисленного типа.
Описание переменных и подпрограмм
Impulses - счетчик импульсов.
curTh - номер текущего потока.
Esc - переменная определяет нажата ли клавиша ESC.
Del - задержка при работе потоков.
Th - массив для хранения типа каждого из потоков: 1 - производитель, 2 – потребитель.
thsNumber - количество потоков в программе.
thsFunc - Способ выбора функций потоков.
Buf - буфер.
bufSize - текущий размер буфера.
OldTimeHandler - переменная процедурного типа, которая необходима для запуска старой процедуры обработки прерывания таймера.
OldKeyHandler - переменная процедурного типа, которая необходима для запуска старой процедуры обработки прерывания клавиатуры.
ThY - функция возвращает координату Y для потока.
ShowBorder - Рисует рамку с заголовком.
ShowBuf - процедура показывает буфер.
Producer - процедура работы потока-производителя.
Consumer - процедура работы потока-потребителя.
TimeHandler - процедура, предназначенная для обработки прерывания таймера.
KeyHandler - процедура, предназначенная для обработки прерывания клавиатуры.
Init – Устанавливает начальные значения переменных и рисует рамки.
Алгоритм программы
1. Прием и анализ входных параметров;
2. Назначаются типы потоков (в заголовке окна для каждого типа потоков указывается в скобках количество потоков такого типа). Делается текущим первый поток. В бесконечном цикле определяется тип текущего потока и вызывается процедура его работы. Если пользователь нажимает клавишу ESC, то осуществляется выход из программы, при этом, если текущим потоком был потребитель, то ему дается возможность прочитать всю информацию из буфера, а если текущим потоком был производитель, то управление передается первому из потоков потребителей (если он имеется), чтобы он прочитал всю информацию из буфера.
3. При возникновении прерывания таймера вызывается процедура TimeHandler. В ней сначала уменьшается количество импульсов, оставшееся для работы текущего потока. Если поток отработал все положенное ему время, то случайным образом назначаются текущим новый поток. Количество импульсов для его работы назначается или случайным образом (если во входных параметрах не указаны приоритеты потоков), или исходя из приоритетов потоков (если во входных параметрах указаны их приоритеты).
4. При возникновении прерывания клавиатуры вызывается процедура KeyHandler. Если прерывание вызвано нажатием клавиши ESC, специальной переменной присваивается значение True. После этого вызывается старый обработчик прерывания клавиатуры.
5. В начале работы любого потока выводится информация о том, что он активный. Для производителя проверяется, не полон ли уже буфер. Если полон, то выдается соответствующее сообщение и текущим назначается другой поток. Иначе, в буфер заносится очередное число.
6. Для потребителя в начале его работы проверяется не пуст ли буфер. Если пуст, то выдается соответствующее сообщение и текущим назначается другой поток. Иначе, осуществляется чтение последнего числа из буфера (буфер реализован по принципу стека).
Текст программы
...
Копия экрана программы
Ответы на контрольные вопросы
1) Как поведет себя программа, если первым будет выбираться на выполнение поток-потребитель?
В этом случае программа выдаст сообщение, что буфер пуст, и передаст управление потоку-производителю.
2) Каким образом можно создать приоритет тому или другому потоку? Используя только датчик случайных чисел? Добавьте возможность задания приоритета в форме параметра командной строки.
Приоритет потоку-производителю можно указать в качестве 4-го параметра командной строки. Его значения от 1 до 100.
Приоритет потоку-потребителю можно указать в качестве 5-го параметра командной строки. Его значения от 1 до 100.
Если в качестве значений обоих приоритетов указаны нули, то активному потоку выделяется 20 + (случайное число от 0 до 99) импульсов таймера. Иначе, активному потоку выделяется 20 + (приоритет потока) импульсов таймера.
3) Возможно ли добавление в ту же программу новых потоков? Измените программу таким образом, чтобы можно было при ее запуске указывать требуемое количество потоков. При этом функции каждого потока определяются случайным образом. Т.е. может получиться несколько потребителей и один производитель, или наоборот… В крайней ситуации – все производители или все потребители. Как поведёт себя программа в подобном случае?
При запуске в командной строке в качестве второго параметра указывается требуемое количество потоков. Это количество может принимать значения от 2 до 10. При этом функции каждого потока определяются третьим параметром. В случае, если все потоки – производители, после заполнения ими буфера, будет просто осуществляться переключение между этими потоками с выдачей сообщения о заполненности буфера. В случае, если все потоки потребители, будет просто осуществляться переключение между ними с выдачей информации о пустоте буфера.