Выдача запроса
В этом разделе мы опишем типичную последовательность действий, выполняемых ядром при выдаче запроса на операцию ввода/вывода общему слою работы с блочными устройствами. Мы будем предполагать, что запрошенные порции данных идут на диске подряд, и что ядро уже определило их физическое местоположение.
Первый шаг заключается в вызове функции bio aiiocO выделения нового дескриптора bio. Затем ядро инициализирует этот дескриптор, устанавливая в нем некоторые поля:
- полю bi sector присваивается номер первого сектора данных (если блочное устройство разбито на несколько разделов, номер сектора считается от начала раздела);
- в поле bi size записывается количество секторов, содержащих данные;
- полю bijodev присваивается адрес дескриптора блочного устройства
- полю bi io vec присваивается адрес начала массива структур bio vec, каждая из которых описывает сегмент (буфер в памяти), вовлеченный в операцию ввода/вывода. Кроме того, в поле bi vcnt записывается общее количество сегментов в дескрипторе bio;
- полю bi rw присваиваются флаги запрошенной операции. Самый важный флаг определяет направление движения данных: read (0) или write (1);
- полю bi end io присваивается адрес завершающей процедуры, которая выполняется по окончании операции ввода/вывода.
После успешной инициализации дескриптора bio ядро вызывает функцию generic make request , КОТОрая ЯВЛЯетСЯ главной ТОЧКОЙ ВХОДа В общий СЛОЙ работы с блочными устройствами.
Эта функция выполняет следующие действия:
1. Проверяет, не превышает ли значение bio->bi_sector количество секторов блочного устройства. Если превышает, функция устанавливает поле bio eof в поле bio->bi_fiags, выводит сообщение ядра об ошибке, вызывает функцию bio endio и завершает свою работу. Функция bio endio обновляет поля bi size и bi sector дескриптора bio и вызывает метод bi end io этого дескриптора. Реализация последней функции сильно зависит от того, какой компонент ядра запустил операцию ввода/вывода. В следующих главах мы рассмотрим несколько примеров методов bi_end_io.
2. Получает в свое распоряжение очередь запросов q, ассоциированную с блочным устройством. Адрес этой очереди хранится в поле bd disk дескриптора блочного устройства, а на дескриптор указывает поле bio->bi_bdev.
3. Вызывает функцию block_wait_queue_running, Чтобы удостовериться, что в данный момент не происходит динамическая замена планировщика ввода/вывода. Если это не так, функция блокирует выполнение процесса, пока не будет запущен новый планировщик ввода/вывода
4. Вызывает функцию bik partition remap , чтобы проверить, ссылается ли блочное устройство на раздел диска (bio->bi_bdev не равно bio->bi_ dev->bd_contains (см. разд. "Блочные устройства" далее в этой главе). В таком случае функция получает дескриптор hd struct раздела диска из поля bio->bi_bdev и выполняет над ним следующие действия:
• обновляет ПОЛЯ read_sectors И reads (ИЛИ write sectors И writes) Дескриптора hd struct в соответствии с направлением движения данных;
• изменяет поле bio->bi_sector, чтобы преобразовать номер сектора относительно начала раздела в номер сектора на уровне диска;
• присваивает полю bio->bi_bdev адрес дескриптора блочного устройства — диска В целом (bio->bd_contains).
С этого момента общий слой работы с блочными устройствами, планировщик ввода/вывода и драйвер устройства забывают о разбивке диска на разделы и работают с целым диском.
5. Вызывает метод q->make_request_fn, чтобы поместить запрос bio в очередь запросов q.
6. Возвращает управление.
Типичную реализацию метода make request fn мы обсудим в разд. "Выдача запроса планировщику ввода/вывода" далее в этой главе.
Предыдущая страница | 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 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | Следующая страница