Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Zemskov_my_sppo1

.pdf
Скачиваний:
33
Добавлен:
18.04.2015
Размер:
595.32 Кб
Скачать

Ю.В. Земсков. Системное и прикладное программное обеспечение. Конспект лекций, варианты заданий и методические указания в лабораторным работам. ВГИ ВолГУ, 2002 г.

4.Реализация многозадачности на однопроцессорных архитектурах

Люди, которым всегда некогда, обычно ничего не делают.

Лихтенберг

4.1.Основные понятия

Внекоторых ОС управление вычислениями осуществляется на уровне процессов (например, в Unix), в других — на уровне потоков (как, например, в Windows). Поэтому в данном разделе будем использовать общий термин «задача» («задание»).

ОС выполняет следующие функции, связанные с управлением задачами:

1)создание и удаление задач;

2)планирование и диспетчеризация задач;

3)синхронизация задач и обеспечение взаимодействия между ними.

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

Обычно разделяют долгосрочное и краткосрочное планирование (short-term scheduling). Последнее часто называют диспетчеризацией. В пакетных ОС долгосрочное планирование было связано с выбором пакета задач, запускаемых для одновременного выполнения, а краткосрочное — с выбором конкретной задачи, которая должна выполняться в данный момент на данном (или единственном) процессоре.

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

Существующие дисциплины диспетчеризации могут быть разбиты на два класса: 1) вытесняющие

(preemptive) и 2) невытесняющие (кооперативные, non-preemptive). В первых версиях Windows и других старых ОС использовалась кооперативная многозадачность, когда сами задачи должны были достаточно часто (например, при выполнении операций ввода-вывода) передавать управление ядру системы, чтобы оно имело возможность переключиться на другую задачу. Таким образом, при невытесняющем планировании любая задача могла заблокировать другие. В большинстве современных ОС (Windows, Linux, OS/2) реализована вытесняющая многозадачность, когда процесс переключения полностью прозрачен для прикладных задач и осуществляется специальным планировщиком (scheduler), который может сам «отбирать» у них процессорное время.

Различают также приоритетное и бесприоритетное планирование. В первом случае учитывается важность каждой задачи (менее важным приходится дольше ждать в очереди) или время её выполнения (в первую очередь выбираются короткие задачи); во втором случае выбор очередной задачи для выполнения производится в некотором заранее установленном порядке без учёта важности задач и времени их выполнения.

4.2. Граф состояний задачи

На рис. 4.1 приведён граф состояний задачи. Новая задача (состояние New — новая) загружа-

ется в оперативную память для выполнения (состояние Ready — готовность). Планировщик операционной системы (диспетчер задач) выбирает по определённому алгоритму очередную задачу из очереди готовых задач и запускает её выполнение (состояние Running — выполнение активной в настоящее время задачи).

По истечении кванта времени, отведённого данной задаче диспетчером (если имеется в виду вытесняющий алгоритм планирования с квантованием), задача приостанавливается и опять попадает в очередь готовых задач (переход Timeout в состояние Ready). Если в состояние готовности перешла какаялибо задача с большим´ приоритетом (при использовании алгоритмов планирования, основанных на абсолютных приоритетах), то активная задача также переводится в состояние готовности, вытесняясь этой более приоритетной задачей.

Если задача, начав операцию обращения к какому-либо ресурсу, ожидает её завершения или освобождения ресурса, то она переходит в состояние Blocked (заблокирована); после освобождения ресур-

23

Ю. В. Земсков. Системное и прикладное программное обеспечение. Конспект лекций, варианты заданий и методические указания в лабораторным работам. ВГИ ВолГУ, 2002 г.

Admit

 

Dispatch-

 

Release

New

- Ready

Running

- Exit

 

6

Timeout

 

 

Event

Occurs Event

=Wait

Blocked

Рис. 4.1. Граф состояний задачи

са задача снова попадает в очередь готовых задач (переход Event Occurs в состояние Ready).

Наконец, закончив своё выполнение (или в результате фатальной ошибки), задача выгружается из памяти (состояние Exit).

4.3. Планирование в порядке очереди

Самой простой в реализации является дисциплина FCFS (first come — first served), согласно которой задачи обслуживаются в порядке очереди («первым пришёл — первым обслужен»)1. При этом либо используется одна общая очередь для всех процессов, в конец которой они попадают при переходе в состояние готовности к выполнению, либо используются две очереди: 1) очередь новых задач, ещё не выполнявшихся, и 2) очередь готовых задач, в конец которой записываются те задачи, которые были заблокированы в процессе работы (например, при выполнении операций ввода-вывода) и которые после окончания состояния ожидания перешли в состояние готовности к выполнению. Из первой очереди задачи выбираются, только если вторая очередь пуста. Последний способ позволяет удовлетворить принципу «по возможности заканчивать вычисления в том порядке, в каком они начинались».

Далее будем рассматривать каждый метод планирования на примере пяти процессов (рис. 4.2). Основные характеристики метода FCFS для данного примера показаны на рис. 4.3.

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

В современных ОС обслуживание по принципу FCFS в чистом виде не применяется, но часто используется в комбинации с другими методами.

4.4. Циклические планировщики

Чтобы гарантировать, что ни одной задаче не придётся слишком долго ждать своей очереди, используются вытесняющие циклические стратегии планирования, когда каждой задаче отводится определённое время, по истечении которого управление передаётся следующей задаче в очереди, а предыдущая записывается в конец очереди. Таким образом, все задачи обслуживаются «по кругу».

При бесприоритетном циклическом (круговом или, иначе, карусельном) планировании (round robin, RR) задачи выбираются на выполнение по принципу FCFS, каждый раз задаче предоставляется ограниченное количество (квант) времени центрального процессора. По истечении выделенного кванта времени, если задача не завершиться раньше этого срока, она приостанавливается и записывается в конец очереди. Именно этот метод (в той или иной модификации, обычно связанной с учётом приоритетов задач) обычно используется в интерактивных ОС, которые должны обеспечивать приемлемое время отклика на действия пользователя. При этом важно выбрать оптимальную продолжительность кванта времени. При слишком коротком кванте большая´ часть ресурсов системы будет тратиться на реализацию механизма переключения задач. При слишком большом — увеличится время ожидания. Примеры для различных значений длительности кванта приведены на рис. 4.5 и 4.6.

Иногда используются две очереди готовых задач: первая — для задач, исчерпавших квант выделенного им времени, а вторая — для задач, у которых завершилась операция ввода-вывода. Диспетчер просматривает сначала вторую очередь и только если она пуста, квант времени выделяется задаче из первой очереди.

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

1Используется также аббревиатура FIFO (first input — first output), т. е. «первым вошёл — первым вышел».

24

Ю. В. Земсков. Системное и прикладное программное обеспечение. Конспект лекций, варианты заданий и методические указания в лабораторным работам. ВГИ ВолГУ, 2002 г.

35

 

 

 

 

C

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Процесс

 

t0

1

 

?

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

6

12

17

 

 

 

 

A

3

0

 

 

 

 

B

 

 

 

 

 

 

 

 

E

 

 

 

 

B

5

1

 

?

 

 

 

 

 

?

 

 

 

 

 

 

 

 

C

2

3

0

 

3

 

 

 

9

 

 

 

14

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

D

5

9

 

 

A

 

 

 

 

 

 

 

 

 

D

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

E

5

12

 

?

 

 

 

 

 

 

 

 

?

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

0

 

5

10

 

 

15

 

20

 

 

 

Рис. 4.2. Пример планирования для пяти процессов: — время выполнения процесса в монопольном режиме; t0 — момент загрузки процесса для выполнения

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Процесс

 

t0

ts

tf

Tr

Tw

Tr=

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

A

3

0

0

3

3

0

1;0

 

 

 

 

3

 

 

10

 

 

 

 

 

 

 

 

 

 

 

B

5

1

3

8

7

2

1;4

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

C

2

3

8

10

7

5

3;5

 

 

 

 

 

 

?

 

 

 

 

C

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

D

5

9

10

15

6

1

1;2

1

 

 

 

 

8

 

 

 

12

 

 

 

 

 

20

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

E

5

12

15

20

8

3

1;6

 

 

 

?

 

 

 

 

B

 

 

 

 

 

 

?

 

 

 

 

E

 

 

 

 

Среднее значение

6;2

2;2

1;74

0

 

3

 

 

 

 

9

 

 

15

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

A

 

 

 

 

 

 

 

 

 

 

 

D

 

 

 

 

 

 

 

 

Процесс

 

t0

ts

tf

Tr

Tw

Tr=

 

?

 

 

 

 

 

 

 

 

 

 

?

 

 

 

 

 

 

 

 

 

 

 

W

1

0

0

1

1

0

1;00

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

A

 

 

 

 

B

 

 

C

 

 

D

 

 

 

 

E

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

X

100

0

1

101

101

1

1;01

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

0

 

 

5

10

 

 

15

 

 

20

Y

1

0

101

102

102

101

102;00

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Z

100

0

102

202

202

102

2;02

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Среднее

значение

101;5

51

28;10

Рис. 4.3. Пример планирования по методу FCFS: ts — момент начала выполнения процесса; tf — момент окончания выполнения; Tr = tf t0 — общее время выполнения; Tw = Tr — общее время ожидания

Описатель

>

Описатель

 

Описатель

>

Описатель

 

Описатель

потока A

потока B

>

потока C

потока D

>

потока E

Ссылка

 

Ссылка

 

Ссылка

 

Ссылка

 

0

 

 

 

 

 

 

 

 

 

Рис. 4.4. Реализация очереди готовых задач в виде связанного списка

38

 

 

 

 

 

 

C

 

 

 

C

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

?

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Процесс

 

 

t0

ts

tf

Tr

Tw

Tr=

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1

 

 

 

 

 

 

11 12

 

 

 

20

 

A

 

3

0

0

6

6

3

2;0

 

 

B

 

 

B

 

 

 

B

 

B

 

B

 

E

 

E

 

E

 

E

E

 

B

 

5

1

1

11

10

5

2;0

 

 

?

 

 

 

 

 

 

 

 

 

?

 

 

 

 

 

 

 

 

C

 

2

3

4

8

5

3

2;5

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

0

 

 

 

 

 

6

9

 

 

 

 

 

 

18

 

 

 

D

 

5

9

9

18

9

4

1;8

 

A

 

A

 

 

 

 

A

 

 

 

D

 

D

 

D

 

D

 

D

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

E

 

5

12

12

20

8

3

1;6

 

?

 

 

 

 

 

 

 

 

 

 

?

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Среднее значение

7;6

3;6

1;98

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

A

B

A

 

B

C

A

B

C

B

D

B

D

E

D

E

D

E

D

E

E

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

0

 

 

 

 

 

5

10

 

 

 

15

20

 

 

 

 

 

 

 

 

 

Рис. 4.5. Пример планирования по методу RR при длительности кванта q = 1

25

Ю. В. Земсков. Системное и прикладное программное обеспечение. Конспект лекций, варианты заданий и методические указания в лабораторным работам. ВГИ ВолГУ, 2002 г.

39

 

 

 

 

 

 

 

 

 

C

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

?

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Процесс

 

 

t0

ts

tf

Tr

Tw

Tr=

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1

 

 

 

 

 

10

 

12

 

 

 

 

20

 

A

 

3

0

0

3

3

0

1;0

 

 

 

 

 

 

B

 

 

 

B

 

 

 

 

 

E

 

 

E

 

B

 

5

1

3

10

9

4

1;8

 

 

?

 

 

 

 

 

 

 

 

 

 

 

?

 

 

 

 

 

 

 

 

C

 

2

3

7

9

6

4

3;0

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

0

 

3

 

 

 

 

9

 

 

 

 

 

 

 

19

 

 

D

 

5

9

10

19

10

5

2;0

 

 

A

 

 

 

 

 

 

 

 

 

 

D

 

 

 

 

 

D

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

E

 

5

12

14

20

8

3

1;6

 

?

 

 

 

 

 

 

 

?

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Среднее значение

7;2

3;2

1;88

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

A

 

 

 

B

 

C

B

 

D

 

 

E

 

D

E

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

0

 

5

10

 

 

15

 

20

 

 

 

 

 

 

 

 

 

Рис. 4.6. Пример планирования по методу RR при длительности кванта q = 4

очереди. Если она пуста, то выбирается очередная задача из менее приоритетной очереди. Именно так работают планировщики в операционных системах OS/2 и Windows NT.

4.5. Планировщики с динамическим приоритетом

Реализация планирования с изменяемыми приоритетами требует дополнительных расходов на вычисление новых значений приоритетов задач во время их выполнения.

Приоритет зависит от времени обслуживания.

В методах планирования этой группы приоритеты задач изменяются в зависимости от того, сколько времени осталось до завершения выполнения задачи.

Дисциплина обслуживания SJF (shortest job first)1 предполагает, что существует одна общая очередь, в конец которой попадают все новые задачи, а также те, что после состояния ожидания перешли в состояние готовности. Из очереди на выполнение выбирается не первая задача, а та, что имеет минимальное оценочное время, оставшееся до своего завершения (рис. 4.7).

В результате удаётся снизить среднее время ожидания (по сравнению с методами FCFS и RR), особенно если имеются трудоёмкие задачи. Данный метод обеспечивает невытесняющую многозадачность, т.к. предполагает переключение к новой задаче только в том случае, если текущая закончила своё выполнение.

К сожалению, заранее узнать время выполнения задачи не всегда возможно. При этом приходится полагаться на ту оценку, которую задал для своей задачи пользователь. Если эта оценка не оправдывается, на задачу «налагается штраф». Для описания потребностей каждой задачи в ресурсах вычислительной системы были разработаны специальные языки, например, язык JCL (job control language — язык управления заданиями).

Планирование по принципу SRT (shortest remaining time) — по минимальному оставшемуся

1Используется также аббревиатура SJN (shortest job next).

времени — является вариантом метода SJF, но предполагает переключение задач (т.е. вытесняющее планирование). По принципу SJF задание, запущенное на выполнение, будет выполняться до своего завершения или до перехода в состояние ожидания. Согласно методу SRT, напротив, выполняющийся процесс может быть прерван при поступлении в очередь готовности новой задачи, имеющей меньшее оценочное время, оставшееся до своего завершения. В результате достигается ещё меньшее среднее время ожидания.

Приоритет зависит от времени ожидания.

Стратегия планирования HRN (highest-response- ratio-next, «по наибольшему относительному времени ответа») компенсирует некоторые слабости метода SJF (например, чрезмерное «предубеждение» против длинных заданий и чрезмерную «благосклонность» по отношению к коротким новым заданиям). В данном методе приоритет каждой задачи является не только функцией времени, требуемой для её обслуживания (выполнения), но также времени, затраченного задачей на ожидание в очереди, т. е. приоритеты вычисляются по формуле

p = Tw + :

Т. к. длительность задачи стоит в знаменателе, то предпочтение будет отдаваться более коротким заданиям. Однако, поскольку в числителе находится время ожидания Tw , более длинные задания, которые уже довольно долго ждут своей очереди, будут также получать определённое предпочтение.

Абсолютные и относительные приоритеты.

При использовании приоритетного планирования без квантования из очереди готовых задач на выполнение выбирается задача, имеющая наибольший приоритет. При этом для определения момента смены активного потока используются два подхода.

В системах с относительными приоритетами

активный поток выполняется до тех пор, пока он сам

26

Ю. В. Земсков. Системное и прикладное программное обеспечение. Конспект лекций, варианты заданий и методические указания в лабораторным работам. ВГИ ВолГУ, 2002 г.

35

 

 

 

 

 

C

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

?

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Процесс

 

 

t0

ts

tf

Tr

Tw

Tr=

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1

 

 

 

 

 

 

 

 

10

 

12

 

 

 

20

 

A

 

3

0

0

3

3

0

1;0

 

 

 

 

 

 

 

 

 

 

B

 

 

 

 

 

 

 

 

 

E

 

B

 

5

1

5

10

9

4

1;8

 

 

?

 

 

 

 

 

 

 

 

 

 

 

 

?

 

 

 

 

 

 

 

 

C

 

2

3

3

5

2

0

1;0

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

0

 

3

 

 

 

 

 

 

 

9

 

 

 

15

 

 

 

 

 

 

D

 

5

9

10

15

6

1

1;2

 

 

A

 

 

 

 

 

 

 

 

 

 

 

 

D

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

E

 

5

12

15

20

8

3

1;6

 

?

 

 

 

 

 

 

 

 

 

 

?

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Среднее значение

5;6

1;6

1;32

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

A

 

 

C

 

 

 

B

 

 

 

 

D

 

 

 

 

E

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

0

 

 

 

 

 

5

 

 

10

 

 

15

20

 

 

 

 

 

 

 

 

 

Рис. 4.7. Пример планирования по методу SJN

не покинет процессор, перейдя в состояние ожидания (или же произойдёт ошибка и задача завершится).

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

Ясно, что для систем реального времени или интерактивных режимов работы первый вариант неприемлем, но для пакетного режима (например, в OS/360) относительные приоритеты широко используются.

Смешанные алгоритмы планирования. В современных ОС обычно используются как квантование, так и приоритеты. При этом длительность кванта и/или порядок выбора задач на выполнение из очереди готовых зависит от приоритета этой задачи.

Приоритетная очередь с обратной связью.

Вытесняющий алгоритм планирования, в котором квантование сочетается с динамическими приоритетами, зависящими от времени выполнения задачи (обратная связь — feedback, FB). Приоритет задачи уменьшается с каждым новым квантом (или несколькими квантами) процессорного времени, потребовавшимся этой задаче для своего выполнения (рис. 4.8).

4.6. Примеры конкретных реализаций планирования

4.6.1. Novel NetWare 3.x и 4.x

Кооперативная многозадачность довольно удачно реализована в ОС Novel NetWare, где в значительной степени благодаря именно этому достигнута высокая скорость выполнения файловых операций.

Планировщик в этой ОС использует несколько очередей готовых потоков. Только что созданный поток попадает в конец очереди RunList, в которой со-

держатся готовые к выполнению потоки. Чтобы не занимать процессор слишком долго, каждый поток в NetWare сам отдаёт управление планировщику ОС, используя следующие системные вызовы:

ThreadSwitch — поток, вызвавший эту функцию, считает себя готовым к немедленному выполнению, но отдаёт управление для того, чтобы могли выполняться и другие потоки;

ThreadSwitchWithDelay — функция аналогична предыдущей, но поток считает, что будет готов к выполнению только через определённое количество переключений с потока на поток;

Delay — функция аналогична предыдущей, но задержка даётся в миллисекундах;

ThreadSwitchLowPriority — функция отдачи управления, отличается от ThreadSwitch тем, что поток просит поместить его в очередь готовых к выполнению, но низкоприоритетных потоков.

После отказа от процессора поток попадает в ту или иную очередь, в зависимости от того, какой системный вызов был использован при передаче управления. При вызове ThreadSwitch поток попадает в конец основной очереди RunList, при вызовах ThreadSwitchWithDelay или

Delay — в конец очереди DelayedWorkToDoList (готовые с задержкой), а при вызове

ThreadSwitchLowPriority — в конец низкоприоритетной очереди LowPriorityRunList. Потоки, находящиеся в очереди DelayedWorkToDoList, после завершения условия ожидания перемещаются в конец очереди RunList.

Очередной поток выбирается на выполнение из начала очереди RunList. Потоки, находящиеся в очереди LowPriorityRunList (обычно они выполняют несрочную фоновую работу), запускаются на выполнение только в том случае, если очередь RunList пуста.

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

27

Ю. В. Земсков. Системное и прикладное программное обеспечение. Конспект лекций, варианты заданий и методические указания в лабораторным работам. ВГИ ВолГУ, 2002 г.

3 6 12 20

 

 

 

 

C

 

C

 

 

 

 

 

 

E

E

E

 

E

 

 

E

 

 

 

 

 

 

 

 

 

 

 

 

 

 

?

 

 

 

 

 

 

 

 

?

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

18

 

 

 

Процесс

 

 

t0

ts

tf

Tr

Tw

Tr=

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

A

 

3

0

0

7

7

4

2;3

 

 

B

 

 

B

 

 

B

B

 

 

 

 

 

 

 

 

B

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

B

 

5

1

1

18

17 12

3;4

 

 

?

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

0

 

 

 

7

9

 

 

 

 

 

 

 

19

 

 

C

 

2

3

3

6

3

1

1;5

 

 

 

 

 

 

 

 

 

 

 

 

D

 

5

9

9

19

10

5

2;0

 

A

 

A

 

 

 

A

 

 

D

D

D

 

 

 

D

 

 

D

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

E

 

5

12

12 20

8

3

1;6

 

?

 

 

 

 

 

 

 

 

?

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1

1 2 1

2 2 3

3 4 1 2 3

1 2 3 4 4

5 5 5

 

 

 

Среднее

значение

9

5

2;16

 

A

B

A

C

B

C

A

B

B

D

D

D

E

E

E

D

E

B

D

E

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

0

 

 

 

5

 

10

 

15

 

20

 

 

 

 

 

 

 

 

 

Рис. 4.8. Пример планирования по методу FB

ся при старте системы для системных целей и выполнения срочных работ. Рабочие потоки из очереди WorkToDoList имеют наивысший приоритет и получают процессорное время перед потоками из очереди RunList. Однако, планировщик следит за тем, чтобы из очереди WorkToDoList выбиралось подряд только ограниченное число потоков (после нескольких «льготников» подряд процессорное время получает обычный поток).

4.6.2. Windows NT/2000/XP

Используется вытесняющее планирование на уровне потоков, при этом динамические абсолютные приоритеты сочетаются с квантованием. На выполнение выбирается поток с наивысшим приоритетом; ему выделяется квант времени. Если во время выполнения в очередь поступит поток с большим´ приоритетом, то текущий поток будет прерван (вытеснен) и помещён в очередь впереди всех потоков с тем же приоритетом. По истечении кванта времени поток также вытесняется и помещается в очередь после всех остальных потоков с тем же приоритетом.

Определено 32 уровня приоритетов и два класса потоков: потоки реального времени (уровни с 16 по 31) и потоки с переменными приоритетами (с 1 по 15). Уровень 0 зарезервирован для системных целей.

При создании процесса в зависимости от своего класса он по умолчанию получает базовый приоритет в верхней или нижней части диапазона соответствующего класса. Базовый приоритет в дальнейшем может быть изменён операционной системой.

Каждый

поток процесса получает снача-

ла значение

базового приоритета из диапазона

[B 2; B + 2], где B — базовый приоритет процесса, в котором он создан. В дальнейшем ОС может изменять приоритет потока, причём это изменение не обязательно связано с изменением базового приоритета процесса. Например, приоритет потока может повышаться, если он не полностью использовал свой квант времени, и понижаться в противном случае. В

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

4.6.3. Unix System V Release 4

Планирование осуществляется на уровне процессов (понятие “поток” отсутствует). Реализована вытесняющая многозадачность на основе приоритетов и квантования.

Каждый процесс относится к одному из трёх приоритетных классов: 1) классу реального времени; 2) классу системных процессов; 3) классу процессов разделения времени. Для каждого класса назначение и обработка приоритетов осуществляется поразному.

Процессы ядра ОС принадлежат к системному классу и используют фиксированные приоритеты.

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

По умолчанию каждый процесс принадлежит к классу процессов разделения времени (в предыдущих версиях Unix других классов не существовало). Здесь используются динамические приоритеты, пропорциональные двум составляющим: пользовательской части процесса и системной части. Пользовательская часть может быть изменена администратором и пользователем–владельцем процесса (во втором случае — только в сторону снижения), а системная составляеющая регулируется диспетчером про-

28

Ю. В. Земсков. Системное и прикладное программное обеспечение. Конспект лекций, варианты заданий и методические указания в лабораторным работам. ВГИ ВолГУ, 2002 г.

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

периода использования процессора. Это ущемление в правах “неповоротливых” процессов компенсируется тем, что процессам с низким приоритетом выделяется более длинный квант времени.

29

Ю. В. Земсков. Системное и прикладное программное обеспечение. Конспект лекций, варианты заданий и методические указания в лабораторным работам. ВГИ ВолГУ, 2002 г.

4.7. Создание многопоточных приложений в Win32 API

Если сказано хорошо, то не все ли равно, на каком языке.

Лопе де Вега

Рассмотрим пример простейшего консольного приложения, использующего потоки. В листинге 4.1 приведён вариант для Borland Delphi, в листинге 4.2 — для Borland C++Builder, в листинге 4.3 — для Microsoft Visual C.

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

В случае использования Delphi сообщения на экране перепутываются: один из потоков, не дожидаясь, пока завершится вывод сообщения другого потока, начинает выводить своё сообщение. В Visual C при использовании потокобезопасной библиотеки libcmt.lib этого не наблюдается. В C++Builder’е функция printf также потокобезопасна.

4.8. Работа с потоками в Delphi

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

Создадим новое приложение командой í File í New í Application ( í Файл í Создать í Приложение ). Подготовим форму с двумя областями рисования TPaintBox размером 100 100 пикселов. Разместим также на форме кнопку, по шелчку на которой будут запускаться потоки. Добавим в проект класс–поток командой í File í New í Other í Thread Object ( í Файл í Создать í Другое í Потоковый объект ). В диалоговом окне ввода названия класса укажем TMyThread. Этот класс будет наследником базового класса–потока TThread. Возникнет файл с пустым описанием этого класса. Перейдём к модулю главной формы и опишем в классе ТFогm1 новый метод CPaint (листинг 4.4), который получит в качестве параметра холст (canvas) и нарисует на нём квадрат размером 10 10 пикселов. Место расположения квадрата и его цвет выбираются случайным образом.

Добавим ещё два метода (листинг 4.5), которые будут обращаться к процедуре CPaint для вывода квадрата либо на холст объекта PaintBox1, либо на холст объекта PaintBox2. Эти процедуры необходимы, чтобы вызывать их из класса–потока, причём специальным образом. Дело в том, что, когда методы классов Delphi 6 (в нашем случае — метод Rectangle) одновременно вызываются из нескольких потоков, это может приводить к самым неожиданным конфликтам между потоками. Например, проблемы могут быть связаны со слишком быстрым чередованием обработки процесса вывода на экран, когда системе требуется обрабатывать объекты классов TBrush, ТРеn. Поэтому в классе TThread имеется метод гарантированно безопасного выполнения таких методов. Этот метод выполняет синхронизацию работы всех потоков:

type TThreadMethod := procedure of object;

procedure Synchronize (Method: TThreadMethod);

В качестве параметра он получает название метода без параметров. Для этого нам и понадобилось создать процедуры Paint1 и Paint2. А как определить внутри потока, какой из этих методов надо вызывать? Добавим в класс TMyThread переменную Box1:

...

public

Box1: boolean;

При создании экземпляра потока занесём в эту переменную значение true, если надо вызывать метод Paint1. Вся логика работы потока описывается в его основном методе Execute (листинг 4.6).

Свойство класса Terminated автоматически примет значение true, когда программа получит команду на завершение. В зависимости от значения переменной Box1 выполнится отрисовка одного квадрата (вызов соответствующего метода класса TForm1), после чего продолжится цикл произвольной длительности. Теперь надо добавить в описание класса TForm1 две новые переменные — два будущих потока:

T1, T2: TMyThread;

Обработчик щелчка на кнопке Button1 показан в листинге 4.7.

Поток создаётся с помощью конструктора Create, который имеет один параметр. Он равен true, если поток создаётся неактивным, а должен начать работу после вызова метода Resume. В противном случае — false — поток начнёт работу сразу же после создания. Далее задаются значения переменной Box1 и свойства Priority — приоритета выполнения потока. Приоритет определяет, как часто операционная система должна выделять процессу кванты времени, т. е. фактически, задаёт быстродействие этого процесса. Свойство Priority имеет тип TThreadPriority и может принимать одно из следующих значений:

tpIdle — поток выполняется, только если системе больше нечего делать;

30

Ю. В. Земсков. Системное и прикладное программное обеспечение. Конспект лекций, варианты заданий и методические указания в лабораторным работам. ВГИ ВолГУ, 2002 г.

Листинг 4.1. Пример многопоточной программы в Delphi

//Создание тредов в Delphi. Используются только функции API Win32.

//Каждый тред подсчитывает кол-во пробелов в своём файле

//Главная программа запускается с параметрами - списком имён файлов

//(при отладке в среде - Project|Settings|Debug|Program arguments)

program Project2; {$APPTYPE CONSOLE} uses SysUtils, Windows;

function MyThread(PFileName:PChar):DWORD;stdcall;

//Эта функция будет считать кол-во пробелов в файле.

//Она будет запускаться в отдельных тредах, поэтому тип возвращаемого

//значения обязательно DWORD

var

 

handle : THandle;

// Дескриптор файла

numRead, total : DWORD;

buf : char; // Сюда будем читать очередной символ из файла

namestr : String;

 

begin

 

namestr := StrPas(PFileName);

writeln(’This is thread ’,GetCurrentThreadId(),’ for file ’,namestr);

handle:=CreateFile(

// Открываем файл

PFileName,

// указатель на имя файла

GENERIC_READ,

// для чтения

FILE_SHARE_READ, // др.процессы тоже смогут читать этот файл

NIL,

// режимы безопасности поддерживаются только в NT и 2000

OPEN_EXISTING,

// файл должен существовать, иначе ошибка

FILE_ATTRIBUTE_NORMAL, // атрибуты файла - без атрибутов

0);

// дескриптор файла для расширенных атрибутов - не используется

total:=0; // Счётчик пробелов в своём файле

repeat // В цикле читаем очередной символ из файла

ReadFile(handle,

// Дескриптор файла

 

buf,

// Адрес буфера, куда читаем

 

1,

// Сколько байт читать

 

numRead,

// Фактически прочитанное кол-во байт

 

NIL);

// Структура перекрытия не используется

if(buf=#$20)then inc(total); // $20 - это код пробела

until(numRead=0);

// повторять, пока ещё что-то читается

writeln(’File

’, namestr, ’ --- ’, total,’ spaces’);

CloseHandle(handle); // закрыли файл

Result:=0; //

Функция MyThread возвращает код ошибки (0 - ошибок нет)

end;

 

 

Var

 

 

i : word;

pid : DWORD;

 

hThrd : array[0..255] of

THandle; // массив ссылок на треды

ParamNames: array[0..10] of String; // массив ссылок на имена файлов Begin

for i:=0 to (ParamCount-1) do begin

ParamNames[i] := ParamStr(i+1); // имя файла, указанное в командной строке

hThrd[i] := CreateThread(

// Создаём тред

NIL,

// Атрибуты безопасности поддеживаются только в NT и Win2000

$4000,

//

Размер стека в байтах

 

//

(если 0 - то тред использует стек родителя)

@MyThread, // указатель на функцию, к-рая будет выполняться в потоке PChar(ParamNames[i]), // указатель на параметр потока (имя файла)

0, // поток сразу выполняется (если CREATE_SUSPEND - то ждёт вызова ResumeThread) pid); // выходной параметр : идентификатор потока

writeln(’===MAIN : thread ’, i, ’ with ID= ’, pid,

’ started for file ’, ParamNames[i],’ ===’);

end;

Writeln(’PRESS ENTER...’); Readln; // ждать нажатия на ENTER

End.

31

Ю. В. Земсков. Системное и прикладное программное обеспечение. Конспект лекций, варианты заданий и методические указания в лабораторным работам. ВГИ ВолГУ, 2002 г.

Листинг 4.2. Пример многопоточной программы в C++Builder

//C++Builder 4. Создание тредов.

//Каждый тред подсчитывает кол-во пробелов в своём файле.

//Главная программа запускается с параметрами - списком имён файлов

//(при отладке в среде - Run | Parameters)

//Используются только функции Win32 API

#include <condefs.h> // Добавляется автоматически при создании // консольного проекта в C++Builder

#include<windows.h>

#include<stdio.h>

#include<conio.h>

//Эта функция будет запускаться в отдельных тредах, поэтому тип

//возвращаемого значения обязательно DWORD

DWORD myprocess(LPVOID lpFileName){

// функция будет считать кол-во пробелов в файле

HANDLE handle;

//

Дескриптор файла

DWORD numRead,

total;

 

char buf;

// Сюда

будем читать очередной символ из файла

printf("\nThis is thread %lu for file %s",GetCurrentThreadId(),lpFileName);

handle=CreateFile(

// Открываем

файл

(LPCTSTR)lpFileName,

//

имя

файла

GENERIC_READ,

//

для

чтения

FILE_SHARE_READ,

//

др.процессы тоже смогут читать этот файл

NULL,

// режимы безопасности поддерживаются только в NT и 2000

OPEN_EXISTING,

// файл должен существовать, иначе ошибка

FILE_ATTRIBUTE_NORMAL,

// атрибуты файла - без атрибутов

NULL);

 

// дескриптор файла для расширенных атрибутов

total=0;

 

 

do{

 

 

ReadFile(handle,(

 

// Дескриптор файла

LPVOID)&buf,

// Адрес буфера, куда читаем

1,

 

// Сколько байт читать

&numRead,

 

// Фактически прочитанное кол-во байт

NULL);

 

// Структура перекрытия не используется

if(buf==0x20) total++;

// 0x20 - это код пробела

}while (numRead>0);

 

// пока еще что-то читается

printf("\n File %s --- %d

spaces", lpFileName,total);

CloseHandle(handle);

 

// закрыли файл

return 0;

 

 

}

 

 

int main(int argc,char*argv[]){ int i;

DWORD pid;

HANDLE hThrd[255]; // массив ссылок на треды

for(i=0;i<(argc-1);i++){ hThrd[i]=CreateThread( // Создаём тред

NULL,

// Атрибуты безопасности поддерживаются только в

NT и Win2000

0x4000,

// Размер стека в байтах

 

 

// (если 0

- то тред использует стек родителя)

 

(LPTHREAD_START_ROUTINE)myprocess,// указатель на функцию потока

(LPVOID)argv[i+1], //

указатель на параметр потока (в нашем

случае имя файла)

0,

//

поток сразу выполняется

 

 

//

(если CREATE_SUSPEND - то ждёт вызова

ResumeThread)

&pid);

//

выходной параметр : идентификатор потока

printf("\n===MAIN :

thread %u

with ID=%lu started for file %s ===",i,pid,argv[i+1]);

Sleep(1000);

//

пауза 1000 мс

}

 

 

 

printf("\nPRESS ANY

KEY...");

 

getch(); // ждать нажатия на любую клавишу

}

32

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]