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

1233

.pdf
Скачиваний:
0
Добавлен:
15.11.2022
Размер:
625.43 Кб
Скачать

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

+----------------------------

+

 

¦Размер свобод-¦Адрес следую-¦

1, 2, 3 - свободные

¦ного

участка¦щего элемента¦

участки.

+----------------------------

+

Заштрихованы занятые

 

 

участки памяти

ОС

 

 

 

 

 

 

+-------------------------------------------------------------

 

 

 

 

 

+

++++++¦

 

++++++¦

 

++++++¦

 

++++++¦

+++++++-----

+

3 +++++++-----

+

2 +++++¦+-----

+ 1

++++++¦

+++ ++¦L3¦0 ¦

++++++¦L2¦ ¦

++++++¦L1¦ ¦

++++++¦

+--+-------------------------

 

 

+------------------

 

+-------------

+

¦

+---------------

+---

+

¦

¦

 

¦

 

+-----------------

 

+---

+

 

+---------------------------------------

 

 

 

+

 

 

В начале каждого участка располагается структура, которая содержит адрес следующего участка. Последний участок в поле адреса содержит ноль. Адрес первого элемента цепочки хранится в ОС.

2.Выделение участка памяти по запросам: элемент исключается из цепочки или изменяется его указатель длины.

3.Освобождение участка - наоборот.

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

Способы борьбы с фрагментацией:

·Расширение размера ОП (в том числе и за счет виртуализации).

·Упорядочение запросов на память. Запросы, подчиняющиеся ка- кой-либо классификации, направляются в одни и те же области памяти. Например, если есть возможность упорядочить запросы по времени освобождения, то

- краткосрочные запросы осуществляются по младшим адресам; - долгосрочные запросы выполняются по старшим адресам (нап-

равление можно менять);

·Упорядочение запросов по размерам. Запросы приблизительно одинаковых размеров удовлетворяются в одной и той же области основной памяти.

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

5.Многоуровневое распределение основной памяти состоит в том, что выделенный участок на верхнем уровне подлежит дальнейшему распределению на нижнем. Существует три уровня распределения:

I - уровень заданий; II - уровень задач; III - уровень запросов.

ВИРТУАЛЬНАЯ ПАМЯТЬ

Текущая задача - это получить доступ к гигабайтам через "хилободы"

(Дж. К. Р. Ликлайдер)

Воображение - в действительности не что иное, как вид памяти, освобожденной от уз времени и пространства (С.Т. Кольридж)

Впервые виртуальная память была реализована в Великобритании в компьютере Atlas (1960), созданном в Манчестерском университете.

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

Перевод виртуального адреса в реальный адрес во время выполнения процесса называется динамическим преобразованием адресов. Адреса, смежные в V (виртуальное пространство), необязательно будут смежными в R (реальное пространство). Таким образом, пользователь освобождается от необходимости учитывать размещение своих процедур и данных в реальной памяти.

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

Системы виртуальной памяти требуют наличия таблиц отображения виртуального адреса в реальный. Главная задача разработчиков систем - это минимизация количества информации отображения при удовлетворительных скоростных характеристиках системы. Эта цель достигается поблочным отображением: информация группируется в блоки и система следит за тем, в каких местах реальной памяти размещаются различные блоки из виртуального пространства. Блоки фиксированного размера называются страницами; блоки переменного размера называются сегментами. В некоторых системах оба вида блоков комбинируются - применяются сегменты, состоящие из целых страниц. Адреса рассматриваются как упорядоченные пары

V=(b,d),

где b - номер блока с виртуальным адресом, d - смещение адреса относительно начала блока b. Таблица отображения блоков обычно хранится в кэш-памяти.

Преобразование виртуального адреса в реальный

Реальный адрес a таблицы загружается в специальный регистр начального адреса таблицы блоков. Таблица содержит по одной строке для каждого блока процесса, причем эти строки идут в порядке возрастания номеров (блок 0, блок 1, ...). Номер блока суммируется с адресом а, образуя реальный адрес строки таблицы для блока b. Эта строка содержит реальный адрес b' блока в реальной памяти. К b' прибавляется смещение d и образуется реальный адрес r=b'+d.

Регистр начального

 

 

адреса таблицы блоков

 

 

+---

+

 

 

¦ а ¦

 

 

+---

+

+---------

+

a

b +-----

+- b ¦ d ¦ Виртуальный адрес v=(b,d)

11

+-+---------

 

+

+---------

+

 

 

¦+¦

+-----------

 

+

¦

 

 

+-+

 

¦

¦d

 

 

¦

¦¦

 

¦

 

Реальный адрес

a+b¦

+-----------

 

¦ b'

+-+

+-------

+

+----

¦ l ¦

 

¦ b'+-----

¦++-----

¦

r ¦

 

+-----------

 

+

+-+

+-------

+

 

¦

 

¦

 

 

 

длина блока

 

адрес блока

 

 

 

 

 

в реальной памяти

 

 

Существует два

 

наиболее распространенных способа реализации

виртуальной памяти - страничный и сегментный.

Страничная организация

Виртуальное и реальное адресные пространства делятся на страницы одинаковых размеров - страничные кадры. Виртуальный адрес V=(p,d) содержит номер страницы р и смещение в странице d. Процесс может выполняться, если страница с требуемым адресом находится в реальной памяти. Страничные кадры реальной памяти начинаются с адресов, кратных фиксированному размеру страницы. Страница из V может быть размещена в любом кадре.

Процесс обращается по виртуальному адресу V. В таблице отображения ищется номер страницы p и определяется адрес в R страничного кадра p', а затем r, с учетом смещения d. Таблица отображения состоит из элементов, которые содержат номера страниц, в нас-

тоящий момент размещенных

в памяти. Строка таблицы:

+---------------------------------------------

 

 

 

+

¦ i ¦

S

¦

p'

¦

+---------------------------------------------

 

 

 

+

i - бит присутствия страницы в R (0 - нет, 1 - есть); S - адрес страницы во внешней памяти (при i=0); p'- номер страничного кадра в R (при i=1). Адрес R, с которого начинается кадр p' при размере страницы l определяется как

r = l*p' + a .

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

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

Сегментная организация

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

Странично-сегментная организация

 

Виртуальный адрес состоит из трех компонент

V=(s,p,d), где

s - номер сегмента, p - номер страницы в сегменте

s, d - смещение

в странице p. Преобразование адреса требует две таблицы отображения: таблицу сегментов и таблицу страниц:

1) определяется расположение в памяти таблицы сегментов;

2)по номеру сегмента s отыскивается его дескриптор и определяется базовый адрес таблицы страниц сегмента;

3)Номер страницы p прибавляется к базовому адресу, что позволяет определить дескриптор страницы, а значит и номер страничного кадра в реальной памяти;

4)С учетом смещения d находится реальный адрес.

Такая схема применяется в ОС, которые используют защищенный режим процессора Intel и механизм трансляции страниц, поддержива-

емых этим режимом (Windows 95, Windows NT).

ДВУХСТУПЕНЧАТАЯ СХЕМА ПРЕОБРАЗОВАНИЯ АДРЕСА

На первом шаге логический адрес, состоящий из 16-иразрядного селектора и 32-хразрядного смещения преобразуется в так называемый линейный адрес.

 

Логический адрес

 

 

 

¦

 

 

 

V

 

+-------------------------------------

 

 

+

¦

селектор ¦

смещение

¦

+-------------------------------------

 

 

+

¦

GDT(LDT)

 

¦

 

16 /

+-----------

+

/

32

¦

+-----------

¦ 32

¦

 

+-----

>+-----------

+--/--

> +

 

 

+-----------

¦

¦

 

 

+-----------

¦

/

32

 

+-----------

¦

¦

 

 

+-----------

¦

¦

 

 

+-----------

+

V

 

линейный адрес

Линейный адрес выбирается из дескриптора, на который указывает селектор. Линейный адрес представляет собой структуру, состоящую из 3 полей:

·индекса в каталоге таблиц страниц;

·индекса в таблице страниц;

·смещения на странице.

+-------------------------------------------------------

 

 

 

+

¦индекс в каталоге ¦индекс в таблице

¦

смещение в

¦

¦ таблиц страниц ¦

страниц

¦

странице

¦

+-------------------------------------------------------

 

 

 

+

10

10

 

12

 

В системе может содержаться произвольное

количество

катало-

гов таблиц страниц. Адрес каталога, в котором

производится поиск,

12

содержится в регистре CR3. Элементами каталога являются дескрипторы, описывающие таблицы страниц. Формат дескриптора:

 

+--------------------------------------

 

+

 

¦адрес таблицы

¦ AVL¦ 0 ¦D¦A¦ 0 ¦U¦W¦P¦

 

¦ страниц

¦

¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦

 

+--------------------------------------

 

+

 

1F

C B -9 8-7 6 5 4-3 2 1 0

P

- присутствие таблицы страниц в памяти;

W

- разрешение записи в страницы;

U

- страницы супервизора (0) или пользователя (1);

A

- доступ: устанавливается в 1 перед записью или чтением;

D

- устанавливается в 1 если была выполнена запись в таблицу;

AVL

- зарезервированы за ОС.

 

С помощью индекса в каталоге таблиц отыскивается адрес таб-

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

+------------------------------------------------------------+

¦Защита ¦ Физический адрес страницы ¦Файл страниц ¦ Состояние¦

+------------------------------------------------------------

 

 

 

+

 

5

20

4

3

 

Устанавливая соответствующим образом биты защиты, операцион-

ная

система

может отметить страницу как доступную для чтения и

записи, только для чтения или как недоступную. В поле "Файл страниц" содержится номер файла подкачки, в котором размещена страница. Младшие биты описывают состояние страницы памяти:

·страница находится в переходном состоянии;

·страница обновлена, но не сохранена в файле страниц;

·страница присутствует в памяти.

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

·Свободная - доступна для использования после ее заполнения нулями;

·Заполненная нулями - свободная страница, заполненная нулями и доступная для использования процессами;

·Правильная - используется активным процессом;

·Измененная - содержимое страницы было изменено, однако страница еще не сохранена в файле страниц;

·Запасная - страница удалена из рабочего набора страниц процесса;

·Плохая - при обращении к странице возникла аппаратная ошибка.

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

+-----------------------------------------------------

 

 

 

 

 

+

¦таблица

 

¦ страница

 

 

¦ смещение

¦

+-----------------------------------------------------

 

 

 

 

 

+

10 /

 

 

10 /

 

 

12 /

¦

+-----------

+

¦

+

--------+

¦

¦

+-----------

¦

¦

+

--------¦

¦

¦

+-----------

¦

¦

+

--------¦

V

 

+--

>+-----------

+-----

+

+-->+--------

+---

>+

адрес

+-----------

¦

¦

+--------

¦

¦

каталога

+-----------

¦

¦

+--------

¦

¦

+-----

+

+-----------

¦

¦

+--------

¦

¦

¦

CR3 +--

>+-----------

+

+-----

>---------

+

V

+-----

+ каталог

таблица

физический

 

таблиц

страниц

адрес

 

страниц

 

 

Вычисление адреса страницы часто называют трансляцией страниц. Трансляция страниц выполняется в том случае, если старший бит CR0 установлен в 1. Если же он сброшен в 0, то адрес из локальной или глобальной таблицы считается базовым, к нему прибавляется смещение и полученный адрес является физическим.

Сплошная модель памяти FLAT

Сплошная модель памяти FLAT реализует виртуальную концепцию адресации в ОС Windows 95 и Windows NT. В соответствии с этой моделью каждому процессу выделяется виртуальное адресное пространство протяженностью 4Гб.

0xFFFFFFFF

+-----------------

 

+

 

 

¦

 

¦

 

 

¦

 

¦ Зарезервировано

 

¦

 

¦

для ОС

 

¦

2Гб

¦

 

 

¦

 

¦

 

 

¦

 

¦

 

 

¦

 

¦

 

0x80000000

+-----------------

 

¦

 

 

¦

64К

¦

 

0x7FFF0000

+-----------------

 

¦

 

 

¦

 

¦

 

 

¦

 

¦

 

 

¦

2Гб - 128К

¦

Доступно

 

¦

 

¦

процессу

 

¦

 

¦

 

0x0000FFFF

+-----------------

 

¦

 

 

¦

64К

¦

 

0x00000000

+-----------------

 

+

 

Из них 2Гб зарезервировано за ОС, а за пользовательским процессом закреплено пространство протяженностью 2Гб - 128 Кб, расположенное в области младших адресов. Блоки по 64 Кб используются для контроля за правильностью указателей. Физически виртуальное адресное пространство реализуется в виде файлов подкачки страниц, которые размещаются на внешних накопителях. Всего может быть создано до 16 файлов подкачки.

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

Функции для доступа к виртуальной памяти

13

У процесса есть две возможности заказать себе страницу виртуальной памяти:

1)резервировать диапазон адресов в виртуальном адресном пространстве;

2)получить в пользование страницу виртуальной памяти.

Оба способа реализуются одной и той же функцией:

LPVOID VirtualAlloc(LPVOID lpvAddress,

DWORD

cbSize,

DWORD

fdwAllocationType,

DWORD

fdwProtect);

первый параметр - адрес области, резервируемой и/или передаваемой в пользование. При резервировании это значение должно быть равно нулю (NULL);

второй параметр - размер области в байтах;

третий параметр - способ получения

MEM_RESERVE

- зарезервировать

MEM_COMMIT

- выделить с обнулением

MEM_TOP_DOWN

- выделить в пространстве верхних адресов

 

(под стек);

четвертый параметр - флаги доступа

PAGE_READWRITE

- разрешает чтение и запись

PAGE_READONLY

- разрешает только чтение

PAGE_EXECUTE

- выполнение

PAGE_EXECUTE_READ

- разрешает выполнение и чтение блока

PAGE_EXECUTE_READWRITE

- полный доступ

PAGE_NOACCEESS

- нет доступа, можно определить только

 

состояние блока

PAGE_GUARD

- сигнализация доступа к странице

PAGE_NOCACHE

- отмена копирования страницы для этого

 

блока

 

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

Освобождение виртуальной памяти

BOOL VirtualFree (LPVOID lpvAddress,

DWORD

cbSize,

DWORD

fdwFreeType);

Функции передаются адрес и размер освобождаемой области.

Третий параметр может иметь значения:

MEM_RELEASE

- освободить

MEM_DECOMMIT

- вернуть в зарезервированное состояние.

Фиксирование страниц основной памяти

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

BOOL VirtualLock (LPVOID lpvAddress,

DWORD cbSize);

Расфиксирование страниц выполняется следующей функцией:

BOOL VirtualUnlock (LPVOID lpvAddress,

DWORD cbSize);

Страницы возвращаются ОС и могут быть переданы другому процессу. По умолчанию процесс не может зафиксировать более 30 страниц основной памяти. Установка числа страниц, доступных для фиксиро-

вания, выполняется функцией:

BOOL SetProcessWorkingSetSize (HANDLE hProcess, DWORD dwMinSize, DWORD dwMaxSize);

позволяет для процесса (1 параметр) установить минимальное и максимальное число страниц основной памяти. Текущее число страниц может быть получено следующим образом:

BOOL GetProcessWorkingSetSize (HANDLE hProcess, LPDWORD lpdwMinSize, LPDWORD lpdwMaxSize);

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

СТРАТЕГИИ УПРАВЛЕНИЯ ВИРТУАЛЬНОЙ ПАМЯТЬЮ

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

СТРАТЕГИИ ВТАЛКИВАНИЯ реализуют перенесение страницы из виртуального в реальное адресное пространство. Их цель - определить, в какой момент следует переписать страницу или сегмент из внешней памяти в основную. Применяются следующие подходы:

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

14

ния памятью; б) упреждающее вталкивание. По этой стратегии в основную па-

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

СТРАТЕГИИ РАЗМЕЩЕНИЯ должны определить место в реальной памяти для размещения очередного поступающего сегмента или страницы из виртуальной памяти. В системах со страничной памятью решение о размещении принимается достаточно тривиально, поскольку поступающая страница может быть помещена в любой свободный страничный кадр. В системах с сегментной организацией виртуальной памяти требуется использование более развитых средств размещения. Это обусловлено необходимостью борьбы с фрагментацией реальной памяти компьютера. Чаще всего применяются:

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

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

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

СТРАТЕГИИ ВЫТАЛКИВАНИЯ. Целью этих стратегий является обеспечение процедуры смены блоков (страниц или сегментов), принадлежащих различным процессам, в реальной памяти. Необходимость выталкивания из основной памяти в виртуальное пространство обусловлена различной протяженностью реального адресного пространства компьютера и суммы виртуальных адресных пространств действующих процессов. Выталкивание позволяет разместить поступающие блоки, даже если реальная память полностью занята.

Рассмотрим следующие подходы:

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

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

в) FIFO (First In - First Out). Выталкивается та страница, которая дольше остальных находится в памяти. Аргумент для применения такой стратегии весьма существенен: у выталкиваемой страницы уже был высокий шанс использования, и пора дать подобные возможности другой странице. К сожалению, стратегия FIFO с большой вероятностью будет приводить к замещению активно используемых страниц, поскольку тот факт, что страница находится в основной

памяти в течении длительного времени, может означать, что она постоянно в работе. Если ее вытолкнуть из основной памяти по принципу FIFO, ее почти немедленно придется вталкивать обратно.

Исследователями была обнаружена аномалия, присущая стратегии FIFO: при увеличении количества страничных кадров, выделенных процессу, возможно увеличение числа прерываний по отсутствию страницы в реальной памяти. Рассмотрим пример. Процесс в течении некоторого времени работает со страницами A, B, C, D и E. Последовательность работы со страницами определена левым столбцом на рисунке. В первом случае процессу выделено 3 страничных кадра, во втором - 4. При отсутствии страницы в памяти возникает прерывание. Подсчитаем количество прерываний:

----------------------------------------------------------------

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

+

 

¦

 

 

 

 

 

 

 

Варианты

 

 

 

 

 

 

 

¦

Стра-+----------------------------------------------------------

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

¦

ница ¦

 

 

 

1

 

 

 

¦

 

 

 

2

 

 

 

 

¦

 

+------------------------

 

 

 

 

 

 

 

+---------------------------------

 

 

 

 

 

 

 

 

¦

 

¦Преры-¦

 

 

Кадры

 

 

¦Преры-¦

 

 

Кадры

 

 

 

 

¦

 

¦вание +-----------------

 

 

 

 

 

¦вание +--------------------------

 

 

 

 

 

 

 

¦

 

¦

 

¦ 1 ¦ 2 ¦ 3 ¦

¦ 1 ¦ 2 ¦ 3 ¦ 4 ¦

-----+------

 

+-----

 

+

-----

+-----

 

+------

+------

 

+------

 

+------

 

+-----

 

¦

A

¦

есть ¦

A

¦

-

¦

-

¦ есть ¦

A

¦

-

¦

-

¦

-

¦

B

¦

есть ¦

A

¦

B

¦

-

¦ есть ¦

A

¦

B

¦

-

¦

-

¦

C

¦

есть ¦

A

¦

B

¦

C

¦ есть ¦

A

¦

B

¦

C

¦

-

¦

D

¦

есть ¦

D

¦

B

¦

C

¦ есть ¦

A

¦

B

¦

C

¦

D

¦

A

¦

есть ¦

D

¦

A

¦

C

¦ нет

¦

A

¦

B

¦

C

¦

D

¦

B

¦

есть ¦

D

¦

A

¦

B

¦ нет

¦

A

¦

B

¦

C

¦

D

¦

E

¦

есть ¦

E

¦

A

¦

B

¦ есть ¦

E

¦

B

¦

C

¦

D

¦

A

¦

нет

¦

E

¦

A

¦

B

¦ есть ¦

E

¦

A

¦

C

¦

D

¦

B

¦

нет

¦

E

¦

A

¦

B

¦ есть ¦

E

¦

A

¦

B

¦

D

¦

C

¦

есть ¦

E

¦

C

¦

B

¦ есть ¦

E

¦

A

¦

B

¦

C

¦

D

¦

есть ¦

E

¦

C

¦

D

¦ есть ¦

D

¦

A

¦

B

¦

C

¦

E

¦ нет

¦

E

¦

C

¦

D

¦ есть ¦

D

¦

E

¦

B

¦

C

¦

----------------------------------------------------------------

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

+

 

 

9

 

 

 

 

 

 

10

 

 

 

 

 

 

 

 

 

г) LRU (Least Recently Used). Выталкивается та страница, которая дольше не использовалась; Эта стратегия требует, чтобы при каждом обращении к странице обновлялась связанная с ней временная метка. Процедура выталкивания может найти страницу с максимальным значением временной метки.

д) LFU (Least Frecuently Used).- Эта стратегия нацелена на выталкивание той страницы, которая реже использовалась. Здесь контролируется интенсивность использования страницы. Однако, велика вероятность, что наименее интенсивно используемой окажется страница, которая только что была загружена в основную память и к которой было только одно обращение.;

е) NUR (Not Used Recently). Стратегия обеспечивает выталкивание страницы, которая не использовалась в последнее время. Эта стратегия близка к LRU и характеризуется малыми издержками. Основанием для применения стратегии считается следующее утверждение: к страницам, которые в последнее время не использовались, вряд ли

15

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

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

A - доступ (обращение): устанавливается в 1 перед записью или чтением;

D - модификация: устанавливается в 1 если была выполнена запись в таблицу.

Первоначально биты-признаки для всех страниц устанавливаются в 0. При обращении к какой-либо странице бит A устанавливается в 1, а в случае изменения содержимого страницы устанавливается D=1. Когда нужно выбрать страницу для выталкивания, находят страницу, к которой не было обращений (A=0). Если таких страниц нет, ищем страницу, у которой D=0.

В системах с разделением времени основная память работает активно, так что очень скоро у всех страниц бит обращения будет установлен в 1. Один из широко используемых методов решения этой проблемы заключается в том, что все биты обращений немодифицированных страниц периодически сбрасываются в 0.

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

Определение оптимального размера страниц

От выбора размера страниц зависит эффективность вычислительного процесса.

Вот некоторые соображения, которые позволят принять решение разработчику системы управления виртуальной памятью:

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

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

3.Обмен данными с дисковой памятью более эффективен при большом размере страниц.

4.Свойство локальности распространяется на небольшие участ-

ки.

5.При малых размерах страниц потери памяти на внутреннюю фрагментацию (то есть наличие не полностью занятых страниц) уменьшаются.

В целом страницы должны быть небольшими (не более 1К слов).

Поведение программ при подкачке страниц

Результаты экспериментов:

1. В начале выполнения процесса происходит быстрое обращение

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

2.Количество прерываний по отсутствию нужной страницы увеличивается с увеличением размера страницы при постоянном объеме реальной памяти.

3.Частота прерываний по отсутствию нужной страницы уменьшается с увеличением количества кадров, выделенных процессом.

4.Число команд, выполняемых на странице, обычно не велико (<=200 команд на странице в 1К слов).

УПРАВЛЕНИЕ ПРОЦЕССАМИ

Просто удивительно, что Природе удалось сравнительно спокойно пройти свой счастливый процесс развития среди такой дьявольской кутерьмы

(Стивен Крейн) Процессом называется программа (приложение) в стадии выполнения. Каждый процесс имеет свое адресное пространство. В период своего существования процесс проходит через ряд дискретных состо-

яний:

-процесс находится в состоянии выполнения, если в данный момент ему выделен центральный процессор;

-процесс находится в состоянии готовности, если он мог бы сразу использовать центральный процессор, предоставленный в его распоряжение;

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

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

Заблокированные процессы переводятся в список готовых процессов по мере наступления событий, которых они ожидают.

Для повышения гибкости управления процессами в некоторых системах вводят два дополнительных состояния:

- приостановлен-заблокирован - приостановлен-готов.

С помощью этих состояний процессы временно исключаются из списков готовых и заблокированных процессов.

Переход процесса из одного состояния в другое

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

16

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

 

+----------

+

 

Запуск+---------------

¦Выполнение+--------

+Блокирование

¦

+----------

+

¦

¦

Истечение¦кванта

¦

+-----

+-----------------

+

+

----------+

¦Готов¦-----------------------------

 

¦Блокировка¦

+-----

+

Пробуждение

+----------

+

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

Единственная смена состояния, инициируемая самим процессом - это блокирование, остальные три смены состояния инициируются объектами, внешними по отношению к данному процессу.

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

 

 

+----------

+

 

 

Запуск+---------------

 

¦Выполнение+--------

 

+Блокирование

¦

 

+----------

+

 

¦

¦

 

Истечение¦кванта

 

¦

+-----

+-----------------

+

 

+----------

+

¦Готов¦-----------------------------

 

 

¦Блокировка¦

+-----

+

Пробуждение

+----------

+

------------ ¦ -----------------------------------

 

 

 

 

¦ ------------

Приостановка ¦ Возобновление

Приостановка

¦Возобновление

+--------------

 

+

+

--------------+

¦Приостановлен-¦

¦Приостановлен-¦

¦

готов

¦

¦

блокирован ¦

+--------------

+

+

--------------+

БЛОК УПРАВЛЕНИЯ ПРОЦЕССОМ (PCB)

Представителем процесса в ОС является PCB (Process Control Block). Это структура данных, содержащая информацию о процессе:

-текущее состояние процесса;

-уникальный идентификатор процесса;

-приоритет процесса;

-указатели памяти процесса;

-указатели выделенных процессу ресурсов;

-область сохранения регистров, заполняющаяся в момент перевода процесса из одного состояние в другое.

Для ускорения выполнения операций в PCB предусматриваются аппаратно реализованные команды загрузки информации в PCB и выбора этой информации.

ОСНОВНЫЕ ОПЕРАЦИИ НАД ПРОЦЕССАМИ

1.Создание.

2.Уничтожение.

3.Приостановка.

4.Возобновление.

5.Изменение приоритета.

6.Блокировка.

7.Пробуждение.

8.Запуск.

Каждая операция может включать ряд стадий. Например, создание процесса состоит из:

-присвоения имени;

-включения имени в список;

-определения начального приоритета;

-формирования РСВ;

-выделения начальных ресурсов.

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

Управление асинхронными параллельными процессами

Человек, имеющий одни часы, всегда может с уверенностью сказать, сколько времени, - и этим выгодно отличается от того, у кого двое часов

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

17

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

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

суверенностью, что ошибка устранена.

Вязыках программирования предусматриваются конструкции для указания параллелизма. Эти конструкции, как правило, представляют следующие парные операторы:

· оператор, указывающий, что последовательное течение программы должно быть разделено на несколько параллельно выполняемых последовательностей;

· оператор, указывающий, что параллельно выполняемые последовательности должны слиться воедино.

Примером может служить пара parbegin/parend. В общем виде конструкция для указания параллелизма имеет вид

parbegin

оператор1; оператор2;

:..

операторN parend;

Например,рассмотрим выражение для корня квадратного уравне-

ния:

x:= ( -b + sqrt ( sqr(b) - 4*a*c )) / ( 2*a );

 

Последовательный код:

¦

Параллельный код:

 

 

¦

 

 

1.

t1:= sqr(b);

¦

1.

parbegin

2.

t2:= 4*a;

¦

 

t1:= -b;

3.

t2:= t2*c;

¦

 

t2:= sqr(b);

4.

t1:= t1 - t2;

¦

 

t3:= 4*a;

5.

t1:= sqrt(t1);

¦

 

t4:= 2*a;

6.

t2:= -b;

¦

 

parend;

7.

t1:= t2 + t1;

¦

2.

t5:= t3*c;

8.

t2:= 2*a;

¦

3.

t5:= t2 - t5;

9.

x:= t1/t2;

¦

4.

t5:= sqrt(t5);

 

 

¦

5.

t5:= t1 + t5;

 

 

¦

6.

x:= t5/t4;

Мультизадачность

Виды мультизадачности:

Переключательная мультизадачность. Этот вид характеризуется тем, что передача центрального процессора от одной задачи другой выполняется при наступлении некоторого внешнего события (внешнего по отношению к ОС). Такой вид мультизадачности был реализован в

MS-DOS.

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

приоритетом (ЦП не может быть принудительно отобран у какого-либо приложения).

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

Процессы и задачи

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

Распределение времени между задачами

В современных операционных системах используется приоритетное планирование задач, когда и процессы и задачи имеют свои уровни приоритетов. ОС может в небольших пределах изменять текущий приоритет задач для повышения общей производительности. Рассмотрим принципы планирования на примере Windows NT.

Приоритеты устанавливаются в диапазоне от 1 до 31. Используется двухступенчатая схема назначения приоритетов:

1)для процесса устанавливается класс приоритета;

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

+---------------------------------------------------------------

 

 

+

¦ Классы приоритета

¦

Приоритеты

¦

+-------------------------

+-------------------------------------

 

¦

¦ REALTIME_PRIORITY_CLASS

¦ 24

- процессы реального времени

¦

¦ HIGH_PRIORITY_CLASS

¦ 13

- высокоприоритетные процессы

¦

¦ NORMAL_PRIORITY_CLASS

¦ 7

или 9 - прикладные процессы

¦

¦ IDLE_PRIORITY_CLASS

¦ 4

- низкоприоритетные процессы

¦

+---------------------------------------------------------------

 

 

+

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

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

NORMAL_PRIORITY_CLASS устанавливается процессам по умолчанию. Если процесс с классом NORMAL_PRIORITY_CLASS выполняется в фоновом режиме, то ему устанавливается уровень приоритета 7. При выводе окна приложения на передний план его приоритет повышается до 9.

18

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

Относительные приоритеты задач

Приоритет задачи устанавливается относительно приоритета процесса. Возможно 7 уровней приоритета:

THREAD__PRIORITY_TIME_CRITICAL

15 или 31

 

 

 

(если класс приоритета - REALTI-

 

ME_PRIORITY_CLASS,

то тогда за-

 

дача

получает приоритет 31,

во

 

всех остальных случаях - 15)

 

THREAD__PRIORITY_HIGHEST

+2

 

 

 

THREAD__PRIORITY_ABOVE_NORMAL

+1

 

 

 

THREAD__PRIORITY_NORMAL

0

 

 

 

THREAD__PRIORITY_BELOW_NORMAL

-1

 

 

 

THREAD__PRIORITY_LOWEST

-2

 

 

 

THREAD__PRIORITY_IDLE

1 или 16

 

 

 

(если класс приоритета - REALTI-

 

ME_PRIORITY_CLASS,

то тогда за-

 

дача

получает приоритет 16,

во

 

всех остальных случаях - 1)

 

Процессовая мультизадачность

Запуск процесса:

BOOL CreateProcess (LPCTSTR lpApplicationName, LPTSTR lpCommandLine,

LPSECURITY_ATTRIBUTES lpProcessAttr, LPSECURITY_ATTRIBUTES lpThreadAttr, BOOL bInheritHandles,

DWORD dwCreationFlags, LPVOID lpEnvironment, LPCTSTR lpCurrentDirectory, LPSTARTUPINFO lpStartupInfo,

LPPROCESS_INFORMATION lpProcessInfo);

Первый параметр должен описывать строку, содержащую путь и имя исполняемого файла приложения. Второй параметр передает командную строку. Если имя файла приложения задано с помощью lpApplicationName, второй параметр может иметь значение NULL.

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

Через параметр dwCreationFlags можно указать флаги создания процесса:

CREATE_SUSPENDED - приостанов главной задачи при создании; DEBUG_PROCESS - отладочный процесс;

DEBUG_ONLY_THIS_PROCESS - информация предку передается только об этом процессе;

CREATE_UNICODE_ENVIRONMENT - для блока среды применяется кодиров-

ка UNICODE;

CREATE_NEW_CONSOLEдля нового процесса создается своя консоль; DETACHED_PROCESS - процесс не имеет доступа к родительской консоли (не совместим с предыдущим флагом);

CREATE_SEPARATE_WOW_VDM - для процесса создается отдельная виртуальная машина DOS;

CREATE_DEFAULT_ERROR_MODE - процесс не наследует режим обработки ошибок, установленный предком;

REALTIME_PRIORITY_CLASS HIGH_PRIORITY_CLASS NORMAL_PRIORITY_CLASS IDLE_PRIORITY_CLASS

Последние четыре флага устанавливают класс приоритета процесса.

Параметр lpEnvironment служит для передачи адреса блока среды MS DOS. Блок среды содержит набор текстовых строк вида "Параметр=значение".

Следующий параметр lpCurrentDirectory - это строка, содержащая путь до текущей директории.

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

DWORD cb; // размер структуры в байтах

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

Функция

VOID ExitProcess (UINT uExitCode);

в которой предку передается установленный параметром uExitCode код завершения, предназначена для самозавершения процесса.

Функция принудительного завершения процесса с указанным первым параметром идентификатором

BOOL TerminateProcess (HANDLE hProcess, UINT uExitCode);

также позволяет передать код завершения.

Потоковая мультизадачность

Функция запуска задачи:

HANDLE CreateThread (LPSECURITY_ATTRIBUTES lpThreadAttr, DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddr, LPVOID lpParameter,

DWORD dwCreationFlags, LPDWORD lpThreadId);

1 параметр - указатель на структуру типа SECURITY_ATTRIBUTES содержит параметры для установки характеристик системы защиты. Стандартные характеристики системы задаются при передаче значения

NULL;

2 параметр - размер стека для задачи; передача нулевого значения

19

этого параметра

означает, что стек задачи равен стеку процесса

или вызывающей задачи;

 

3

параметр - указатель на функцию, которая начинает выполнение

задачи;

 

 

4

параметр - параметр стартовой функции;

5

параметр - флаги создания, устанавливающие режим, в котором бу-

дет работать задача:

 

 

0

 

- немедленное выполнение;

 

CREATE_SUSPENDED

- загрузка и приостанов задачи;

6

параметр - указатель на переменную, которая будет содержать

системный номер задачи.

 

 

Функция при успешном завершении возвращает идентификатор за-

дачи типа HANDLE. При аварийном завершении возвращает NULL.

 

Для установки

и

определения приоритетов используются функ-

ции:

 

 

BOOL SetThreadPriority (HANDLE hThread, int iPriority);

Значением параметра int iPriority может быть любой из семи уровней приоритета задачи.

int GetThreadPriority (HANDLE hThread); - получение текущего при-

оритета.

Чтобы управлять приостановкой и возобновлением задач имеется три функции:

DWORD

SuspendThread (HANDLE hThread); - приостановка задачи

DWORD

ResumeThread (HANDLE hThread); - возобновление задачи

VOID

Sleep (DWORD cMilliseconds); - временная самоприостановка

ОС ведет для каждой задачи счетчик приостановок, который увеличивается при каждом выполнении SuspendThread и уменьшается при возобновлении. В случае ошибки первая и вторая функции возвращают: 0xFFFFFFFF. Возможна самоприостановка, заданная на бесконечное время (INFINITE).

Завершение задачи:

VOID ExitThread (DWORD dwExitCode);

Код завершения передается предку.

Чтобы предок мог получить код завершения, следует запросить его функцией

BOOL GetExitCodeThread (HANDLE hThread,

LPDWORD lpExitCode);

После того, как задача завершится, необходимо освободить идентификатор:

BOOL CloseHandle (HANDLE hThread);

Синхронизация задач

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

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

Ожидание завершения задачи или процесса

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

DWORD WaitForSingleObject (HANDLE hObject, DWORD dwTimeOut);

Первым параметром передается идентификатор объекта, вторым - время таймаута, в течении которого следует ждать изменения состояния идентификатора. Если передать dwTimeOut = INFINITE, то время ожидания будет бессрочным. В качестве идентификатора можно передавать идентификаторы задач, процессов, событий, файлов и других объектов.

Функция возвращает

WAIT_FAILED при ошибке;

WAIT_OBJECT_0 при достижении отмеченного состояния; WAIT_TIMEOUT при истечении таймаута;

WAIT_ABANDONED при принудительном завершении ожидания.

Ожидание завершения нескольких задач или процессов

DWORD WaitForMuitipleObject (DWORD cObject,

HANDLE*1phObject,

BOOL fWaitAll,

DWORD dwTimeOut);

Первый параметр - это количество элементов массива идентификаторов. Второй параметр содержит указатель на массив идентификаторов. Третий параметр - тип ожидания. Если параметр установлен в значение True, то ожидание завершается при завершении всех задач, т.е. когда все идентификаторы переведены в состояние signed. Если установлено значение False, то функция завершается при переключении хотя бы одного идентификатора в отмеченное состояние. Коды завершения этой функции практически те же, за исключением нормального и принудительного завершения. При нормальном завершении функция возвращает результат в диапазоне от WAIT_OBJECT_0 до (WA- IT_OBJECT_0+cObject-1), которое в зависимости от значения параметра fWaitAll означает, что либо все идентификаторы перешли в отмеченное состояние, либо за вычетом WAIT_OBJECT_0 равно индексу идентификатора отмеченного объекта. Аналогично код принудительного завершения возвращается в диапазоне от WAIT_ABANDONED_0 до

(WAIT_ABANDONED_0+cObject-1).

20

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