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


Открытие файла блочного устройства

Мы завершаем эту главу описанием шагов, выполняемых виртуальной файловой системой при открытии файла блочного устройства.

Ядро открывает файл блочного устройства каждый раз, когда на диске или разделе монтируется файловая система, каждый раз, когда активизируется раздел подкачки, и каждый раз, когда процесс, работающий в режиме пользователя, выполняет системный вызов open для файла блочного устройства. Во всех случаях ядро выполняет, в сущности, одни и те же операции: ищет дескриптор блочного устройства (возможно, выделяя новый дескриптор, если устройство еще не используется) и определяет методы файловых операций для последующих пересылок данных.

В этом случае в поле f op файлового объекта находится адрес таблицы def bik fopsЗдесь нас интересует только метод open, вызываемый функцией dentry_ open . Функция blkdev_open Принимает В качестве параметров inode и f iip, в которых хранятся адреса индексного дескриптора и файлового объекта соответственно. Она выполняет следующие действия:
1. Вызывает bd_acquire(inode), чтобы получить адрес bdev дескриптора блочного устройства. Вызванная функция принимает в качестве параметра адрес индексного дескриптора и выполняет следующие шаги:
• проверяет поле inode->i_bdev индексного дескриптора на равенство null. Если значение поля не равно null, значит, файл блочного устройства уже открыт, и поле содержит адрес соответствующего дескриптора блочного устройства. В таком случае функция увеличивает счетчик обращений inode->i_bdev->bd_inode индексного дескриптора специальной файловой системы bdev, ассоциированной с блочным устройством, и возвращает адрес inode->i_bdev дескриптора;
• если файл блочного устройства еще не был открыт, функция вызывает
bdget (inode->i_rdev), Чтобы ПОЛуЧИТЬ адрес Дескриптора блОЧНОГО устройства в соответствии со старшим и младшим номерами файла блочного устройства. Если дескриптор еще не существует, функция bdget о выделяет его. Обратите внимание, что дескриптор вполне может существовать, например, если какой-то процесс обратился к этому блочному устройству через другой файл устройства;
• сохраняет адрес дескриптора блочного устройства в inode->i_bdev, чтобы ускорить операции открытия того же файла устройства в будущем;
• записывает в поле inode->i_mapping значение соответствующего ПОЛЯ в индексном дескрипторе bdev. Это указатель на объект "адресное пространство”, обсуждается в разд.
• заносит inode в список открытых индексных дескрипторов в дескрипторе блочного устройства. Список имеет корень в bdev->bd_inodes;
• возвращает адрес дескриптора bdev.
2. Записывает В поле filp->i_mapping значение inode->i_mapping.
3. Получает адрес дескриптора gendisk, имеющего отношение к данному блочному устройству:
disk = get_gendisk(bdev->bd_dev, &part);
Если открываемое блочное устройство является разделом, функция возвращает его индекс в локальной переменной part; в противном случае устанавливает переменную part в ноль. Функция get_gendisk() просто вызывает функцию kobj iookupO на области отображения объекта kobject bdev map, передавая ей старший и младший номера устройства
4. Если поле bdev->bd_openers не равно нулю, значит, блочное устройство уже ОТКрЫТО. ФуНКЦИЯ Проверяет ПОЛе bdev->bd_contains:
• если оно равно bdev, блочное устройство представляет собой целый ДИСК. Функция вызывает метод bdev->bd_disk->fops->open блОЧНОГО устройства, если он определен, затем проверяет поле bdev-> bdinvalidated И ВЫЗЫВает, еСЛИ необходимо, функцию rescan_ partitions;
• если поле не равно bdev, значит, блочное устройство является разделом. Функция увеличивает счетчик bdev->bd_contains->bd_part_count.
5. На этом шаге функция оказывается, если обращение к блочному устройству происходит впервые. Функция инициализирует поле bdev->bd_disk адресом disk дескриптора gendisk.
6. Если блочное устройство является диском (part равно нулю), функция выполняет следующие действия:
• выполняет метод блочного устройства disk->fops->open, если таковой определен. Фактически это специализированная функция, определенная драйвером блочного устройства, чтобы выполнить специфическую инициализацию, "в последнюю минуту”;
• считывает из поля hardsect size очереди запросов disk->queue размер сектора в байтах и использует это значение для корректной установки
полей bdev->bd_block_size И bdev->bd_inode->i_blkbits. Кроме ТОГО, записывает в поле bdev->bd_inode->i_size размер диска, вычисленный ПО значению disk->capacity;
• если установлен флаг bdev->bd_invaiidated, вызывает функцию rescan partitionsO, чтобы просканировать таблицу разделов и обновить их дескрипторы. Флаг устанавливается методом check_disk_ change блочного устройства, который имеется только у съемных дисков.
7. В противном случае, если блочное устройство является разделом (part не равно нулю), функция выполняет следующие действия:
• снова вызывает функцию bdget , на этот раз передавая ей младший номер disk->first_minor, чтобы получить адрес whole дескриптора всего диска;
• повторяет шаги с 3 по 6 для дескриптора всего диска, тем самым инициализируя его, если необходимо;
• записывает в поле bdev->bd_contains адрес дескриптора всего диска;
• увеличивает whoie->bd_part_count, чтобы учесть новую операцию открытия раздела на диске;
• записывает в поле bdev->bd_part значение disk->part [part-i], которое является адресом дескриптора hd struct данного раздела. Кроме того, вызывает kobject_get (&bdev->bd_part->kobj ), Чтобы увеличить СЧет- чик ссылок раздела;
• устанавливает поля индексного дескриптора так, чтобы они содержали размер раздела и размер его сектора.
8. Увеличивает СЧеТЧИК bdev->bd_openers.
9. Если файл блочного устройства открывается в режиме исключительного использования (установлен флаг o excl в поле fiip->f_fiags), функция вызывает bd_ciaim(bdev, fiip), чтобы установить держателя блочного устройства. В случае ошибки, у блочного устройства уже есть держатель— функция освобождает дескриптор устройства и возвращает код ошибки -EBUSY.
10. Завершает выполнение, возвращая 0 (успех).
По окончании функции bikdev_open системный вызов open о продолжает работать как обычно. Каждый последующий системный вызов для открытого файла приведет к выполнению одной из операций по умолчанию, установленных для файла блочного устройства. Как мы увидим в главе 16, каждая пересылка данных блочному устройству или от него эффективно реализуется путем выдачи запросов общему слою работы с блочными устройствами.

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




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

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

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

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

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

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

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

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

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