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


Функция page_cache_readahead

Функция page cache readahead берет на себя ответственность за все операции опережающего чтения, которые не были явно запущены соответствующими системными вызовами. Она пополняет текущее и опережающее окна, изменяет их размеры в соответствии с количеством попаданий”, т. е. соглас
но тому, насколько успешной была стратегия опережающего чтения при предыдущих обращениях к файлу.
Функция вызывается, когда ядро должно удовлетворить запрос на чтение одной или нескольких страниц файла. Она принимает пять параметров:
- mapping— указатель на объект address space, который описывает владельца страницы;
- указатель на дескриптор fiie ra state файла, содержащего страницу;
- f iip — адрес файлового объекта;
- offset — смещение страницы внутри файла;
- req size — количество страниц, которые необходимо прочесть, чтобы завершить текущую операцию чтения.
На самом деле, если операция чтения включает в себя количество страниц, превышающее максимальный размер окна опережающего чтения, функция page cache readahead вызывается несколько раз. Таким образом, параметр req size может быть меньше количества страниц, которые необходимо прочесть, чтобы завершить текущую операцию чтения.

Функция воздействует на поле дескриптора fiie ra state. Таким образом, хотя описание действий в блок-схеме весьма неформально, вы легко догадаетесь, какие шаги выполняет функция. Например, чтобы проверить, совпадает ли запрошенная страница с предыдущей прочитанной страницей, функция проверяет, совпадают ли значения поля ra->prev_page и параметра offset Когда процесс впервые обращается к файлу, и первая запрошенная страница имеет в файле нулевое смещение, функция предполагает, что процесс будет выполнять последовательные обращения. Поэтому она создает новое текущее окно, начиная с первой страницы. Длина первого текущего окна всегда является степенью двойки и некоторым образом зависит от количества страниц, запрошенных процессом при первой операции чтения: чем больше страниц запрошено, тем больше текущее окно, вплоть до максимума, хранящегося в поле ra->ra_pages. И наоборот, если процесс впервые обращается к файлу, но смещение первой запрошенной страницы не равно нулю, функция предполагает, что процесс не будет выполнять последовательные обращения. Тогда она временно отключает опережающее чтение (устанавливает поле ra->size в значение-1). Однако новое текущее окно создается, когда функция распознает последовательное обращение при временно отключенном опережающем чтении.

Если опережающее окно еще не существует, оно создается, как только функция обнаружит, что процесс выполнил последовательное обращение к текущему окну. Опережающее окно всегда начинается со страницы, следующей за последней страницей текущего окна. Однако его длина зависит от длины текущего окна: если флаг ra flag miss установлен, длина опережающего окна равна длине текущего окна минус 2, или четырем страницам, если результат меньше 4; в противном случае длина опережающего окна либо вчетверо, либо вдвое больше длины текущего. Если процесс продолжает обращаться к файлу последовательно, опережающее окно, в конце концов, становится новым текущим окном, и создается новое опережающее окно. Таким образом, опережающее чтение агрессивно интенсифицируется, если процесс читает файл последовательно.

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

Всякий раз, когда функция page cache readahead создает новое окно, она запускает операцию чтения для страниц, входящих в окно. Чтобы прочитать группу страниц, функция page cache readahead вызывает функцию blockable_page_cache_readahead. Для уменьшения нагрузки на ядро последняя функция обладает следующими интеллектуальными возможностями:
- чтение не выполняется, если очередь запросов, обслуживающая данное блочное устройство, переполнена запросами на чтение (нет смысла переполнять ее дальше и блокировать операцию опережающего чтения);
- для каждой страницы, подлежащей чтению, проверяется ее наличие в кэше страниц. Если страница уже присутствует в кэше, функция пропускает ее;
-все страничные кадры, необходимые запросу на чтение, выделяются сразу, до выполнения чтения с диска. Если не все страничные кадры могут быть получены, опережающее чтение выполняется только для доступных страниц. Нет никакого смысла откладывать опережающее чтение до получения всех страничных кадров;
- когда это возможно, запросы на операции чтения передаются общему слою работы с блочными устройствами при помощи многосегментных дескрипторов bio. Это делается специализированным методом readpages объекта address space, если ЭТОТ метод определен. Если же он не определен, вызывается метод readpage. Последний был описан в разд. ”Чтение из файла” ранее в этой главе для случая
одного сегмента, но читатель легко расширит этот описание и для случая с несколькими сегментами.

Предыдущая страница | 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...