Поэтому размер блока равен размеру сектора, умноженному на число, которое является целой степенью двойки. Наиболее часто встречающиеся размеры блока — это 512 байт, один килобайт и четыре килобайта.
Часто сбивает с толку то, что некоторые люди называют секторы и блоки по- разному. Секторы, наименьшие адресуемые элементы устройства, иногда называют "аппаратными секторами" (hardware sector) или "блоками аппаратного устройства" (device block). В то время как блоки, наименьшие адресуемые единицы файловых систем, иногда называются "блоками файловой системы" (filesystem block) или "блоками ввода-вывода" (I/O block). В этой главе будут использованы термины "сектор" (sector) и "блок" (block), однако следует помнить и о других возможных названиях. На рис. 13.1 показана диаграмма соответствия между секторами и блоками.
Рис. 13.1. Связь между секторами и бликами
Существует еще одна часто встречающаяся терминология. По крайней мере в отношении к жестким дискам, используются термины кластеры (clusters), цилиндры (cylinder, дорожка) и головки (head). Такие обозначения являются специфическими только для некоторых типов блочных устройств, они, в основном, невидимы для пользовательских программ и в этой главе рассматриваться не будут. Причина, по которой секторы являются важными для ядра, состоит в том, что все операции ввода-вывода должны выполняться в единицах секторов. Поэтому более высокоуровневые концепции ядра, которые основаны на блоках, являются надстройками над секторами.
Буферы и заголовки буферов
Когда блок хранится в памяти (скажем, после считывания или в ожидании записи), то он хранится в структуре данных, называемой буфером (buffer). Каждый буфер связан строго с одним блоком. Буфер играет роль объекта, который представляет блок в оперативной памяти. Вспомним, что блок состоит из одного или больше секторов, но по размеру не может быть больше одной страницы памяти. Поэтому одна страница памяти может содержать один или больше блоков. Поскольку для ядра требуется некоторая управляющая информация, связанная с данными (например, какому блочному устройству и какому блоку соответствует буфер), то каждый буфер связан со своим дескриптором. Этот дескриптор называется заголовком буфера (buffer head) и представляется с помощью структуры struct buffer_head
.
Структура buffer_head
содержит информацию, которая необходима ядру для управления буферами и определена в файле <linux/buffer_head.h>
.
Рассмотрим эту структуру с комментариями, которые описывают назначение каждого поля.
struct buffer_head {
unsigned long b_state; /* флаги состояния буфера */
atomic_t b_count; /* счетчик использования буфера */
struct buffer_head *b_this_page; /* список буферов в текущей
странице памяти */
struct page *b_page; /* соответствующая страница памяти */
sector_t b_blocknr; /* логический номер блока */
u32 b_size; /* размер блока (в байтах) */
char *b_data; /* указатель на буфер в странице памяти */
struct block_device *b_bdev; /* соответствующее блочное устройство */
bh_end_io_t *b_end_io; /* метод завершения ввода-вывода */
void *b_private; /* данные метода завершения */
struct list_head b_assoc_buffers; /* список связанных отображений */
};
Поле b_state
содержит состояние определенного буфера. Это значение может содержать один или несколько флагов, которые перечислены в табл. 13.1. Возможные значения флагов описаны в виде перечисления bh_state_bits
, которое описано в файле <linux/buffer_head.h>
.
Таблица 13.1. Значения флагов поля bh_state
Флаг состояния | Назначение |
---|---|
BH_Uptodate |
Буфер содержит действительные данные |
BH_Dirty |
Буфер изменен (содержимое буфера новее соответствующих данных на диске, и поэтому буфер должен быть записан на диск) |
BH_Lock |
Для буфера выполняется операция чтения-записи дисковых данных, и буфер заблокирован, чтобы предотвратить конкурентный доступ |
BH_Req |
Буфер включен в запрос |
BH_Mapped |
Буфер является действительным и отображается на дисковый блок |
BH_New |
Буфер только что выделен и к нему еще не было доступа |
BH_Async_Read |
Для буфера выполняется асинхронная операция чтения |
BH_Async_Write |
Для буфера выполняется асинхронная операция записи |
BH_Delay |
С буфером еще не связан дисковый блок |
BH_Boundary |
Буфер является последним в последовательности смежных блоков — следующий за ним блок не является смежным с этой серией |
Перечисление bh_state_bits
также содержит в качестве последнего элемента флаг BH_PrivateStart
. Этот флаг не является разрешенным значением флага, а соответствует первому биту, который можно использовать по усмотрению разработчиков кода. Все биты, номер которых больше или равен значению BH_PrivateStart
, не используются подсистемой блочного ввода-вывода и безопасно могут использоваться драйверами, которым необходимо хранить информацию в поле b_state
.
Флаги, которые используются драйверами, могут быть определены на основании значения этого флага, что позволяет гарантированно избежать перекрытия с битами, которые официально используются уровнем блочного ввода-вывода.
Поле b_count
— это счетчик использования буфера. Значение этого поля увеличивается и уменьшается двумя функциями, которые определены в файле <linux/buffer_head.h>
следующим образом.
static inline void get_bh(struct buffer_head *bh) {
atomic_inc{&bh->b_count);
}
static inline void put_bh(struct buffer_head *bh) {
atomic_dec(&bh->b_count);
}