Вы находитесь на странице: 1из 14

Некоторые замечания о многозадачности.

Цель.
Основная цель программиста при использовании инструментов
параллельного программирования - добиться ускорения вычислений. Вторая,
не менее важная цель - добиться увеличения эффективности системы
(использование минимального объема ресурсов для достижения
максимального результата).

Система S1 с кол-вом ресурсов R в которой за время t решается 5 задач


одинаковой сложности, будет в 5 раз эффективнее системы S2 с тем же кол-вом
ресурсов, в которой за тоже самое время решается только одна задача. В случае
же если кол-во ресурсов в системе S2 в два раза меньше кол-ва ресурсов S1,
система S1 становится только в 2.5 раза эффективнее S2 и т.д.

Структура вычислительной системы.


Современная вычислительная система похожа на слоеный пирог, в
основании которого находится реальная машина - аппаратное обеспечение
(англ. hardware). Аппаратное обеспечение делится на ядро и периферию. Ядро
системы – связка «процессор - память», периферия – различного рода
устройства ввода-вывода (видеокарта-дисплей, клавиатура и пр.), хранения
информации (например, жесткий диск, флэш-память). Аппаратное
обеспечение используется слоем программного обеспечения благодаря
стандартному интерфейсу, который оно предоставляет. Так, процессор в
качестве такого интерфейса предоставляет ISA (instruction set architecture),
периферийные устройства – систему команд и правила общения с
использованием портов и прерываний (используются команды OUT, IN).

1
Примером ISA является стандарт X86, который описывает какие коды
задают какие команды, как задаются операнды. Благодаря ISA бинарный код,
записанный пользователем в оперативную память, может выполняться
процессором.

Очень важно отметить здесь первое – аппаратное обеспечение


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

Следующим за слоем аппаратного обеспечения идет слой операционной


системы. Суть его состоит в организации работы пользовательских
приложений, распределении ресурсов (процессорного времени, памяти,
периферийных устройств) между выполняющимися программами. С одной
стороны операционная система предоставляет значительные удобства в
выполнении пользовательских программ, с другой – налагает на них
ограничения. Одним из существенных ограничений является то, что
пользовательское приложение должно обращаться за необходимыми
ресурсами к операционной системе, а не использовать их напрямую.
Пользовательское приложение вынуждено работать с ОС, используя
специальный интерфейс API (application programing interface), который
физически представляет собой набор библиотек со множеством функций (в
случае Windows можно назвать широко известные kernel32.dll, user32.dll,
system32.dll).

Последним и самым важным слоем является слой пользовательских


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

2
Многозадачность.
Понятие режима многозадачности (англ. multitasking) означает, что в
заданный момент времени в вычислительной системе может одновременно
решаться несколько вычислительных задач. Эти задачи будут пребывать в
разной степени завершенности и выполнятся различными устройствами
системы, которые, как мы уже определили работают с разной скоростью и что
важно, могут работать в автономном или полуавтономном режиме, то есть
независимо от центрального процессора. Например, в то время, когда одна из
задач ожидает реакции пользователя с клавиатуры, другая – может ждать
пересылки необходимых данных с диска в память, а третья – выполнятся
процессором и т. д.
Как видно из приведенного примера преимущество подхода
многозадачного режима выполнения состоит в совмещении (англ. overlapping)
различных операций, выполняемых разными устройствами при решении
различных вычислительных задач. И если быть точным – в совмещении
работы периферийных устройств с работой процессора, при выполнении
различных вычислительных задач.
Ключом к пониманию преимущества данного подхода является понимание
структуры типовой задачи, которая показана на рис.1.

IO device Processor IO device

Retrieve data Process data Save results

Рис.1. Структура типовой вычислительной задачи.


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

3
и выполнив операции над готовыми к обработке операндами, процессор
приостанавливает свою активность до момента готовности к обработке
данных, хранящихся на медленном устройстве, т.е. их передачи с медленного
устройства в оперативную память. Тоже самое происходит в момент
сохранения результатов. Принимая во внимание значительный разрыв во
времени обработки «процессор-периферийное устройство», легко видеть, что
такая система будет неэффективной.
В реальности же, фаза обработки, показанная на рис.1 будет разделена еще
на множество дополнительных шагов, как показано на рис.2, из которых
большую часть времени будет занимать взаимодействие с различными
медленными периферийными устройствами.
Interaction Processing Interaction Processing

Process data

Рис.2. Уточненная структура типовой вычислительной задачи.

Однако для введения такого механизма в действие понадобятся


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

4
инструкциям одной задачи к данным другой. Все это приводит к тому, что
должен быть введен некоторый посредник, который будет организовывать
выполнение задач, распределять между ними ресурсы и пр. Таким
посредником является операционная система.
Операционная система состоит из множества подсистем, но основных - три,
они и составляют ядро:
1) Подсистема управления процессами (диспетчер) - определяет, какую
задачу и в какое время следует передать процессору для обслуживания. Также
эта подсистема обеспечивает бесконфликтное использование ресурсов
компьютера (например, магнитных дисков, принтера, дисплея) сразу
несколькими программами.
2) Подсистема управления памятью - обеспечивает бесконфликтное
использования памяти несколькими программами. Для достижения этой цели
в результате был предложен механизм виртуализации памяти.
3) Подсистема управления файловой системой – управляет доступом к
данным и программам, которые хранятся в файлах на дисковом носителе.
Не обошлось без нововведений и на аппаратном уровне. Так обязательной
частью систем стала подсистема прерываний от периферийных устройств,
обеспечивающая асинхронное взаимодействие «процессор-периферия»
(рис.3). Так периферийное устройство после завершения операции, с
использованием специальной схемы, которая называется PIC (programmable
interrupt controller), передает процессору, через специальный вывод-канал,
сигнал о прерывании и его номер (англ. interrupt). Процессор в ответ на
прерывание, если оно не замаскировано, руководствуясь переданной
информацией (номером прерывания) вызывает процедуру-обработчик,
который уже передает управление подсистеме управления процессами.

5
load

Task 1
read file
save ctx
Start processing

Operating system
load

IO device
Task 2
Interrupt
save ctx
load
Task 1

Рис.3. Пример обработки прерывания ОС.


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

Система прерываний. Системный вызов.


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

6
exception); ошибка кода операции и пр. Со всеми этими прерываниями связаны
обработчики – процедуры ОС, которые их обрабатывают. Связь прерываний и
обработчиков осуществляется с помощью задания таблицы дескрипторов
прерываний (IDT – interrupt descriptor table).

Идея дескриптора состоит в кратком описании объекта: его свойств,


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

Операционная система при старте загружает создает эту таблицу в


память и сообщает процессору ее адрес с использованием регистра IDTR
(листинг 1).

Листинг 1
lidt [idt_info] ;load IDT pointer to IDTR

idt_info:
dw idt_end - idt_start - 1
dd idt_start
idt_start:
irq0:
dw isr0 ; offset bits 0-15
dw 0x0008 ; code segment selector in GDT or LDT
db 0x00
db 10101110b
dw 0x0000
irq1:
dw isr1
dw 0x0008
db 0x00
db 10101110b
dw 0x0000

7
irq2:
...

isr0:
...
iret
isr1:
...
iret

Далее процессор при возникновении аппаратного прерывания или


выполнении команды INT находит по номеру прерывания соответствующий
дескриптор, и используя его получает адрес процедуры-обработчика. На рис.4
показана упрощенная схема использования таблицы IDT.

@(int 255)

...
Int 0 handler
@(int 3)

@(int 2)
address
@(int 1)

@(int 0) address
IDT IDTR

Рис.4. Связь прерываний и их процедур-обработчиков.

Кроме всего прочего с системой прерываний связан важнейший метод


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

8
функцией malloc, создания/открытия файла на диске, печати на принтере)
задает необходимую информацию (номер функции и параметры) и вызывает
определенное прерывание (в Windows номер этого прерывания – 2Eh, в Linux
– 80h). Это прерывание обрабатывается процессором также как и внешние
прерывания или уже описанные исключительные ситуации. Обработчик
системного вызова считывает переданные аргументы. В системе Windows
через регистр eax передается номер функции. Для передачи параметров в
системе Windows используется соглашение FastCall (часть параметров
передается через регистры, часть через стек).

Обработчик системного вызова знает, какой процесс является активным


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

Вывод – чем больше запросов ресурсов в вашей программе, тем больше


системных вызовов и ненужной работы операционной системы, вместо
полезной работы вашего приложения.

Защищенный режим работы процессора.

Исходя из вышеописанного, для организации многозадачности


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

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

Режим процессора, в котором выполняется подобное разделение


называется защищенным (англ. protected mode). В данном режиме процессор
работает в одном из двух колец защиты (protection ring):

✓ 0-ое – подразумевает, что задача выполняется в режиме ядра,


привилегированном режиме;
✓ 3-ье – режим пользовательских программ.

Переход в защищенный режим производится путем установки младшего


бита регистра CR0 (листинг 2).

Листинг 2
mov eax, cr0
or al, 1
mov cr0, eax

Процессы и потоки.

Процессом называется объект операционной системы, связывающий


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

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

Вот средством выполнения таких параллельных регионов являются


потоки (англ. threads of control flow within a process). Существует несколько
видов реализации потоков:

✓ Kernel-level threads – управляемые операционной системой (например,


потоки Windows). Данные потоки подобно процессам описываются
операционной системой в виде дескрипторов, ОС выделяет под каждый
поток стек и область TLS (thread local space). Потоки могут выполняться на
разных процессорах, проблемы, возникшие в одном из потоков, не
блокируют выполнения остальных;
✓ Lightweight processes – легковесные потоки, которые управляются
диспетчером встроенном в исполняемый код процесса (например, Posix
threads). Данный вид потоков по своим свойствам является полной
противоположностью kernel-level threads: на разных процессорах
выполняться не могут, выполнение одного потока блокирует выполнение
остальных. К положительным чертам абстракции данного вида можно
отнести скорость работы, независимость организации вычислений от ОС;
✓ Hybrid threads – гибридные потоки, которые объединяют качества первых
двух (предложены в системе Solaris компании SUN).

11
Состояния и контекст потока.

Создание потока в системе Windows связано с определенными


временными затратами: необходимо ввести дескрипторы, выделить место под
стек и TLS и пр. Если создается большое количество потоков – эти затраты
могут быть довольно внушительными.

После создания дескриптор потока заносится в очередь потоков готовых


к выполнению. И здесь важно отметить, что таких очередей может быть
несколько. Отличаются эти очереди приоритетом выполнения (в Windows
различают 7 приоритетов [https://docs.microsoft.com/en-
us/windows/win32/procthread/scheduling-priorities]). Алгоритмы диспетчеризации могут
быть разными, но более приоритетные потоки, как следует из названия,
выполняются более интенсивно.

Рассмотрим диаграмму состояний потока (рис. 5)

created
destroyed

run
Ready Running Exited
yield

sleep
wake up

Blocked

Рис. 5. Диаграмма состояний потока.

После создания поток помещается в очередь потоков готовых к


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

12
деталях был описан выше и дополнительных разъяснений не требует, кроме
того, что поток в этом случае, как правило, переходит в состояние Blocked
(ожидания выполнения системного запроса). Суть же варианта со временем
выполнения состоит в следующем. Диспетчер перед запуском потока заносит
в таймер (аппаратное устройство PIT – programmable interval timer –
микросхема Intel 8253/54) некоторое значение (в листинге 3 показан вариант
«зарядки» таймера на 10 миллисекунд). Более подробно о таймере можно
узнать в [http://www.brokenthorn.com/Resources/OSDevPit.html].

Листинг 3
; COUNT = input hz / frequency

mov dx, 1193180 / 100 ; 100hz, or 10 milliseconds

; FIRST send the command word to the PIT. Sets binary counting,
; Mode 3, Read or Load LSB first then MSB, Channel 0

mov al, 110110b


out 0x43, al

mov ax, dx
out 0x40, al ;LSB
xchg ah, al
out 0x40, al ;MSB

Таймер по истечении заданного времени срабатывает, вызывая


соответствующее прерывание, которое обрабатывается программой-
обработчиком ОС. Это программа-обработчик или сама является диспетчером
или вызывает диспетчер потоков, который уже сохраняет контекст текущего
потока и выполняет загрузку нового потока из очереди Ready на выполнение.
Заметим, что в этом случае сохраненный поток переходит в состояние «готов
к выполнению». Так строится система разделения времени между

13
выполняемыми потоками (англ. time sharing system - TSS), позволяющая
построить многопользовательские системы. Время, отводимое для
выполнения потока для серверной и клиентской версий операционных систем,
может сильно отличаться (в десятки раз).

Более подробно об организации и управлении потоками в ОС Windows


можно узнать в [https://www.codeproject.com/Articles/662735/Internals-of-Windows-Thread].

Взаимодействие процессов.

Иногда бывает необходимость, чтобы разные программы,


представленные на уровне ОС процессами, взаимодействовали между собой.
Для этого используются разные механизмы. В системе Windows это возможно
реализовать через общую память с использованием memory mapped files.
Такое взаимодействие будет самым быстрым. Кроме этого, есть довольно
быстрый механизм LRPC (local remote procedure call). Есть еще именованные
каналы (англ. pipes) и сокеты.

Если же процессы запущены на разных компьютерах-хостах,


единственным средством меж-процессного взаимодействия остаются только
сокеты. Поддержка протокола TCP/IP - стандартное требование для любой
операционной системы. Можно с уверенностью сказать, что все современные
операционные системы поддерживают данный протокол. Это дает
возможность построения гетерогенных распределенных вычислительных
систем, в которых разные программы, работающие под управлением разных
операционных систем, взаимодействуют через сокеты.

14