Как уже отмечалось, компилятор Watcom C генерирует код, использующий преимущества архитектуры процессоров 80386 и 80486. Он использует 32-битовые ближайшие указатели (near pointers) и 4-байтовые целые числа. Использование 32-битовых указателей делает концепцию моделей памяти (Tiny, Small, Compact, Medium, Large, Huge и т. д.) во многом ненужной. NLM-модули компилируются для непрерывной модели памяти с абсолютной адресацией ("плоской" модели), в которой сегментация памяти гораздо менее важна, чем в других. Однако 32-битового указателя достаточно для адресации всей доступной памяти. Кроме того, компилятор генерирует код, выполняемый в виртуальном режиме (для NetWare 4.х).
Таким образом, основная память файлового сервера NetWare интерпретируется как один большой сегмент, но идентифицируется для использования NLM с помощью функций распределения.
Когда процесс (нить) запрашивает память, ему выделяется пул памяти. Этот пул может быть освобождён, но оставлен в пуле процесса, либо освобождён и возвращён в системный пул.
Когда запрашивается память, NetWare использует три массива указателей для определения того, где находится доступная память. Это массивы отслеживают блоки доступной памяти. Первый массив отслеживает блоки с 16-байтовыми приращениями от 16 байтов до 1024 байтов каждый. Второй массив отслеживает блоки с 256-байтовыми приращениями. Третий массив указателей отслеживает блоки, превышающие 4 Кб. Основываясь на размере запрошенной NLM-модулем памяти, NetWare выполняет поиск в соответствующем массиве, пока не находит затребованный объём памяти.
В NetWare 4.х внесены следующие улучшения:
Таблица 2.13. SET-параметры, регулирующие "сбор мусора" в NetWare 4.х
SET-параметр | Значение по умолчанию | Границы изменения | Примечания | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Garbare Collection Interval | 15 мин. | 1 мин. - 1 час | Определяет максимальный интервал времени между "чистками" памяти. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Number of Frees for Garbare | 1000 | 100 - 10000 | Определяет минимальное число освобождений памяти для запуска системной программы чистки памяти. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Minimum Free Memory for Garbare Collection | 8000 | 1000-1000000 | Определяет минимальный размер освобождаемой памяти для запуска программы чистки памяти. |
Обработка, которая встречается в многозадачных сетевых операционных системах, основывается на одной из двух моделей использования центрального процессора (ЦП) - модели с приоритетами или модели без приоритетов (невытесняющая многозадачность).
Большинство многозадачных сетевых операционных систем, таких, как OS/2 и UNIX, являются системами, где поддерживается модель с приоритетами. Предположим, что в одной из этих ОС выполняются две задачи (рисунок 2.33 а), причём задача 2 имеет более высокий приоритет, чем задача 1.
После операции с диском (чтение или запись) операционная система активизирует задачу 2, имеющую более высокий приоритет (рисунок 2.33 а, точка 1). При этом задача 1 прерывается (вытесняется) и переходит в состояние ожидания. Если для задачи 2 требуется выполнить операцию с диском, то операционная система приостановит её и передаёт управление задаче 1 (рисунок 2.33 а, точка 2) и т. д.
Рис. 2.33. Схемы переключения процессов
(а - для модели с приоритетами, б - для модели без приоритетов)
Многозадачная сетевая операционная система NetWare является системой, где поддерживается модель без приоритетов (невытесняющая многозадачность). Если какая-либо задача (нить) выполняет функцию ThreadSwitch, то ОС помещает её в конец очереди RunList и передаёт управление другой задаче (рисунок 2.33 б, точки 1,2).
Укажем преимущества и недостатки рассмотренных моделей использования центрального процессора.
В системах с приоритетами необходимо перед обновлением ресурсов (областей основной памяти, записей файлов и т. д.) выполнить их блокировку (рисунок 2.34 а, точки 1, 2, 3, 4).
Это связано с тем, что задача может быть прервана в любой момент времени. Но, во-первых, на блокировку и разблокировку разделяемых ресурсов тратится процессорное время, что снижает производительность системы. Во-вторых, при использовании блокировок часто возникают тупиковые ситуации.
Предположим, что задача 1 заблокировала запись 1 какого-либо файла (рисунок 2.34 а, точка 1) и была прервана задачей 2. Пусть задача 2, в свою очередь, блокирует запись 2 (точка 2). При попытке заблокировать запись 1 задача 2 переходит в состояние ожидания, так как эта запись уже заблокирована задачей 1. Управление передаётся задаче 1, которая пытается блокировать запись 2 и переходит в состояние ожидания, так как эта запись уже была заблокирована задачей 2. Таким образом, ни одна из задач (1 и 2) не может продолжить выполнение из-за возникшей тупиковой ситуации.
Преимуществом системы с приоритетами является то, что при выполнении операции с диском процессор переключается на выполнение другой задачи.
В NetWare, где поддерживается модель использования процессора без приоритетов, переключение на другую задачу планирует сама программа (NLM-модуль), используя команду ThreadSwitch в подходящий момент. Т. е. задача 1 может выполнить все требуемые обновления в разделяемых записях 1 и 2, а затем передать управление другой нити с помощью команды ThreadSwitch (рисунок 2.34 б). В этом случае нет необходимости в использовании блокировок ресурсов. Это, во-первых, повышает быстродействие системы, а, во-вторых, устраняет возможность возникновения тупиковых ситуаций.
Рис. 2.34. Схемы использования разделяемых ресурсов
(а - для модели с приоритетами, б - для модели без приоритетов)
Недостатком системы без приоритетов является то, что при выполнении операции с диском (чтение в кэш с диска) операционная система NetWare не переключает процессор на выполнение другой прикладной задачи. Но этот недостаток компенсируется тем, что в NetWare, как правило, используется кэш-память большого размера, и 90% запросов на ввод данных удовлетворяется из этого кэша.