Linux Kernel (Ядро линукса) (часть 3)


Выделение страниц по требованию для отображения в память

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

входит ли адрес, вызвавший ошибку, в какую-нибудь область памяти, принадлежащую процессу. Если так оно и есть, ядро проверяет запись в Таблице Страниц, соответствующую этому адресу, и вызывает функцию do no page , если запись содержит null.

Функция do no page выполняет действия, общие для всех механизмов выделения страниц по требованию, например, выделение страничного кадра и обновление Таблиц Страниц. Она также проверяет, определен ли метод nopage для области памяти, вовлеченной в эту ситуацию.
1. Вызывает метод nopage, который возвращает адрес страничного кадра, содержащего запрошенную страницу.
2. Если процесс пытается сделать запись в страницу, а отображение в память является закрытым, функция должна избежать следующего исключения, связанного с копированием при записи”, для чего делает копию только что прочитанной страницы и заносит ее в неактивный список страниц Если область закрытого отображения еще не имеет подчиненной анонимной области памяти, содержащей новую страницу, функция либо добавляет новую подчиненную анонимную область, либо расширяет уже существующую. На следующих шагах функция пользуется новой страницей, а не страницей, возвращенной методом nopage, чтобы последняя не была модифицирована процессом, работающим в режиме пользователя.
3. Если какой-то другой процесс выполнил усечение страницы или сделал ее недействительной (для подобной проверки используется поле truncate count дескриптора address space), функция повторяет попытку получить страницу, вернувшись к шагу 1.
4. Увеличивает поле rss дескриптора памяти процесса, чтобы отметить факт назначения процессу нового страничного кадра.
5. Заносит в запись Таблицы Страниц, соответствующую адресу, вызвавшему ошибку, адрес страничного кадра и права доступа к странице, хранящиеся в поле vm page prot области памяти.
6. Если процесс пытается выполнить запись в страницу, функция устанавливает биты Read/write и Dirty в Таблице Страниц. В этом случае либо страничный кадр назначен исключительно данному процессу, либо страница является совместно используемой. Как бы то ни было, запись в нее должна быть разрешена.

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

При работе с областями памяти, отображающими файлы, метод nopage должен вначале поискать запрошенную страницу в кэше. Если страница не будет обнаружена, метод должен прочитать ее с диска. В большинстве файловых систем метод nopage реализован С ПОМОЩЬЮ функции filemap_nopage, которая принимает три параметра:
- area— адрес дескриптора области памяти, содержащей запрошенную страницу;
□ address — линейный адрес запрошенной страницы;
- type — указатель на переменную, в которую функция будет записывать тип ошибки обращения к странице, который определила функция
(VM_FAULT_MAJOR ИЛИ VM_FAULT_MINOR).
Функция fiiemap nopage о выполняет следующие действия:
1. Получает адрес file файлового объекта из поля area->vm_fiie и затем адрес объекта address space из поля fiie->f_mapping. Получает адрес индексного дескриптора ИЗ ПОЛЯ host объекта address space.
2. С помощью полей vm start и vm pgoff области area определяет смещение внутри файла для данных, соответствующих странице, начинающейся с адреса address.
3. Проверяет, не превышает ли смещение размер файла. Если это произойдет, функция возвратит null, что означает сбой в выделении новой страницы, если только ошибка обращения к странице не была вызвана отладчиком, отслеживающим другой процесс с помощью системного вызова ptrace . Но мы не будем обсуждать этот специальный случай.
4. Если флаг vm rand read области памяти установлен, можно предположить, что процесс читает страницы отображения произвольным образом. Функция не прибегает к опережающему чтению и переходит к шагу 10.
5. Если флаг vm seq read области памяти установлен, можно предположить, что процесс читает страницы отображения строго последовательно. Функция вызывает функцию page_cache_readahead, чтобы выполнить опережающее чтение, начиная со страницы, вызвавшей ошибку
6. Вызывает функцию find get page , чтобы искать в кэше страницу, идентифицируемую объектом address space и смещением внутри файла. Если страница найдена, функция переходит к шагу 11.
7. Если функция находится на этом шаге, значит, страница в кэше не найдена. Функция проверяет флаг vm seq read области памяти:
• если флаг установлен, значит, ядро агрессивно выполняет опережающее чтение страниц области памяти, и алгоритм опережающего чтения себя не оправдал. Функция вызывает функцию handie ra miss о для настройки параметров опережающего чтения, а затем переходит к шагу 10;
• в противном случае, если флаг сброшен, функция увеличивает на единицу значения счетчика mmap miss в дескрипторе fiie ra state файла. Если количество промахов намного превышает количество попаданий
(хранящееся в счетчике mmap hit), функция пренебрегает опережающим чтением и переходит к шагу 10.
8. Если опережающее чтение не отключено (поле ra pages дескриптора file ra state больше нуля), функция вызывает функцию do_page_cache_ readahead , чтобы прочитать некоторое количество страниц, окружающих запрошенную.
9. Вызывает функцию find get page , чтобы проверить наличие запрошенной страницы в кэше. Если страница там, функция переходит к шагу 11.
10. Вызывает функцию page cache read . Эта функция проверяет, находится ли запрошенная страница в кэше страниц, и, если ее там нет, выделяет новый страничный кадр, добавляет его в кэш страниц и выполняет метод mapping->a_ops->readpage, чтобы спланировать операцию ввода/вывода, которая прочитает содержимое страницы с диска.
11. Вызывает функцию grab swap token , чтобы, по возможности, присвоить жетон защиты от выгрузки текущему процессу
12. Запрошенная страница находится в кэше. Функция увеличивает на единицу значение счетчика mmap hit дескриптора файла f iie ra state.
13. Если страница устарела (флаг PG uptodate сброшен), функция вызывает функцию iock_page, чтобы заблокировать страницу, выполняет метод mapping->a_ops->readpage, чтобы запустить пересылку данных, и вызывает функцию wait on page bitо, чтобы приостановить процесс, пока страница не будет разблокирована, т. е. пока не завершится операция пересылки данных.
14. Вызывает функцию mark_page_accessed, чтобы пометить страницу как страницу, к которой обращался процесс
15. Если в кэше была найдена неустаревшая версия страницы, функция записывает в переменную type значение vm fault minor; в противном случае записывает в нее значение vm fault major.
16. Возвращает адрес запрошенной страницы.

Процесс, работающий в режиме пользователя, может настроить опережающее чтение, выполняемое функцией fiiemap nopage о, с помощью системного вызова madvise . Команда madv_random устанавливает флаг vm_rand_read области памяти, чтобы показать, что процесс будет обращаться к страницам области памяти в случайном порядке. Команда madv sequential устанавливает флаг vm seq read, чтобы показать, что обращение к страницам будет строго последовательным; а команда madv normal сбрасывает флаги vm rand read и vm_seq_read, показывая, что порядок обращения будет непредсказуемым.

Предыдущая страница | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | Следующая страница




Возможно, Вас также заинтересует:

ОС Knoppix - это Linux без про...

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

Linux Kernel (Ядро линукса) (ч...

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

Linux Kernel (Ядро линукса) (ч...

Копирование при записи В системах Unix первых поколений создание процесса было реализовано довольно...

Linux Kernel (Ядро линукса) (ч...

Буферы блоков и головы буферовУ каждого буфера есть дескриптор голова буфера, имеющий тип buffer...