3121

Написание программы реализующей параллельную работу нескольких процессов

Курсовая

Информатика, кибернетика и программирование

Необходимо написать программу, реализующую параллельную работу нескольких процессов. Каждый процесс может состоять из одного или нескольких потоков. Любой из потоков, работающих в составе этих процессов, может быть приостановлен и вновь запущен неко...

Русский

2012-10-24

121.5 KB

18 чел.

Необходимо написать программу, реализующую параллельную работу нескольких процессов. Каждый процесс может состоять из одного или нескольких потоков. Любой из потоков, работающих в составе этих процессов, может быть приостановлен и вновь запущен некоторой определенной клавишей (можно использовать буквенные или цифровые клавиши). Нажатия клавиш обрабатывать с помощью прерывания от клавиатуры (по материалам лаб. работы №1).

Окончание работы программы должно происходить при приостановке всех потоков их ключевыми клавишами либо при нажатии клавиши ESC. При окончании работы необходимо выполнить корректное завершение, т.е. “дочитать” всю информацию из буфера каждого процесса (при его наличии), закрыть все открытые файлы и т.п. – по материалам лаб. работы №4.

Те потоки, которые выводят информацию на экран, должны использовать для этого каждый свое отдельное окно, обрамленное рамкой – экран визуально делится на несколько окон, в каждом из которых отображается один процесс.

Дополнительное информационное окно должно содержать описание управляющих клавиш и краткое сообщение о тех действиях, которые выполняются в программе: номер потока, его статус в текущий момент времени (активен, приостановлен, ожидает), другую информацию (указание величины выделенного потоку кванта времени, процент заполненности буфера и т.п.) в зависимости от конкретного потока.

Программа должна работать устойчиво, без “зависаний” и непредвиденных зрительных эффектов. В случае необходимости указания параметров при запуске программы необходимо предусмотреть и обработать все возможные ошибки (с выводом диагностики на экран).

Задачи 1, 3, 6 предполагают наличие управляющего блока, который, используя прерывания таймера, случайным образом определяет очередной активный поток и выделяет ему кванты времени (возможно, в рамках большего кванта, выделенного всему процессу). Кванты времени – как для процесса в целом, так и для его потоков – изначально задавать некоторой фиксированной величины, но предусмотреть возможность её изменения во время работы путем нажатия некоторых ключевых клавиш (для каждого из потоков предусмотреть свою клавишу) – т.е. можно, например, увеличить или уменьшить квант только потока-пpоизводителя. При этом допустимы разные варианты реализации – “общий” квант может либо меняться, либо оставаться постоянным (тогда при ускорении одного потока другой автоматически замедлится, т.к. величина его кванта уменьшится).

Потоки этого класса задач могут иметь три статуса: “активен”, “ожидает” или “приостановлен”. В процессе работы может возникнуть, например, следующая ситуация. Поток-потребитель приостановлен своей ключевой клавишей, следовательно, буфер не освобождается. Поток-производитель активен, он заполнит буфер информацией и перейдёт в состояние ожидания. Из этого состояния он сможет выйти только после того, как будет возобновлена (нажатием клавиши) работа потока-потребителя, который освободит место в буфере для помещения новой информации. В случае приостановки производителя возникнет аналогичная ситуация, только с пустым буфером. Приостановка/возобновление потока возможны в любом его состоянии – как в активном, так и в состоянии ожидания.

Задачи 2, 4, 5, 7 должны выполняться равномерно, независимо от степени загрузки системы. Для этого каждой из них необходимо получать управление через фиксированное количество “тиков” системного таймера, во время которого они выполнят какое-то свое элементарное действие (“бегущая строка” или “летающий объект” сместится на одну позицию, сменится нота в музыке…). При такой реализации скорость каждого потока будет определяться количеством “тиков” таймера между его запусками. Для уменьшения скорости такого потока достаточно после нажатия ключевой клавиши предоставлять ему управление реже, через большее число “тиков”, соответственно для ускорения такого потока – опять же после нажатия ключевой клавиши – ему предоставляется управление чаще, в пределе – на каждом “тике”. Так, “бегущая строка” должна двигаться равномерно с постоянной скоростью (если она не приостановлена ключевой клавишей) независимо от количества активных процессов в системе, музыка – тоже играть равномерно… Потоки этого класса задач могут иметь два статуса: “активен” и “приостановлен”.

Задания:

3. Два потока: один выполняет поиск всех последовательных простых чисел и заносит их в буфер, второй осуществляет их вывод из буфера на экран (по материалам лаб. работы №4).

4. Вывод заголовка работы (фамилия и имя автора, название работы) постоянно меняющегося цвета. Место вывода (верхняя или нижняя строка), задавать в качестве параметра командной строки.

6. Два потока: один генерирует случайные числа и выбирает в буфер те, которые являются полным квадратом, второй – выводит их из буфера на экран (по материалам лаб. раб. №4).

7. Движущийся объект (в простейшем случае, например, летающий и отражающийся от границ шарик). Движение может осуществляться свободно или при управлении с клавиатуры (по материалам лаб. работы №5).
Параметры командной строки.

Программа принимает один параметр – положение заголовка (a – вверху, b – внизу).

Описание основных алгоритмов, используемых в программе.

Вывод заголовка и летающий квадрат реализованы как фоновые процессы. Изменяют свой вид эти объекты благодаря генератору случайных чисел.

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

Для поиска простых чисел используется следующий алгоритм. Берем число из переменной Num (изначально там записана единица) и прибавляем к нему единицу до тех пор, пока оно не станет простым. Для проверки на простоту числа используется отдельная булева функция PrimeNumber. Найденное число заносится в буфер. Проверка на наличие свободного места в буфере находится в начале процедуры, поэтому, если в буфере нет свободного места, то поток переходит в состояние ожидания и новых простых чисел не ищет. Любое простое число, помещенное в буфер, не превосходит константы MaxLongint. Поиск простых чисел продолжается до тех пор, пока не истечет время, отведенное на работу данного потока. Поток печати простых чисел проверяет буфер на пустоту и, если буфер не пуст, то извлекает первое число из буфера и выводит его на экран. Если буфер пуст, то поток переходит в режим ожидания.

Описание основных переменных, констант и типов.

В программе для фиксирования состояний (статусов) процессов и потоков определён следующий тип:

type Status = (Assigned, Wait, Suspended);

Константы.

Title – текст заголовока;

TitleRefresh –  период смены цвета заголовка;

Buf1Len – размер буфера первого процесса;

Buf2Len – размер буфера второго процесса;

Delay1 – задержка для первого процесса;

Delay2 – задержка для второго процесса;

StrLen – длина строки окна вывода;

Kill – флаг завершения программы;

SquareRefresh – период движения квадрата;

TPos – положение заголовка.

Переменные.

OldTHandler, OldKHandler – старые обработчики прерываний;

Scr – массив для прямого доступа к видеопамяти;

T, T1, T2 – счётчики времени таймер;

Thread – состояния потоков;

Buf1 – буфер первого процесса;

Buf2 – буфер второго процесса;

Top1, Top2 – вершины буферов;

Time – дополнительные времена для потоков;

CurThread – номер текущего активного потока;

X1, Y1, X2, Y2 – координаты экрана для вывода сгенерированных чисел;

SX, SY – координаты квадрата;

dx, dy – «направляющие» квадрата;

tmp_symbol, tmp_attr – перекрытая квадратом часть экрана;

Num – полученное простое число.

Описание подпрограмм.

Print – процедура вывода строки на экран;

Fly – процедура сдвига летающего квадрата;

THandler – обработчик прерываний таймера;

PrintStatus – вывод на экран состояния заданного потока;

ChangeStatus – изменение состояния заданного потока;

Prod1, Cons1, Prod2, Cons2 – процедуры потоков потребителей и производителей;

PrimeNumber – функция проверки числа на простоту;

KHandler – обработчик прерываний клавиатуры;

SetCurSize – процедура изменения размера курсора;

Initialize – инициализирует основные переменные;

KillProc – процедура завершения работы программы.

Работа программы (снимок экрана).


Исходный код программы.

program solution;

{$M $1024, 0, 0}

uses

 Crt, Dos;

type

 Status = (Active, Waits, Suspended); { Состояния потока }

const

 Title = 'Заголовок'; { Текст заголовка }

 TitleRefresh = 10;  { Период смены цвета заголовка   }

 Buf1Len = 13;       { Размер буфера первого процесса }

 Buf2Len = 13;       { Размер буфера второго процесса }

 Delay1 = 10000;     { Задержка для первого процесса  }

 Delay2 = 10000;     { Задержка для второго процесса  }

 StrLen = 39;        { Длина строки окна вывода       }

 Kill: Boolean = False; { Флаг завершения программы   }

 SquareRefresh = 2;  { Период движения квадрата       }

 TPos: Byte = 1;

var

 OldTHandler, OldKHandler: Procedure; { Старые обработчики прерываний }

 Scr: Array[1..25, 1..80] of Record   { Массив для прямого доступа к видеопамяти }

   Symbol: Char;

   Attr: Byte;

 end Absolute $B800:$0000;

 T, T1, T2: Word;      { Счётчики времени таймера }

 Thread: Array[1..6] of Status;    { Состояния потоков }

 Buf1: Array[1..Buf1Len] of Word;  { Буфер первого процесса }

 Buf2: Array[1..Buf2Len] of Longint; { Буфер второго процесса }

 Top1, Top2: Word;                          { Вершины буферов }

 Time: Array[1..4] of Byte;  { Дополнительные времена для потоков }

 CurThread: Byte;            { Номер текущего активного потока    }

 X1, Y1, X2, Y2: Byte; { Координаты экрана для вывода сгенерированных чисел }

 F: Text;         { Файл с текстом }

 SX, SY: Byte;    { Координаты квадрата     }

 dx, dy: Integer; { "Направляющие" квадрата }

 tmp_symbol: Array[0..1, 0..1] of Char; { Перекрытая квадратом часть экрана }

 tmp_attr: Array[0..1, 0..1] of Byte;

 Num: Longint;

{ Вывод строки S на экран начиная с i-го столбца, j-й строки цветом Color }

procedure Print(const S: String; const i, j: Byte; const Color: Byte);

var

 k: Integer;

begin

 if i + Length(S) - 1 > 80 then Exit;

 for k := i to i + Length(S) - 1 do begin

   Scr[j, k].Attr := Color;

   Scr[j, k].Symbol := S[k - i + 1];

 end;

end;

{ Сдвигает летающий квадрат }

procedure Fly;

var

 i, j: Integer;

begin

 while (SX + dx > 64) or (SX + dx < 45) or (SY + dy > 22) or (SY + dy < 3) do

 begin

   case Random(4) of

     0: dx := -1;

     1: dx := 1;

     2: dx := 2;

     3: dx := -2;

   end;

   case Random(4) of

     0: dy := -1;

     1: dy := 1;

     2: dy := 2;

     3: dy := -2;

   end;

 end;

 for i := 0 to 1 do

   for j := 0 to 1 do

   begin

     Scr[SY + j, SX + i].Attr := tmp_attr[j, i];

     Scr[SY + j, SX + i].Symbol := tmp_symbol[j, i];

   end;

 SX := SX + dx;

 SY := SY + dy;

 for i := 0 to 1 do

   for j := 0 to 1 do

   begin

     tmp_attr[j, i] := Scr[SY + j, SX + i].Attr;

     tmp_symbol[j, i] := Scr[SY + j, SX + i].Symbol;

   end;

 for i := 0 to 1 do

   for j := 0 to 1 do

   begin

     Scr[SY + j, SX + i].Attr := LightGreen;

     Scr[SY + j, SX + i].Symbol := Chr(219);

   end;

end;

{ Обработчик прерываний системного таймера }

{$F+}

procedure THandler; Interrupt;

begin

 if Thread[1] = Active then begin

   Inc(T1);

   if T1 >= TitleRefresh then begin

     Print(Title, 40 - Length(Title) div 2, TPos, 1 + Random(15));

     T1 := 0;

   end;

 end;

 if Thread[2] = Active then begin

   Inc(T2);

   if T2 >= SquareRefresh then begin

     Fly;

     T2 := 0;

   end;

 end;

 Inc(T);

 Inline($9C);

 OldTHandler;

end;

{$F-}

{ Вывод на экран состояния i-го потока }

procedure PrintStatus(const i: Byte);

var

 _Y: Byte;

begin

 case Thread[i] of

   Active: Print('Активен    ', 66, 3 + i, LightGreen);

   Waits: Print('Ожидание   ', 66, 3 + i, Yellow);

   Suspended: Print('Остановлен ', 66, 3 + i, LightRed);

 end;

end;

{ Изменение состояния i-го потока }

procedure ChangeStatus(const i: Byte);

begin

 case i of

   1:

   begin

     if Thread[1] = Active then begin

       Thread[1] := Suspended;

       NoSound;

     end

     else

       Thread[1] := Active;

     PrintStatus(1);

   end;

   2:

   begin

     if Thread[2] = Active then Thread[2] := Suspended else Thread[2] := Active;

     PrintStatus(2);

   end;

   3:

   begin

     if Thread[3] <> Suspended then

       Thread[3] := Suspended

     else

       if CurThread = 0 then Thread[3] := Active else Thread[3] := Waits;

     PrintStatus(3);

   end;

   4:

   begin

     if Thread[4] <> Suspended then

       Thread[4] := Suspended

     else

       if CurThread = 1 then Thread[4] := Active else Thread[4] := Waits;

     PrintStatus(4);

   end;

   5:

   begin

     if Thread[5] <> Suspended then

       Thread[5] := Suspended

     else

       if CurThread = 2 then Thread[5] := Active else Thread[5] := Waits;

     PrintStatus(5);

   end;

   6:

   begin

     if Thread[6] <> Suspended then

       Thread[6] := Suspended

     else

       if CurThread = 3 then Thread[6] := Active else Thread[6] := Waits;

     PrintStatus(6);

   end;

 end;

end;

{ Поток-производитель первого процесса (генерация чисел) }

procedure Prod1(const TMax: Byte);

var

 Z: String[5];

 Num: Word;

begin

 if Thread[3] = Suspended then Exit;

 if (Thread[3] = Waits) and (Top1 <> Buf1Len) then Thread[3] := Active;

 if Thread[3] = Active then begin

   Print('   ', 66, 11, White);

   Str(TMax, Z);

   Print(Z, 66, 11, White);

 end;

 PrintStatus(3);

 T := 0;

 while (T <= TMax + Time[1]) and (Thread[3] <> Suspended) do begin

   if Top1 = Buf1Len then begin

     Thread[3] := Waits;

     PrintStatus(3);

     Break;

   end;

   repeat

     Num := Random(6000);

   until Frac(Sqrt(Num)) < 1e-6;

   Inc(Top1);

   Buf1[Top1] := Num;

   Str(Top1 / Buf1Len * 100:2:2, Z);

   Print(Z + ' %   ', 66, 16, White);

   Delay(Delay1);

 end;

 if Thread[3] = Active then Print('Время вышло', 66, 6, LightGray);

 Print(' - ', 66, 11, White);

end;

{ Поток-потребитель первого процесса }

procedure Cons1(const TMax: Byte);

var

 i, j: Integer;

 S: String;

begin

 if Thread[4] = Suspended then Exit;

 if (Thread[4] = Waits) and (Top1 <> 0) then Thread[4] := Active;

 if Thread[4] = Active then begin

   Print('   ', 66, 12, White);

   Str(TMax, S);

   Print(S, 66, 12, White);

 end;

 PrintStatus(4);

 T := 0;

 while (T <= TMax + Time[2]) and (Thread[4] <> Suspended) do begin

   if Top1 = 0 then begin

     Thread[4] := Waits;

     PrintStatus(4);

     Break;

   end;

   Str(Buf1[1]: 4, S);

   if X1 + Length(S) > StrLen then begin

     X1 := 0;

     if Y1 = 8 then begin

       for i := 3 to 10 do

         for j := 3 to 41 do

           Scr[i, j].Symbol := Scr[i + 1, j].Symbol;

       for j := 3 to 41 do

         Scr[11, j].Symbol := ' ';

     end

     else Inc(Y1);

   end;

   Print(S, 3 + X1, 3 + Y1, White);

   Inc(X1, Length(S) + 2);

   Dec(Top1);

   for i := 1 to Top1 do

     Buf1[i] := Buf1[i + 1];

   Str(Top1 / Buf1Len * 100:2:2, S);

   Print(S + ' %   ', 66, 16, White);

   Delay(Delay1);

 end;

 if Thread[4] = Active then Print('Время вышло', 66, 7, LightGray);

 Print(' - ', 66, 12, White);

end;

{ Возвращает True, если число x - простое }

function PrimeNumber(const x: Longint): Boolean;

var

 i: Integer;

 u: Longint;

begin

 PrimeNumber := False;

 if x <= 1 then Exit;

 for i := 2 to Trunc(Sqrt(x)) do

   if x mod i = 0 then Exit;

 PrimeNumber := True;

end;

{ Поток-производитель второго процесса (текс из файла) }

procedure Prod2(const TMax: Byte);

var

 i: Integer;

 c: Char;

 Z: String[8];

begin

 if Thread[5] = Suspended then Exit;

 if (Thread[5] = Waits) and (Top2 <> Buf2Len) then Thread[5] := Active;

 if Thread[5] = Active then begin

   Print('   ', 66, 13, White);

   Str(TMax, Z);

   Print(Z, 66, 13, White);

 end;

 PrintStatus(5);

 T := 0;

 while (T <= TMax + Time[3]) and (Thread[5] <> Suspended) do begin

   if Top2 = Buf2Len then begin

     Thread[5] := Waits;

     PrintStatus(5);

     Break;

   end;

   repeat

     Inc(Num);

   until PrimeNumber(Num) or (Num = MaxLongint);

   if Num = MaxLongint then Num := 2;

   Inc(Top2);

   Buf2[Top2] := Num;

   Str(Top2 / Buf2Len * 100:2:2, Z);

   Print(Z + ' %   ', 66, 17, White);

   Delay(Delay2);

 end;

 if Thread[5] = Active then Print('Время вышло' , 66, 8, LightGray);

 Print(' - ', 66, 13, White);

end;

{ Поток-потребитель второго процесса }

procedure Cons2(const TMax: Byte);

var

 i, j: Integer;

 Z: String[8];

 S: String;

begin

 if Thread[6] = Suspended then Exit;

 if (Thread[6] = Waits) and (Top2 <> 0) then Thread[6] := Active;

 if Thread[6] = Active then begin

   Print('   ', 66, 14, White);

   Str(TMax, Z);

   Print(Z, 66, 14, White);

 end;

 PrintStatus(6);

 T := 0;

 while (T <= TMax + Time[4]) and (Thread[6] <> Suspended) do begin

   if Top2 = 0 then begin

     Thread[6] := Waits;

     PrintStatus(6);

     Break;

   end;

   Str(Buf2[1]:10, S);

   if X2 + Length(S) > StrLen then begin

     X2 := 0;

     if Y2 = 10 then begin

       for i := 13 to 22 do

         for j := 3 to 41 do

           Scr[i, j].Symbol := Scr[i + 1, j].Symbol;

       for j := 3 to 41 do

         Scr[23, j].Symbol := ' ';

     end

     else Inc(Y2);

   end;

   Print(S, 3 + X2, 13 + Y2, White);

   Inc(X2, Length(S) + 2);

   Dec(Top2);

   for i := 1 to Top2 do

     Buf2[i] := Buf2[i + 1];

   Str(Top2 / Buf2Len * 100:2:2, Z);

   Print(Z + ' %   ', 66, 17, White);

   Delay(Delay2);

 end;

 if Thread[6] = Active then Print('Время вышло', 66, 8, LightGray);

 Print(' - ', 66, 14, White);

end;

{ Обработчик прерываний клавиатуры }

{$F+}

procedure KHandler; Interrupt;

var

 Local_Time: String[5];

begin

 case Port[$60] of

   1:  Kill := True;                    { нажата Esc }

   2:  if Time[1] > 0  then Dec(Time[1]);   { нажата 1 }

   3:  if Time[1] < 90 then Inc(Time[1]);   {        2 }

   4:  if Time[2] > 0  then Dec(Time[2]);   {        3 }

   5:  if Time[2] < 90 then Inc(Time[2]);   {        4 }

   6:  if Time[3] > 0  then Dec(Time[3]);   {        5 }

   7:  if Time[3] < 90 then Inc(Time[3]);   {        6 }

   8:  if Time[4] > 0  then Dec(Time[4]);   {        7 }

   9:  if Time[4] < 90 then Inc(Time[4]);   {        8 }

   59: ChangeStatus(1); { нажата F1 }

   60: ChangeStatus(2); {        F2 }

   61: ChangeStatus(3); {        F3 }

   62: ChangeStatus(4); {        F4 }

   63: ChangeStatus(5); {        F5 }

   64: ChangeStatus(6); {        F6 }

 end;

 Print('      ', 69, 11, White);

 Print('      ', 69, 12, White);

 Print('      ', 69, 13, White);

 Print('      ', 69, 14, White);

 Str(Time[1], Local_Time);

 Print(' + ' + Local_Time, 69, 11, White);

 Str(Time[2], Local_Time);

 Print(' + ' + Local_Time, 69, 12, White);

 Str(Time[3], Local_Time);

 Print(' + ' + Local_Time, 69, 13, White);

 Str(Time[4], Local_Time);

 Print(' + ' + Local_Time, 69, 14, White);

 Inline($9C);

 OldKHandler;

end;

{$F-}

{ Изменение размера курсора }

procedure SetCurSize(const BegLine, EndLine: Byte);

var

 Regs: Registers;

begin

 with Regs do begin

   AH := $01;

   CH := BegLine;

   CL := EndLine;

 end;

 Intr($10, Regs);

end;

{ Инициализация основных переменных }

procedure Initialize;

var

 i, j: Integer;

begin

 T1 := 0;

 T2 := 0;

 Top1 := 0;

 Top2 := 0;

 SetCurSize($20, $00);

 for i := 1 to 6 do

   Thread[i] := Active;

 for i := 1 to 4 do

   Time[i] := 0;

 PrintStatus(1);

 PrintStatus(2);

 Print('Не запущен', 66, 6, LightGray);

 Print('Не запущен', 66, 7, LightGray);

 Print('Не запущен', 66, 8, LightGray);

 Print('Не запущен', 66, 9, LightGray);

 Print('0.00 %', 66, 16, White);

 Print('0.00 %', 66, 17, White);

 Print('    + 0', 66, 11, White);

 Print('    + 0', 66, 12, White);

 Print('    + 0', 66, 13, White);

 Print('    + 0', 66, 14, White);

 X1 := 0;

 Y1 := 0;

 X2 := 0;

 Y2 := 0;

 Num := 1;

 dx := -1;

 dy := 1;

 SX := 50;

 SY := 3;

 for i := 0 to 1 do

   for j := 0 to 1 do begin

     tmp_attr[j, i] := Scr[SY + j, SX + i].Attr;

     tmp_symbol[j, i] := Scr[SY + j, SX + i].Symbol;

   end;

 GetIntVec($9, @OldKHandler);

 SetIntVec($9, Addr(KHandler));

 GetIntVec($8, @OldTHandler);

 SetIntVec($8, Addr(THandler));

end;

{ Действия при завершении работы программы }

procedure KillProc;

begin

 Thread[3] := Suspended;

 Thread[4] := Active;

 Thread[5] := Suspended;

 Thread[6] := Active;

 T := High(T);

 CurThread := 1;

 while (Top1 <> 0) or (Top2 <> 0) do begin

   T := 0;

   case Random(2) of

     0: Cons1(1 + Random(10));

     1: Cons2(1 + Random(10));

   end;

 end;

 SetIntVec($9, Addr(OldKHandler));

 SetIntVec($8, Addr(OldTHandler));

 Window(1, 1, 80, 25);

 GotoXY(1, 25);

 SetCurSize($06, $07);

 Halt(0);

end;

var

 v: String;

begin

 v := ParamStr(1);

 if (ParamCount = 0) or not ((Upcase(v[1]) = 'A') or (Upcase(v[1]) = 'B')) then begin

   WriteLn('Неправильно задано положение заголовка.');

   WriteLn('Формат:');

   WriteLn('имя_файла Pos');

   WriteLn('где Pos - положение заголовка (a - вверху, b - внизу).');

   ReadLn;

   Halt;

 end;

 if Upcase(v[1]) = 'B' then TPos := 25;

 TextBackground(Black);

 ClrScr;

 Window(2, 2, 42, 24);

 TextBackground(White);

 ClrScr;

 TextColor(Black);

 GotoXY(17, 1);

 Write('Процесс 1');

 Window(3, 3, 41, 23);

 TextBackground(Black);

 ClrScr;

 Window(2, 12, 42, 12);

 TextBackground(White);

 ClrScr;

 TextColor(Black);

 GotoXY(17, 1);

 Write('Процесс 2');

 Window(44, 2, 79, 24);

 TextBackground(White);

 ClrScr;

 GotoXY(14, 1);

 Write('Управление');

 Window(45, 3, 78, 23);

 TextBackground(Black);

 ClrScr;

 Window(45, 3, 78, 3);

 TextBackground(3);

 ClrScr;

 TextColor(White);

 GotoXY(8, 1);

 Write('Изменение состояний');

 Window(45, 4, 78, 9);

 TextBackground(Black);

 ClrScr;

 TextColor(White);

 WriteLn('F1 Заголовок       :');

 WriteLn('F2 Летающий квадрат:');

 WriteLn('F3 Производитель 1 :');

 WriteLn('F4 Потребитель   1 :');

 WriteLn('F5 Производитель 2 :');

 Write('F6 Потребитель   2 :');

 Window(45, 10, 78, 10);

 TextBackground(3);

 ClrScr;

 GotoXY(4, 1);

 Write('Время  <уменьшить>/<добавить>');

 Window(45, 11, 78, 14);

 TextBackground(Black);

 ClrScr;

 WriteLn('1/2 Производитель 1:');

 WriteLn('3/4 Потребитель   1:');

 WriteLn('5/6 Производитель 2:');

 Write('7/8 Потребитель   2:');

 Window(45, 15, 78, 15);

 TextBackground(3);

 ClrScr;

 GotoXY(7, 1);

 Write('Статистические данные');

 Window(45, 16, 78, 17);

 TextBackground(Black);

 ClrScr;

 WriteLn('Буфер 1 заполнен на:');

 Write('Буфер 2 заполнен на:');

 Window(45, 18, 78, 18);

 TextBackground(3);

 ClrScr;

 Window(45, 19, 78, 23);

 TextBackground(Black);

 ClrScr;

 GotoXY(1, 5);

 Write('Esc - выход');

 Initialize;

 Randomize;

 while True do begin

   if Kill then KillProc;

   CurThread := Random(4);

   case CurThread of

     0: Prod1(10 + Random(10));

     1: Cons1(10 + Random(10));

     2: Prod2(10 + Random(10));

     3: Cons2(10 + Random(10));

   end;

 end;

end.


 

А также другие работы, которые могут Вас заинтересовать

20356. СТАБИЛИЗАЦИЯ ДИСКРЕТНОГО МНОЖЕСТВА ЧАСТОТ 105 KB
  Автоматическая подстройка частоты 15. Частотная автоподстройка частоты 15. Фазовая автоподстройка частоты 15. Основными параметрами синтезатора являются: диапазон частот выходного сигнала количество N и шаг сетки частот fш долговременная и кратковременная нестабильность частоты уровень побочных составляющих в выходном сигнале и время перехода с одной частоты на другую.
20357. ДИОДНЫЕ СВЧ АВТОГЕНЕРАТОРЫ И УСИЛИТЕЛИ 98 KB
  ДИОДНЫЕ СВЧ АВТОГЕНЕРАТОРЫ И УСИЛИТЕЛИ 16. Физические основы работы генераторных СВЧ диодов 16. СВЧ диодные автогенераторы 16. СВЧ диодные генераторы с внешним возбуждением 16.
20358. ПОЛУПРОВОДНИКОВЫЕ УМНОЖИТЕЛИ ЧАСТОТЫ 47.5 KB
  ПОЛУПРОВОДНИКОВЫЕ УМНОЖИТЕЛИ ЧАСТОТЫ 17. Транзисторный умножитель частоты 17. Диодные умножители частоты 17. Назначение принцип действия и основные параметры Умножители частоты в структурной схеме радиопередатчика см.
20359. СУММИРОВАНИЕ МОЩНОСТЕЙ СИГНАЛОВ СВЧ ГЕНЕРАТОРОВ 95.5 KB
  СУММИРОВАНИЕ МОЩНОСТЕЙ СИГНАЛОВ СВЧ ГЕНЕРАТОРОВ 18. Способы суммирования мощностей сигналов 18. Суммирование мощностей сигналов с помощью многополюсной схемы 18. Суммирование мощностей сигналов с помощью ФАР 18.
20360. АМПЛИТУДНАЯ МОДУЛЯЦИЯ 94.5 KB
  Виды модуляции 19. Виды модуляции Модуляцией называется процесс управления одним или несколькими параметрами колебаний высокой частоты в соответствии с законом передаваемого сообщения. Классифицировать методы модуляции можно по трем признакам в зависимости: – от управляемого параметра высокочастотного сигнала: амплитудная AM частотная ЧМ и фазовая ФМ; – числа ступеней модуляции: одно двух трехступенчатая; – вида передаваемого сообщения – аналогового цифрового или импульсного непрерывная со скачкообразным изменением...
20361. Однополосная АМПЛИТУДНАЯ МОДУЛЯЦИЯ 54 KB
  Нелинейные искажения сигнала при амплитудной модуляции. Структура ОБП сигнала 20. Усиление ОБП сигнала в двухканалыюм усилителе 20. Формирование ОБП сигнала 20.
20362. ЧАСТОТНАЯ И ФАЗОВАЯ МОДУЛЯЦИЯ 111 KB
  Спектр сигнала при частотной и фазовой модуляции. Основные определения Поскольку мгновенная частота t с фазой t сигнала связана соотношением: 21. При частотной модуляции ЧМ мгновенная частота сигнала изменяется по закону модулирующего сигнала при фазовой ФМ фаза.7 следует что при частоте модулирующего сигнала =const отличить ЧМ от ФМ не представляется возможным.
20363. ЧАСТОТНАЯ И ФАЗОВАЯ МОДУЛЯЦИЯ дискретных сообщений 63.5 KB
  Частотная и фазовая модуляция дискретных сообщений При передаче дискретной в том числе цифровой кодированной информации комбинации двоичных сигналов состоящей из логических 1 и 0 модуляцию называют манипуляцией сигнала а устройство реализующее данный процесс как модулятором так и манипулятором. Три названных способа манипуляции ВЧ сигнала имеют разный уровень помехоустойчивости определяемой как вероятность ошибки принятого символа на выходе приемника от соотношения мощностей полезного сигнала и белого шума на входе демодулятора.1...
20364. ИМПУЛЬСНАЯ МОДУЛЯЦИЯ 116.5 KB
  Излучаемый РПДУ сигнал модулированный последовательностью прямоугольных импульсов показан на рис. Рис. При периодической последовательности прямоугольных импульсов рис.l где Е амплитуда импульса рис.