Області пам’яті

Області памяті (memory areas) представляються за допомогою обєктів областей памяті, які зберігаються в структурах типу vm_area_struct Ця структура визначена у файлі Області памяті часто називаються областями віртуальної памяті (virtual memory area, або VMA)

Структура vm_area_struc t описує одну безперервну область памяті в даному адресному просторі Ядро розглядає кожну область памяті, як унікальний обєкт Для кожної області памяті визначені деякі загальні властивості, такі як права доступу і набір відповідних операцій Таким чином, одна структура VMA може представляти різні типи областей памяті, наприклад файли, які відображаються в память, або стек простору користувача Це аналогічно обєктно-орієнтованого підходу, який використовується в підсистемі VFS (см Главу 12, Віртуальна файлова система )

Нижче показана ця структура даних з коментарями, що описують призначення кожного поля

struct vm_area_struct {

struct mm_struct * vm_mm / * Відповідна структура mm_struct * / unsigned long vm_start / * Початок діапазону адрес * / unsigned long vm_end / * Кінець діапазону адрес * /

struct vm_area_struct * vm_next / * Список областей VMA * / pgprot_t vm_page_prot / * Права доступу * / unsigned long vm_flags / * Прапори * /

struct rb_node vm_rb / * Вузол поточної області VMA * /

union {/ * звязок з address_space-> i_mmap, або i_mmap_nonlinear * /

struct {

struct list_head      list void                 *parent struct vm_area_struct  *head

} vm_set

struct prio_tree_node prio_tree_node

} shared

struct list_head anon_vma_node / * Анонімні області * / struct anon_vma * anon_vma / * Обєкт анонімної VMA * / struct vm_operations_struct * vm_ops / * Операції * /

unsigned long vm_pgoff / * Зміщення у файлі * /

struct file * vm_file / * Відображений файл (якщо є) * /

void * vm_private_data / * Приватні дані * /

}

Як вже було розказано, кожен дескриптор памяті повязаний з унікальним діапазоном (інтервалом) адрес в адресному просторі процесу Поле vm_start – це початковий (мінімальний) адреса, а поле vm_end- кінцевий (максимальний) адреса даного інтервалу Отже, значення (vm_end vm_start) – це розмір (довжина) інтервалу адрес в байтах Інтервали адрес різних областей памяті одного адресного простору не можуть перекриватися

Поле vm_mm вказує па структуру mm_struct, повязану з даною галуззю VMA Зауважимо, що кожна область VMA унікальна для тієї структури mm_struct, з якою ця область повязана Тому, навіть якщо два різних процеси відображають один і той же файл на свої адресні простори, то для кожного процесу створюється своя структура vm_area_struct, щоб ідентифікувати унікальні області памяті кожного процесу Отже, два потоки, які спільно використовують адресний простір, також спільно використовують і всі структури vm_area_struct в цьому адресному просторі

Прапори областей VMA

Поле прапорів vm_flags містить бітові прапори, які визначені у файлі

. Вони вказують особливості поведінки і містять описову інформацію про сторінки памяті, які входять в дану область памяті На відміну від прав доступу, які повязані з певної фізичної сторінкою памяті, прапори областей VMA вказують особливості поведінки, за які відповідає ядро, а не апаратне забезпечення Більш того, поле vm_flags містить інформацію, яка відноситься до кожної сторінки в області памяті або, що те ж саме, до всієї області памяті в цілому У табл 141 наведено список можливих значень прапорів vm_flags

Таблиця 141 Прапори областей VMA

Прапор Вплив на область УМА і на її сторінки памяті

VM_READ VM_WRITE VM_EXEC VM_SHARED VM_MAYREAD VM_MAYWRITE VM_MAYEXEC VM_MAYSHARE VM_GROWSDOWN VM_GROWSUP VM_SHM VM_DENYWRITE VM_EXECUTABLE VM_LOCKED VM_IQ

VM_SEQ_READ VM_RAND_READ VM_DONTCOPY VM_DONTEXPAND VM_RESERVED VM_ACCOUNT VM_HUGETLB VM_NONLINEAR

Зі сторінок памяті можна зчитувати інформацію

У сторінки памяті можна записувати інформацію Можна виконувати код, що зберігається в сторінках памяті Сторінки памяті є спільно використовуваними Можна встановлювати прапор VM_REA D

Можна встановлювати прапор VM_WRIT E Можна встановлювати прапор VM_EXE C Можна встановлювати прапор VM_SHARE D

Область памяті може розширюватися вниз

Область памяті може розширюватися вгору

Область використовується для розділяється (спільно використовуваної) памяті

В область відображається файл, в який не можна виконувати запис

В область відображається виконуваний файл

Сторінки памяті в області є заблокованими

В область памяті відображається простір введення-виведення апаратного пристрою

До сторінок памяті, найімовірніше, здійснюється послідовний доступ До сторінок памяті, найімовірніше, здійснюється випадковий доступ Область памяті не повинна копіюватися при виклику for k ()

Область памяті не може бути збільшена за допомогою виклику remap () Область памяті не повинна откачиваться на диск

Область памяті є обєктом, за яким виконується облік ресурсів

В області памяті використовуються гігантські (hugetlb) сторінки памяті

Область памяті містить нелінійне відображення

Розглянемо докладніше призначення найбільш цікавих і важливих прапорів Прапори VM_READ, VM_WRITE і VM_EXEC указипают звичайні права на читання-запис та виконання для сторінок памяті, які належать даній області памяті Пр і необхідності їх можна комбінувати для формування відповідних прав доступу Наприклад, відображення виконуваного коду процесу може бути виконано із зазначенням прапорів VM_READ і VM_EXEC, але ніяк не з зазначенням прапора VM_WRITE З іншого боку, сегмент даних з виконуваного файлу може відображатися з зазначенням прапорів VM_READ і VM_WRITE, вказувати при цьому прапор VM_EXEC не має сенсу Файл даних, який відображається тільки для читання, повинен відображатися з зазначенням тільки прапора VM_READ

Прапор VM_SHARED вказує на те, що область памяті містить відображення, яке е може спільно використовуватися декількома процесами Якщо цей прапор встановлений, то таке відображення називають спільно використовуваних(shared mapping),  що інтуїтивно зрозуміло Якщо цей прапор не встановлений, то таке відображення доступно тільки одному процесу і воно називається приватним відображенням, (private mapping)

Прапор VM_IO вказує, що область памяті містить відображення області введення-виведення апаратного пристрою Цей прапор зазвичай встановлюється драйверами пристроїв при виконанні виклику mmap () Для відображення в память області введення-виведення апаратного пристрою Крім усього іншого, цей прапор вказує, що область памяті не повинна включатися у файл core процесу Прапор VM_RESERVED вказує, що область памяті не повинна откачиваться на диск Цей прапор також укаливаются при відображенні на память областей вводу-виводу апаратних пристроїв

Прапор VM_SEQ_READ є підказкою ядру, що додаток виконує послідовне (тобто лінійне і безперервне) читання з відповідного відображення При цьому ядро ​​може підвищити продуктивність читання за рахунок виконання попереджувального читання (read-ahead) з відображуваного файлу Прапор VM_RAND_READ вказує зворотне, тобто додаток виконує операції читання з випадково обраних місць відображення (Тобто не послідовно) При цьому ядро ​​може зменшити або зовсім відключити виконання попереджувального читання з відображуваного файлу Ці прапори встановлюються за допомогою системного виклику madvic e () шляхом зазначення відповідно прапорів MADV_SEQUENTIAL і MADV_RANDOM для цього виклику Попередній виклик – це послідовне читання кілька більшої кількості даних, ніж було запитано, в надії на те, що додатково лічені дані можуть скоро знадобитися Такий режим корисний для додатків, які зчитують дані послідовно Однак якщо зчитування даних виконується випадковим чином, то режим читання, не ефективний

Операції з областями VMA

Поле vm_ops структури vm_area_struc t містить покажчик на таблицю операцій, які повязані з даною галуззю памяті і які ядро ​​може викликати для маніпуляцій з областю VMA Структура vm_area_struc t служить спільним обєктом для подання всіх типів областей віртуальної памяті, а в таблиці операцій описані конкретні методи, які можуть бути застосовані до кожного конкретного екземпляру обєкта

Таблиця операцій представлена ​​за допомогою структури vm_operations_struct, яка визначена у файлі таким чином

structvm_operations_struct {

void (*open) (struct vm_area_struct *)

void (*close) (struct vm_area_struct *)

struct page * (*nopage) (struct vm_area_struct *, unsigned long, int)

int (*populate) (struct vm_area struct *, unsigned long, unsigned long, pgprot_t, unsigned long, int)

}

Розглянемо кожен метод окремо

• void open (struct vm_area_struct *area)

Ця функція викликається, коли відповідна область памяті додається в адресний простір

• void close(struct vm_area_struct *area)

Ця функція викликається, коли відповідна область памяті видаляється з адресного простору

• struct page * nopage(struct vm_area_sruct *area, unsigned long address,

int unused)

Ця функція викликається обробником переривання через відсутність сторінки (page fault), коли провадиться доступ до сторінки, яка відсутня у фізичній памяті

• int populate {struct vm_area_struct *area, unsigned long address,

unsigned long len, pgprot_t prot,

unsigned long pgoff, int nonblock)

Ця функція викликається з системного виклику remap_pages () для попереднього заповнення таблиць сторінок області памяті (prefault) при створенні нового відображення

Списки і дерева областей памяті

Як вже розповідалося, до областей памяті здійснюється доступ за допомогою двох структур даних дескриптора памяті: полів mmap і mm_rb Ці дві структури даних незалежно один від одного вказують на всі області памяті, повязані з даним дескриптором памяті Вони містять покажчики на одні й ті ж структури vm_area_struct, просто ці покажчики повязані один з одним по-різному

Перший контейнер, поле mmap, обєднує всі обєкти областей памяті в однозвязний список Структури vm_area_struc t обєднуються в список за допомогою своїх полів vm_next Області памяті відсортовані в порядку збільшення адрес (від найменшого і до найбільшого) Першою області памяті відповідає структура vm area_struct, на яку вказує саме поле mmap Покажчик на саму останню структуру дорівнює значенню NULL

Друге поле, mm_rb, обєднує всі обєкти областей памяті в червоно-чорне (red-black) дерево На корінь дерева вказує поле mm_rb, а кожна структура vm_area struc t приєднується до дерева за допомогою поля vm_rb

Червоно-чорне дерево – це один з типів бінарного дерева Кожен елемент червоно-чорного дерева називається вузлом Початковий вузол є коренем дерева Більшість вузлів має два дочірні вузла: лівий дочірній вузол і правий дочірній вузол Деякі вузли мають всього один дочірній вузол, і, нарешті, вузли, які не мають дочірніх, називаються листям Для будь-якого вузла всі елементи дерева, які знаходяться зліва від даного вузла, завжди менше за своїм значенням, ніж значення даного вузла, а всі елементи дерева, які знаходяться праворуч від деякого вузла, завжди більше по значенням, ніж значення цього вузла Більше того, кожному вузлу присвоєно колір (червоний або чорний, звідси і назва цього типу дерев) у відповідності з наступними двома правилами: дочірні елементи червоного вузла є чорними і будь-який шлях по дереву від вузла до листя повинен містити однакову кількість чорних вузлів Корінь дерева завжди корисний Пошук, вставка і видалення елементів з такого дерева вимагають кількість операцій порядку О (lo g (n))

Звязаний список використовується, коли необхідно пройти по всіх вузлах Красночерное дерево використовується, коли необхідно знайти певну область памяті адресного простору Таким чином, ядро використовує надмірні структури даних для забезпечення оптимальної продуктивності незалежно від того, які операції виконуються з областями памяті

Області памяті в реальному житті

Розглянемо приклад адресного простору процесу та області памяті в цьому адресному просторі Для цієї мети можна скористатися корисною файлової системою / рго с і утилітою pmар (1) Як приклад розглянемо наступну просту прикладну програму, яка працює в просторі користувача Ця програма не робить абсолютно нічого, крім того, що служить прикладом

int main(int argc, char *argv[])

return 0

}

Розглянемо список областей памяті з адресного простору цього процесу Цих областей небагато Ми вже знаємо, що серед них є сегмент коду, сегмент даних сегмент bss Якщо врахувати, що ця програма динамічно скомпонована з бібліотекою функцій мови С, то відповідні області існують також для модуля libcso і для модуля ldso І нарешті, серед областей памяті також є стек процесу

Результат виведення списку областей адресного простору цього процесу з файлу / proc / / map s має наступний вигляд

rml@phantasy:~$ cat /proc/1426/maps

00e80000-00faf000 r-xp 00000000 03:01 208530 /lib/tls/libc-232so

00faf000-00fb2000 rw-p 0012fOOO 03:01 208530 /lib/tls/libc-232so

00fb2000-00fb4000 rw-p 00000000 00:00 0

08048000-08049000 r-xp 00000000 03:03 439029 /home/rml/src/example

08049000-0804a000 rw-p 00000000 03:03 439029 /home/rml/src/example

40000000-40015000 r-xp 00000000 03:01 80276  /lib/ld-232so

40015000-40016000 rw-p 00015000 03:01 80276  /lib/ld-232so

4001e000-4001f000 rw-p 00000000 00:00 0 bfffe000-c0000000 rwxp fffffOOO 00:00 0

Інформація про області памяті видається в наступному форматі

початок-кінець права доступу зміщення старший: молодший номера пристрою файловий індекс файл

Утиліта рmар (1) 4 форматує цю інформацію в наступному, більш зрозумілому людині вигляді

rml@phantasy:~$ pmap 1426 example[1426]

OOe8OOOO (1212 KB) r-xp (03:01 208530)       /lib/tls/libc-232so

OOfafOOO (12 KB)   rw-p (03:01 208530)       /lib/tls/libc-232so

00fb2000 (8 KB)   rw-p (00:00 0)

08048000 (4 KB)    r-xp (03:03 439029)       /home/rml/src/example

08049000 (4 KB)    rw-p (03:03 439029)       /home/rml/src/example

40000000 (84 KB)   r-xp (03:01 80276)        /lib/ld-232so

4 Утиліта pmap (l) друкує форматування й список областей памяті процесу Результат її виведення кілька більш удобочитаем, ніж інформація, одержувана з файлово ї системи / ргос , Але це одна і та ж інформація Дана утиліта включена в нові версії пакету procps

40015000 (4KB)    rw-p (03:01 80276)         /lib/ld-232so

4001e000 (4 KB)   rw-p (00:00 0)

bfffeOOO (8 KB)   rwxp (00:00 0)

mapped: 1340 KB   writable/private:  40 KB  shared: 0 KB

Перші три рядки відповідають сегменту коду, сегменту даних і сегменту bss модуля libcso (бібліотека функцій мови С) Наступні два рядки описують відповідно сегмент коду і сегмент даних виконуваного образу Далі три рядки-опис сегментів коду, даних і bss модуля ld so (динамічний компонувальник) Останній рядок описує стек процесу

Зверніть увагу, що всі сегменти коду мають права на читання і виконання, що й має бути для виконуваних образів З іншого боку, сегменти даних і bss, які містять глобальні змінні, позначаються як мають права на запис і читання, а не на виконання

Всі адресний простір складає близько 1340 Кбайт, але тільки 40 Кбайт з них мають право на запис і відповідають приватному відображенню Якщо область памяті є спільно використовуваної і не має прав на запис, то ядро ​​зберігає в памяті всього одну копію відображуваного файлу Це може здатися звичайним для спільно використовуваних відображень однак, випадок, коли при цьому ще й відсутні права на запис, виявляється дещо несподівано Якщо врахувати факт, що коли на відображення немає прав запису, то відповідна інформація ніколи не може бути змінена (з відображення можливо тільки читання), стає ясно, що можна абсолютно безпечно завантажити виконуваний образ в память всього один раз Тому динамічно завантажувана бібліотека функцій мови С і займає в памяті всього 1212 Кбайт, а не 1212 Кбайт, помножене на кількість процесів, які цю бібліотеку використовують У звязку з цим, процес, код і дані якого мають обсяг порядку 1340 Кбайт, насправді займає всього 40 Кбайт фізичної памяті Економія памяті через такого спільного використання виходить істотною

Зверніть увагу на області памяті, які не мають відображуваного файлу, знаходяться на пристрої з номерами 00:00 і номер файлового індексу для яких дорівнює нулю Це відображення сторінки, заповненої нулями (zero page, кульова сторінка) Якщо відобразити сторінку, заповнену нулями, на область памяті, яка має права на запис, то побічним ефектом є ініціалізація всіх змінних в нульові значення Це важливо, оскільки в такому випадку виходить область памяті, заповнена нулями, яка потрібна для сегмента bss

Кожній області памяті, повязаної з процесом, відповідає структура vm_ area_struct Так як процес не є потоком (thread), то для нього існує окрема структура min_struct, на яку є посилання зі структури task_struct

Джерело: Лав, Роберт Розробка ядра 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>

*

*