Буфери і заголовки буферів

Коли блок зберігається в памяті (скажімо, після зчитування або в очікуванні записи), то він зберігається в структурі даних, званоїбуфером (buffer)Кожен буфер повязаний строго з одним блоком Буфер грає роль обєкта, який представляє блок в оперативній памяті Згадаймо, що блок складається з одного або більше секторів, але по розміром не може бути більше однієї сторінки памяті Тому одна сторінка памяті може містити один або більше блоків Оскільки для ядра потрібна деяка керуюча інформація, повязана з даними (наприклад, якому блокового пристрою і якого блоку відповідає буфер), то кожен буфер повязаний зі своїм дескриптором Цей дескриптор називається заголовком, буфера (buffer head)і представляється за допомогою структури struc t buffer_head

Структура buffer_hea d містить інформацію, яка необхідна ядру для управління буферами і визначена у файлі

Розглянемо цю структуру з коментарями, які описують призначення кожного поля

.  struct buffer_head {

unsigned long b_state / * Прапори стану буфера * / atomic_t b_count / * Лічильник використання буфера * / struct buffer_head * b_this_page / * Список буферів в поточній

сторінці памяті * /

struct page sector_t

u32

*b_page b_blocknr  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_stat e містить стан певного буфера Це значення може містити один або кілька прапорів, які перераховані в табл 131 Можливі значення прапорів описані у вигляді перерахування bh_state_bits , Яке описано у файлі

Таблиця 131 Значення прапорів поля bh_stat e

Прапор стану Призначення

BH_Uptodat e Буфер містить справжні дані

BH_Dirt y Буфер змінений (вміст буфера новіше відповідних даних на диску, і тому буфер повинен бути записаний на диск)

BH_Lock Для буфера виконується операція читання-запису дискових даних, і буфер заблокований, щоб запобігти конкурентний доступ

BH_Req Буфер включений в запит

BH_Mapped Буфер є дійсним і відображається на дисковий блок BH_NEW Буфер щойно виділений і до нього ще не було доступу BH_Async_ Read Для буфера виконується асинхронна операція читання

вн_Азуnс Writ e Для буфера виконується асинхронна операція запису вн_Dеlа у С буфером ще не повязаний дисковий блок

BH_Boundary Буфер є останнім у послідовності суміжних блоків –

наступний за ним блок не є суміжним з цією серією

Перерахування bh_state_bit s також містить в якості останнього елемента прапор BH_PrivateStart Цей прапор не є дозволеним значенням прапора, а відповідає першому біту, який можна використовувати на розсуд розробників коду Всі біти, номер яких більше або дорівнює значенню BH_PrivateStart не використовуються підсистемою блочного введення-виведення і безпечно можуть використовуватися драйверами, яким необхідно зберігати інформацію в поле b_state

Прапори, які використовуються драйверами, можуть бути визначені на підставі значення цього прапора, що дозволяє гарантовано уникнути перекриття з битами, які офіційно використовуються рівнем блочного введення-виведення

Поле b_coun t – це лічильник використання буфера Значення цього поля збільшується і зменшується двома функціями, які визначені у файлі таким чином

static inline void get_bh (struct buffer_head *bh)

{

atomic_inc{&ampbh-&gtb_count)

}

static inline void put_bh (struct buffer_head *bh)

{

atomic_dec (&ampbh-&gtb_count)

}

Перед тим як маніпулювати заголовком буфера, необхідно збільшити значення лічильника використання за допомогою функції get_bh (), що гарантує, що під час роботи буфер не буде звільнений Коли робота з заголовком буфера закінчена, необхідно зменшити значення лічильника, посилань за допомогою функції put_b h ()

Фізичний блок на жорсткому диску, якому відповідає буфер, – це блок з логічним номером b_blocknr, якому й знаходиться на блочному пристрої b_bdev

Фізична сторінка памяті, в якій зберігаються дані буфера, відповідає значенню поля b_page Поле b_dat a – це покажчик прямо на дані блоку (які зберігаються десь в сторінці памяті b_page), розмір блоку зберігається в полі b_size Отже, блок зберігається в памяті, починаючи з адреси b_dat a і закінчуючи адресою (b_dat a + b_size)

Призначення заголовка буфера-це опис відображення між блоком на диску і буфером у фізичній памяті (тобто послідовністю байтів, які зберігаються у зазначеній сторінці памяті) Виконання ролі дескриптора відображення буфер-блок-єдине призначення цієї структури даних ядра

У ядрах до серії 26 заголовок буфера був значно більш важливою структурою даних По суті, це була одиниця введення-виведення даних в ядрі Він не тільки виконував роль дескриптора для відображення буфер-блок-сторінка фізичної памяті, але і виступав контейнером для всіх операцій блочного введення-виведення Це призводило до двох проблем Перша проблема полягала в тому, що заголовок буфера був великий і громіздкою структурою даних (сьогодні він дещо зменшився в розмірах), а крім того, виконання операцій блочного введення-виведення в термінах заголовків буферів було непростим і досить незрозумілою завданням Замість цього, ядру краще працювати зі сторінками памяті, що одночасно і простіше і дозволяє отримати велику продуктивність Використовувати великий заголовок буфера, описує окремий буфер (який може бути розміром із сторінку памяті), – неефективно У звязку з цим в ядрах серії 26 було зроблено багато роботи, щоб дати можливість ядру виконувати операції безпосередньо зі сторінками памяті і просторами адрес, замість операцій з буферами Деякі з цих операцій обговорюються в главі 15, Сторінковий кеш і зворотний запис сторінок, де також розглядається структура address_spac e і демони pdflush

Друга проблема, повязана з заголовками буферів, – це те, що вони описують тільки один буфер Коли заголовок буфера використовується як контейнер для операцій введення-виведення, то це вимагає, щоб ядро ​​розбивало потенційно велику операцію блочного вводу-виводу на безліч дрібних структур buffer_head, що в свою чергу призводить до непотрібних витрат памяті для храпения структур даних В результаті, основною метою при створенні серії ядра 25 була розробка нового гнучкого і швидкого контейнера для операцій блочного введення-виведення У результат зявилася структура bio, яка буде розглянута в наступному розділі

Джерело: Лав, Роберт Розробка ядра Linux, 2-е видання : Пер з англ – М: ТОВ «ІД Вільямс »2006 – 448 с : Ил – Парал тит англ

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*