- •1.Архитектура операционных систем
- •1.1Общие вопросы архитектуры операционных систем
- •1.2Архитектура Windows
- •1.2.1История возникновения Windows
- •1.2.2Архитектура ос Windows
- •1.2.3История возникновения ос Linux
- •1.2.4Архитектура Linux
- •1.2.5Интерфейсы системы unix
- •1.2.6Файловая система unix
- •1.2.7Аутентификация в unix
- •1.2.8Сценарии командной оболочки unix
- •1.3Операционная система qnx
- •1.3.1 Архитектура qnx
- •1.4Выводы
- •1.5Вопросы для самоконтроля
- •2.Типы и алгоритмы работы с оперативной памятью
- •2.1Общие принципы функционирования подсистемы памяти в ос
- •2.1.1Обобщённые принципы управления памятью
- •2.1.2Однозадачная система без подкачки на диск
- •2.1.3Многозадачность с фиксированными разделами
- •2.1.4Подкачка
- •2.1.5Управление памятью с помощью битовых массивов
- •2.1.6Управление памятью с помощью связанных списков
- •2.1.7Виртуальная память
- •2.1.8Многоуровневые таблицы страниц
- •2.1.9Алгоритмы замещения страниц
- •2.2Виртуальная память ос Windows
- •2.2.1Архитектура памяти в ос Windows
- •2.2.2Работа с виртуальной памятью в ос Windows
- •2.2.3Использование виртуальной памяти в приложениях
- •2.3Пример организации страничной памяти на примере linux
- •2.3.1Страничная организация памяти в Linux
- •2.3.2Права доступа к области памяти
- •2.3.3Работа с областями памяти в Linux
- •3.Процессы и потоки
- •3.1Процессы
- •3.1.1Модель процесса
- •3.1.2Создание процесса
- •3.1.3Завершение процесса
- •3.1.4Состояния процессов
- •3.1.5Реализация процессов
- •3.2Потоки
- •3.2.1Реализация потоков
- •3.2.2Реализация потоков на уровне ядра
- •3.2.3Смешанная реализация
- •3.2.4 Метод управления «Активация планировщика»
- •3.2.5Всплывающие потоки
- •3.3Межпроцессное взаимодействие
- •3.3.1Состояние состязания
- •3.3.2Критические секции (Критические области)
- •3.3.3Взаимное исключение с активным ожиданием
- •3.3.4Примитивы межпроцессного взаимодействия
- •3.4Семафоры
- •3.5Мьютексы
- •3.6Организация многопоточной обработки в среде Windows
- •3.6.1Объекты ядра Windows
- •3.6.2Потоки Windows
- •3.6.3Синхронизация потоков в Windows
- •3.6.4Синхронизация потоков с помощью объектов ядра
- •3.6.5Сравнение объектов, используемых для синхронизации потоков
- •3.7Организация процессов и потоков в Linux
- •3.7.1Среда окружения в Linux
- •3.7.2Создание нового процесса. Системный вызов exec.
- •3.7.3Потоки unix. Функции потоков стандарта posix.
- •3.8Синхронизация потоков в unix
- •3.8.1Мьютексы
- •3.8.2Семафоры
- •0,0,0, //Ожидать обнуления семафора
- •0,1,0 // Затем увеличить значение семафора на 1};
- •0,1, 0 // Увеличитьзначение семафора на 1};
2.3.3Работа с областями памяти в Linux
Основными функциями при работе с виртуальной памятью в операционной системе Linux. В данном разделе рассматриваются основные системные вызовы, которые используются для работы с виртуальной памятью в Linux.
Основная функция для работы с виртуальной памятью с виртуальной памятью Linux – это vmalloc. Код реализации данной функции приведен ниже:
void * vmalloc(unsigned long size)
{
void * addr;
struct vm_struct *area;
size = PAGE_ALIGN(size);
if (!size || size > (max_mapnr << PAGE_SHIFT))
return NULL;
area = get_vm_area(size);
if (!area)
return NULL;
addr = area->addr;
if (vmalloc_area_pages(VMALLOC_VMADDR(addr), size)) {
vfree(addr);
return NULL;
}
return addr;
}
Функция vmalloc принимает один параметр — размер области памяти для распределения. Она возвращает указатель распределенной области или NULL, если память нельзя было распределить. Диапазон виртуальных адресов, в пределах которых функция vmalloc может распределять память, ограничена константами VMALLOC_START и VMALLOC_END. VMALLOC_START начинается на 8 Мб выше конца физической памяти для перехвата любых ошибочных операций доступа к памяти ядра в промежуточной области, a VMALLOC_END располагается немного ниже максимально возможного 32-разрядного адреса в 4 Гб.
Функция vmalloc начинает свою работу с округления затребованного размера в большую сторону до границы следующей страницы, если он еще не выровнен по границе страницы. Запрос отвергается, если результирующий размер либо слишком мал (0), либо, безусловно, слишком велик.
Далее производится попытка найти участок, достаточно большой для размещения блока с размером size с помощью функции get_vm_area, которая рассматривается ниже.
Проверка того, что может быть установлено отображение таблицы страниц с помощью вызова функции vmalloc_area_pages. Далее следует возврат распределённой области.
В приведенной функции используется структура vm_struct. Основные поля данной структуры приведены в табл. 2.5
Таблица 2.5. Поля дескриптора vm_struct
Тип |
Имя |
Описание |
void * |
addr |
Линейный адрес первой ячейки области |
unsigned long |
size |
Размер области плюс 4096 (интервал безопасности между областями) |
unsigned long |
flags |
Тип памяти, отображаемой несмежной областью памяти |
struct page ** |
pages |
Указатель на массив из nr_pages указателей на дескрипторы страниц |
unsigned int |
nr_pages |
Количество страниц, занимаемых областью |
unsigned long |
phys_addr |
Поле содержит 0, если область не была создана для отображения совместно используемой памяти аппаратного устройства |
struct vm struct * |
next |
Указатель на следующую структуру vm_struct |
Также в приведенной функции используется вызов get_vm_area. Функция get_vm_area() ищет свободный интервал линейных адресов между vmalloc_start и vmalloc_end. Эта функция принимает два параметра: size — размер создаваемой области в байтах; flag — флаг, задающий тип памяти.
Функция выполняет следующие действия:
1. Вызывает функцию kmalloc (), чтобы получить область памяти для нового дескриптора типа vmstruct.
2. Получает блокировку vmlistlock и просматривает список дескрипторов типа vmstruct в поисках свободного интервала линейных адресов, включающего, как минимум, size + 4096 адресов 4096 — это размер интервала безопасности между областями памяти).
3. Если такой интервал существует, функция инициализирует поля дескриптора, освобождает блокировку vmlistlock и завершает работу, возвращая начальный адрес несмежной области памяти.
4. В противном случае функция get_vm_area () освобождает ранее полученный дескриптор, освобождает блокировку vmlistlock и возвращает null.
Нечастые запросы на области памяти обрабатываются с помощью группы общих кэшей, объекты которых имеют размеры, геометрически распределенные в диапазоне от 32 до 131 072 байтов.
Функция vfree гораздо проще по сравнению с vmalloc (по крайней мере, если функция vmalloc рассматривается в сочетании с get_vm_area), но ради полноты вкратце рассмотрим vfree. Безусловно, здесь addr обозначает начало области vmallocd, которая подлежит освобождению. Код, соответствующий функции vfree() приведен ниже:
void vfree(void * addr)
{
struct vm_struct **p, *tmp;
if (!addr)
return;
if ((PAGE_SIZE-1) & (unsigned long) addr) {
printk("Trying to vfree() bad address (%p)\n", addr);
return;
}
for (p = &vmlist ; (tmp = *p) ; p = &tmp->next) {
if (tmp->addr == addr) {
*p = tmp->next;
vmfree_area_pages(VMALLOC_VMADDR(tmp->addr),
tmp->size);
kfree(tmp);
return;
}
}
printk("Trying to vfree() nonexistent vm area (%p)\n", addr);
}
Вслед за несколькими простыми проверками допустимости функция выполняет в цикле просмотр vmlist, отыскивая область для освобождения. Этот линейный просмотр заставляет думать, что было бы интересно посмотреть, позволит ли структура сбалансированного дерева, наподобие деревьев AVL, используемая для управления областями VMA, повысить производительность функций vmalloc и vfree.
Если будет найден объект struct vm_struct, соответствующий параметру addr, функция vfree удалит его из списка, освободит структуру и связанные с ней страницы, затем вернет управление. В каждом объекте struct vm_struct хранятся сведения не только о его начальном адресе, но также о его размере; это было удобно для функции get_vm_area и это также удобно здесь, поскольку позволяет функции vfree знать, сколько памяти нужно освободить.
Если бы функция vfree нашла соответствие в списке, она бы уже вернула управление, поэтому соответствие не было найдено. Поэтому vfree выводит предупредительное сообщение.