/
Author: Матвеев М.Д.
Tags: программирование на эвм компьютерные программы программирование операционные системы информационные технологии компьютерные технологии операционная система linux
ISBN: 978-5-907592-14-8
Year: 2023
Text
МАТВЕЕВ М. Д.
Ядро
•
1nux
СБОРКА,Н АСТРОЙКА
УПРАВЛЕНИЕ
"Издательство Наука и Техника"
Санкт-Петербург
УДК
004.42
ББК
32.973
Матвеев М. Д .
ЯДРО LINUX. СБОРКА, НАСТРОЙКА, УПРАВЛЕНИЕ НАУКА И ТЕХНИКА ,
2023. - 352
СПБ.: ИЗДАТЕЛЬСТВО
С., ИЛ .
ISBN 978-5-907592-14-8
В этой книге собрана самая разнообразная и полезная информация о ядре
Linux.
Спектр материалов до статочно широк: от самых основ (компиляция
ядра , загрузчик GRUB2, управление процессами
(обработка
до более сложных тем
прерываний, таймеры и отслеживание хода времени, управление
памятью ядра и т.д.). Отдельное внимание будет уделено различным аспек
там файловой и псевдофайловой систем
Linux,
управлению хранилищем,
механизмам кэ ширования чтени я и записи ядра.
Также будет рассмотрено взаи модействие ядра с разными типами устройств
и модулей , а для практики мы даже создадим свой несложный модуль.
Книга будет полезна как начинающих линуксоидам, так и более опытным
пользователям, которые хотят больше узнать о ядре
Linux.
В се права защище н ы . Никакая часть да нной кю1ги не может быть во спро ю ве,:хс н а в какой бы то ни было форме без п 11сьмеш1 о rо разрешения
владельцев авторских прав .
Издательство не несет ответственности за доступность матери ал ов . ссылки на которые вы м ожете найти а
3'tOi кинге . Н а м оме нт по.1готовюt
кн и ги к и зданию все сс ылки на интер н ет-ресурсы был11 действующ им 11.
1SB N 978-5-907 592-14-8
9
J
Ко нтакт ны е телефоны издательства:
(8 12) 4 12 70 26
Официальный сайт :
211
www.nit.com. ru
©
Матвеев М . Д.
©
И здательство Н аука и Техника (о ригинал-макет)
Содержание
ГЛАВА
1.
ВВЕДЕНИЕ В ОПЕРАЦИОННУЮ СИСТЕМУ И
ЯДРО
LINUX ......................................................................... 11
1.1.
НАЧАЛО. 1950-1990-ЫЕ ГГ..........................................................................................
12
1.2.
ИЗ
15
1.3.
ЭТАП ДИСТРИБУТИВОВ
MINIX
ГЛАВА
2.
В
LINUX.
ЭТАП ЯДРА ..................................................................................
.............................................................................................. 16
ОСНОВНЫЕ СВЕДЕНИЯ: О ЯДРЕ ............................ 19
2.1.
ЧТО ЕСТЬ ЯДРО
2.2.
ОСОБЕННОСТИ ЯДРА
2.3.
ВЕРСИЯ ЯДРА
2.4.
ВЫБОР ЯДРА ПРИ ЗАГРУЗКЕ
2.5.
СООБЩЕНИЯ ЯДРА ПРИ ЗАГРУЗКЕ ........................................................................
28
2.6.
ПЕРЕДАЧА ЯДРУ ПАРАМЕТРОВ ................................................................................
30
ГЛАВА
3.
............................................................................................................... 20
LINUX ..................................................................................... 23
LINUX ..................................................................................................... 26
..................................................................................... 27
КОМПИЛЯЦИЯ ЯДРА ................................................. ;.35
3.1.
ПОЛУЧЕНИЕ ИСХОДНИКОВ ЯДРА
3.2.
РАСПАКОВКА АРХИВА С ИСХОДНЫМ КОДОМ .................................................. 38
.......................................................................... 36
3.3. ИСПОЛЬЗОВАНИЕ ПАТ.ЧЕЙ ........................................................................................ 39
3.4.
СОДЕРЖИМОЕ КАТАЛОГА С ИСХОДНЫМИ КОДАМИ
3.5. СБОРКА
•
................................... 39
ЯДРА ....................................................................................................................
40
·················································································· t l l l
И , 1р11
l .i1111,
...................... n.1nux
3.6. КОМПИЛЯЦИЯ МОДУЛЕЙ ........................................................................................... 43
3.7.
УСТАНОВКА ЯДРА
................................................................ _.,...................................... 44
3.8. ПРАКТИЧЕСКИЙ ПРИМЕР: УСТАНОВКА ЯДРА 6.0 В
ГЛАВА
4.1.
4.
ЗАГРУЗЧИК
ЗАГРУЗЧИКИ
BUNTU 22.04 .......... 45
GRUB2 ....................................................... 49
LINUX ....................................................................................................... 50
4.2. КОНФИГ.УРАЦИОННЫЕ ФАЙЛЫ ............................................................................ 51
4.3.
ВЫБОР МЕТКИ ·ПО УМОЛЧАНИЮ
4.4.
ЗАГРУЗКА
4.5.
ПАРОЛЬ ЗАГРУЗЧИКА
4.6.
УСТАНОВКА ЗАГРУЗЧИКА
4.7.
СИСТЕМА ИНИЦИАЛИЗАЦИИ
.......................................................................... 57
WINDOWS ..................................................................................................... 58
GRUB2 .......................................... _ ....................................... 58
................................................._ ...................................... 61
.................................................................................. 61
4.7, 1.
Принцип работы ......................................................... ...........................
4.7,2.
Конфигурационные файлы
62
systemd .................................................... 64
4.7.3. Цели ... ,.... ,........... .. ,.... ,.... ,........ ... .. ,......... ,.................. .......................... ,, . 67
4.8.
УПРАВЛЕНИЕ СЕРВИСАМИ ПРИ ИСПОЛЬЗОВАНИИ
ГЛАВА
5.
SYSTEMD ................. 68
КАК ЯДРО УПРАВЛЯЕТ ПРОЦЕССАМИ .............. 71
5.1.
ЧТО ТАКОЕ ПРОЦЕСС ...................................................................................................
5.2.
СТРУКТУРЫ , СВЯЗАННЫЕ С ПРОЦЕССАМИ
72
..................................................... 74
5.2.1.
Список задач и структура процесса ....................................................
74
5.2.2.
Состояния процесса .... ,., ..... ,..... ,....... ,,............. .... ,.... ,........ ,..................
77
5.2.3,
Дескриптор процесса
............... .............. ...... ., ........... .... .......... ...... ., ..... 79
5.3.
КОНТЕКСТ ПРОЦЕССА .................................................................................................
82
5.4.
СОЗДАНИЕ НОВОГО ПРОЦЕССА И ЕГО ЗАВЕРШЕНИЕ .................................
83
5.5.
потоки
5.6.
ПЛАНИРОВЩИК
5.7.
УПРАВЛЕНИЕ ПРОЦЕССА МИ ИЗ КОНСОЛИ .......................................................
............................................................................................................................... 87
.............................................................................................................. 91
92
•
. ... .. ... . . . . .. . . . . .. .. . . . . . . . . . . . . . ·.· .................................... ... ...... .
Co. tl'p:m:aшн·
n.1nux ................. .
5.7.1 . Командырs, nice и ki/1.......................................................................... 92
Получение информации о процессе .................................................... 92
5.7.2.
Изменение приоритета процесса .........................................................
97
Аварийное завершение процесса .... ........ .. ........ ...... .......... .... .......... ....
98
Команда
top.......................................................................................... 100
5.7.3. Информация об использовании памяти и дискового пространства"102
5.7.4. Команда/иsеr ...................................................................................... 104
ГЛАВА 6. ОБРАБОТКА ПРЕРЫВАНИЙ ................................... 107
6.1.
ЧТО ТАКОЕ ПРЕРЫВАНИЯ
6.2.
ОБРАБОТЧИКИ ПРЕРЫВАНИЯ ................................................................................
....................................................................................... 108
6.2 .1.
Что такое обработчик прерывания?
6.2.2.
Регистрация обработчика прерывания
109
........................ .......... ...... .......... 109
......... ........ .................. .......... 110
6.3. ПИШЕМ СОБСТВЕННЫЙ ОБРАБОТЧИК ПРЕРЫВАНИЯ .............................. 113
6.4. API ДРАЙВЕРОВ ВЫСОКОГО УРОВНЯ .................................................................. 116
6.5.
КОНТЕКСТ ПРЕРЫВАНИЯ
......................................................................................... 117
6.6. ФУНКЦИЯ DO_IRQO ········································••,•···························································119
6.7. ИНТЕРФЕЙС /PROC/INTERRUPTS .......................................................................... 122
ГЛАВА 7. ТАЙМЕРЫ И ОТСЛЕЖИВАНИЕ ХОДА ВРЕМЕНИ .. 127
7.1.
УЧЕТ ВРЕМЕНИ В ЯДРЕ
............................................................................................. 128
7.2. ТАЙМЕРЫ ЯДРА ............................................................................................................. 130 _
7.3. API ТАЙМЕРА ................................................................................................................... 132
7.4. РЕАЛИЗАЦИЯ ТАЙМЕРОВ ЯДРА ............................................................................. 135
ГЛАВА
8.1.
•
8.
УПРАВЛЕНИЕ ПАМЯТЬЮ
КАКАЯ БЫВАЕТ ПАМЯТЬ?
....................................... 139
....................................................................................... 140
8.1.1.
Физическая и виртуальная .................................. ........ .......................
8.1.2.
Файловая и анонимная
140
................................................ ........ ............... 143
·-······-··············-··-···--····-··--···-···-···---··--···--·---·······--···-· -
и 11111
l ,illll\
....... . ............... n.lnux
8.1.3 . Вытесняемая
и н е выте сня емая п ам ят ь .............................................
144
8.1.4. Разные типы адресов .. .. ................. ................................ .. ............... .... 146
8.2. МЕТОДЫ УПРАВЛЕНИЯ ПОДСИСТЕМОЙ ПАМЯТИ ...................................... 148
8.2.1. Подкачка
и невытесня ем ая п ам я ть ......................... .. .........................
8.2.2.
Систем ный вы з ов
8.2.3.
ООМ
148
mlock() .................................................................. 148
killer ... ... ..... ............. ............. ......... ... ............. ........... ..... ..... ..... ... . 149
8.2.4. cgroups ................................................................................................. 150
8.2.5.
NUМA
............................. ......................... ........ ... ..... ........... ..... ..... ....... 150
8.3. МЕХАНИЗМ РАСПРЕДЕЛЕНИЯ LRU ................................. :.................................... 151
8.4. ДОПОЛНИТЕЛЬНЫЕ
СВЕДЕНИЯ ОБ УПРАВЛ Е НИИ ПАМЯТЬЮ В
8.4.1 . Снова
о виртуал ьно й п амяти
8.4.2. Большие
LINUX .. 153
.................. ............ ............................... 153
странИl\ы ................. .............. ... ............ .. ............ ........ ..........
155
8.4.3. Зоны ... .. :..... .......... ... ......... ....................... ...... ...................... ................. 155
8.4.4. Узлы ...... .... .... .......... .. .. .. ... .. .... ..... ... ................ .. ............. ........................ 156
8.4.5. Кэш
страницы
8.4.6. Анонимная
... .. ..... ...... .... ........ .. ..... .. .... ... ... .. ... ............ ... .... .............. 156
па м ять .......... .................. ... ... ..:.................. ... .... .... ..... ...... .
157
8.4.7. Освобожд ени е ..... ..... ... ... .................... ..... ..... .................... ....... ............ 157
8.4.8. Уплотнение
8.5.
(сжатие)
.......... .. ...... .. .................. ...................... ............. . 158
БОЛЬШИЕ СТРАНИЦЫ. БОЛЕЕ ПОДРОБНО ......................................................
8.5.1. Общая
инфор м аци я
8.5.2. В з аимодействие
............................................................................ 159
п ол итики п амяти задач с выделением /
освобождением б ол ьши х страни ц ....... ..... .. .. ..... ... ... ..... ... ...... .................. ... .
8.5.3. Атрибуты
б ол ьших страниц для каждого узла
8.5.4. Испол ь з ование
8.6.
159
166
................................ 166
больших стра н иц ......................................................
167
ПРАКТИКУМ АДМИНИСТРАТОРА ..........................................................................
169
Полез ные команд ы оболоч ки .................................... .........................
169
8.6.1.
Файл
/proc/meminfo ........... ........................................ ........................ . 169
Команда
и ее улучш енны й ва риа нт
top
Ко м анда free
Команда
8.6.2.
lttop .................................... 170
........................................................................................ 172
vmstat ..........................._. ........................................................ 173
Интерф ейс С МА. .... ... ................................................ ... .......................
8.6.3. Добавл ение
фа й ла п одкач к и
174
................ ................ .. ............................ 174
•
•
- - ----------------·----·----------------------------·······················-·--·····
<· н tt•p ; 1,a1111t·
n.1nux ................. .
ГЛАВА 9. ФАЙЛОВАЯ СИСТЕМА И ЯДРО ............................ 177
'
9.1. ВИРТУАЛЬНАЯ ФАЙ~ОВАЯ СИСТЕМА LINUX ................................................ 178
9.2. РЕГИСТРАЦИЯ И МОНТИРОВАНИЕ ФАЙЛОВОЙ СИСТЕМЫ ................... 180
ОБЪЕКТ СУПЕРБЛОКА ........................... ;...................................................................
9.3.
9 .3 .1.
Структура
struct super_ operations ..................................................... 184
9.3 .2.
Структура
structxattr_hand/ers ......................................................... 187
9.4.
ОБЪЕКТ ИН ОДА
9.5.
ОБЪЕКТ АДРЕСНОГО ПРОСТРАНСТВА
............................................................................................................. 188
9.5. 1. Общая
ОБЪЕКТ
9.6.
183
информация
.............................................................. 192
............ ........................................................ ........ 192
9.5.2.
Обработка ошибок во время обратной записи .. .. .... ._
....... .. ........ .......
9 .5 .3.
Структура
194
sutruct address_ space_ operations .................................... 195
FILE ................................................................................................................... 202
9.7. КЭШ ЗАПИСЕЙ КАТАЛОГА (DCACHE) ................................................................. 207
9.7 .1. Структура dentry_ operations .............................................................. 207
9.7.2. АР !
кэша записей каталогов ...............................................................
211
ГЛАВА 10. ПСЕВДОФАЙЛОВЫЕ СИСТЕМЫ ....................... 213
10.1.
НАЗНАЧЕНИЕ
................................................................................................................ 214
10.2. ПСЕВДОФАЙЛОВАЯ СИСТЕМА SYSFS ............................................................... 215
10.3. ПСЕВДОФАЙЛОВАЯ СИСТЕМА PROC ................................................................ 216
ГЛАВА
11.1.
ПОЛЬЗОВАТЕЛИ И ГРУППЫ
11.
ВВЕДЕНИЕ В УЧЕТНЫЕ ЗАПИСИ
................................ 221
LINUX ......................................................., .. 222
11.2. ПОЛУЧЕНИЕ ПОЛНОМОЧИЙ ROOT .................................................................... 225
11.3. УПРАВЛЕНИЕ УЧЕТНЫМИ ЗАПИСЯМИ ПОЛЬЗОВАТЕЛЕЙ ..................... 231
11.3 .1. Создани е
уч етной записи пользователя ....... ....................... ........ .. ..
11.3.2. Файлы /etc/passwd
•
.
-
-
11 .3.3.
- -
-
-
-
-
--- - - -
-
-
-
-
-
-
-
и
Изменение и удаление учетных записей
-
-
-
-
-
-
-
-
-
. . . - . -.
-
-
-
-
-
-
23 1
/etc/shadow ........................ .. ............. .... ........... 233
-
-
-
- -
.- -
-
-
-
........................................ 236
-. -- . - .
-
-
-
-
-
-
- -. -- . --
-
-
-
Я . tро (,iпux
............ . .......... n..1nux
11 .3 .4.
11.4.
Группы пользователей
.............................. ........ ................ ................ 240
МОДУЛИ РАМ .................................................................................................................
11.4.1. Ограничиваем доступ
11.4.2. Ограничиваем
11.4.3.
к системе по IР•адресу
241
............................ ... 244
время входа в систему .............................................
246
Ограничение системных ресурсов с помощью РАМ .................. ...
247
ГЛАВА 12. БЛОЧНЫЙ ВВОД/ВЫВОД ....................................... 251
12.1. БЛОЧНЫЕ У(;ТРОЙСТВА ......................................................................................... 252
12.2. СТРУКТУРА БЛОЧНОГО УСТРОЙСТВА ............................................................ 253
12.3. БУФ ЕРЫ ........................................................................................................................... 254
12.4.
ПЛАНИРОВЩИКИ ВВОДА/ВЫВОДА ....................................................................
257
12.4.1 . Алгоритм deadline ............................................................................ 258
12.4.2. Алгоритм CFQ .. ..... ........... ,.... .................... ..... ................ ................... 259
12.4.3 . Алгоритм NOOP ....................... ...................... ..... ... ........ ... ................ 259
12.4.4. Настройка
планировщиков
...... ..................... ...... ....... ........ ..... ......... 260
Настройка пла нировщика
CFQ .................. .............. ..................... ... 261
Настройка планировщика
deadline ................................................. 263
12.5. НАСТРОЙКА ОБЩИХ ПАРАМЕТРОВ БЛОЧНОГО ВВОДА/ВЫВОДА ..... 264
ГЛАВА
13.
МЕХАНИЗМЫ КЭШИРОВАНИЯ ЧТЕНИЯ И
ЗАПИСИ ЯДРА
LINUX ....................................................... 267
13.1.ДИСКОВЫЙ КЭШ И ОТЛОЖЕННАЯ ЗАПИСЬ ................................................. 268
13.2.
МЕТОДЫ КЭШИРОВАНИЯ
13.3.
КЭШИРОВАНИЕ НА ПРАКТИКЕ ............................................................................
...................................................................................... 269
273
ГЛАВА 14. УСТРОЙСТВА И МОДУЛИ ..................................... 279
14.1. ТИПЫ УСtРОЙСТВ ..................................................................................................... 280
14.2.
МОДУЛИ ЯДРА ...................................•............................................................................
...
14.2.1 . Написание
простого модуля
281
.................................................... ........ 281
•
.
. ----. ---. ---- ----------------------------- ------- ----------. -- --.. ---. ----------
C11. trp,ю11111t·
rt..inux ................. .
14.2.2. Сборка
модуля ................. ... .............. .............................. ...................
В пределах дерева исходных кодов ядра
Вне дерева исходников ядра
14.2.3.
........................................... .. ....... .... ... . 286
Установка модулей ...... ..... .. ... ........... .... .... .........................................
14.2.4. Загрузка
284
............. .......................... . 284
модулей ............. ......... ............. .... .......................... ..............
286
286
14.3. РАЗРАБОТКА СЛОЖНЫХ МОДУЛЕЙ ................................................................... 287
14.3 .1.
Компиля ция модулей из нескольких файлов исходного кода .......
14.3.2. Зависимости
14.3.3.
ГЛАВА
15.
между модулям и
Загрузка модулей с зависимостями ........... ......................................
УПРАВЛЕНИЕ ХРАНИЛИЩЕМ
ПОДКЛЮЧЕНИЕ НОВОГО ЖЕСТКОГО ДИСКА И ЕГО РАЗМЕТКА
15.2.
МЕНЕДЖЕР ЛОГИЧЕСКИХ ТОМОВ
15.3.
в
288
........................... 291
15.1.
15 .2. l . Введение
287
................................ ........ ................ 288
....... 292
................................................................... 300
LVM ......................... ... ...................... .. .................. .......... 300
15 .2.2.
Уровни абстракции
15.2.3.
Немного пра ктики .... ...... ... .......... .......... .. .. ... ..... ... ............. ..... .... .......
302
РАСШИРЕНИЕ LVM-ПPOCTPAHCTBA .................................................................
305
LVM ..................... .. ..................... .. .................... 301
ПРИЛОЖЕНИЕ 1. ФАЙЛЫ КОНФИГУРАЦИИ LINUX ........ 309
Пl.1. КОНФИГУРАЦИОННЫЕ ФАЙЛЫ ........................................................................ 310
Пl.2. ПОДКАТАЛОГИ С КОНФИГУРАЦИОННЫМИ ФАЙЛАМИ ........................ 319
ПРИЛОЖЕНИЕ 2. КОМАНДНЫЙ ИНТЕРПРЕТАТОР BASH.. 329
П2.1. НАСТРОЙКА BASH ..................................................................................................... 330
П2.2. ЗАЧЕМ НУЖНЫ СЦЕНАРИИ
BASH ..................................................................... 334
П2.3. СЦЕНАРИЙ "ПРИВЕТ, МИР!" ................................................................................ 335
П2.4. ПЕРЕМЕННЫЕ В СЦЕНАРИЯХ .............................................................................
336
П2.5. ПЕРЕДАЕМ ПАРАМЕТРЫ СЦЕНАРИЮ .............................................................
338
•
.. . -...
- -
.. .
-
-
- -. -- -. -- - ..
- -
-
- -
... - ....... -
- -
.. -
-
- . - ..
-
- -
- -
.-
- - -
. -- - . -
- -
.-.-
...
- -
--
И , 1рн
l , i1111,
....................... n.,nux
П2.6. ОБРАБОТКА МАССИВОВ
П2.7. ЦИКЛЫ
FOR
И
........................................................................................ 339
WHILE ............................................................................................... 339
П2.8. УСЛОВНЫЕ ОПЕРАТОРЫ ............................. :......................................................... 340
П2.9. ФУНКЦИИ В
BASH................................... ,.................................................................. 342
П2.10. ПРАКТИЧЕСКИЕ ПРИМЕРЫ СЦЕНАРИЕВ ....................................................
343
Проверка прав пользователя .. ,.. ........ ........ ............................... .. ... .. .............
Проверка свободного дискового пространства с уведомлением по
343
e•mail .... 343
ПРИЛОЖЕНИЕ 3. СЕТЕВАЯ ФАЙЛОВАЯ СИСТЕМА NFS .. 345
ПЗ.1. ВКРАТЦЕ О
NFS
И УСТАНОВКЕ НЕОБХОДИМЫХ ПАКЕТОВ
................. 346
П3.2. ФАЙЛ /ETC/EXPORTS ........................ j....................................................................... 347
ПЗ.3. ИСПОЛЬЗОВАНИЕ NFS-KЛИEHTA ......................................................................
СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ ИНФОРМАЦИИ
. . ... .. .. .. -....... ....... ......... ---- ... - . ---
349
...................... 350
•
-- ................ ---- -- -- -- ---- ... -..
Глава
1.
Введение в операционную
систему и ядро Linux
Я , 1р11
1,iщl\
...................... t'l.inux
1.1. Начало. 1950 Говоря об истории
поскольку
Linux
Linux
1990-ые гг.
нельзя не начать с операционной системы
зарождалась не на ровном месте. Когда говорят о
первое , что приходит на ум об этой операционной системе
распространяется по лицензии
OpenSource,
-
UNIX,
Linux, то
это то, что она
то есть исходные коды самой
операционной системы абсолютно свободно доступны и любой желающий
может ними воспользоваться , в том числе и для создания собственного
программного продукта. Подробно о самой лицензии говорить не будем
-
в
Интернете полно информации на эту тему.
Не нужно думать, что
Linux -
это первая ОреnSоurсе-операционная систе
ма. Нет, в 1950-ые годы практически все программное обеспечение в США
разрабатывалось студентами и распространялось абсолютно бесплатно. Ни
каких ограничений на распространение ПО не было
-
вы могли взять ис
ходные коды любого продукта и использовать их как вам пожелается. Тогда
еще не существовало лицензии
OpenSource, но никто даже не задумывался о
лицензировании программных продуктов. Первой операционной системой,
которая распространялась свободно была малоизвестная система А-2, кото
рая была написала для
UNIVAC Remington Rand. На рисунке 1.1
этот компьютер, занимающий всю комнату средних размеров.
изображен
•
81111-....... -------... -... --....... --............... -... --........ --.. --... -... -------.
t\.1nux ........... .
1 1 1а11а 1.
Рис.
В11t·щ·11щ• 11 нщ•р:11111111111~ ю t·11t· 1 t·м~ 11 i1 . 1p11
l .i1111,
1.1. UNIVAC Remington Rand
В 50-ые годы прошлого века началось зарождаться ОреnSоurсе-движение,
тогда оно называлось группой
Share -
результатом работы этой группы была
одноименная операционная система, появившаяся в конце 1950-ых.
Также в конце 50-ых годов компания
ADR
начала разрабатывать програм
му для автозаполнения блок-схем. В силу определенного стечения обсто
ятельств этой компании свой программный продукт пришлось переделать
для платформы IВМ401 , но коммерческого успеха у данной платформы не
было , ведь все ждали бесплатное решение от
ADR.
Сама же компания
ADR
не могла допустить выход бесплатного продукта, иначе бы она стала банкро
том. Поэтому ее разработчик, желая получить хоть что-то, продал патент на
программу в 1968-ом году. Эту дату считают датой коммерциализации ПО и
датой, когда ПО из полезного бонуса к «железу» превратилось в отдельный
продукт.
Параллельно , в том же 1968-ом году специалисты из
операционную систему
(англ.
patch -
Multics.
Bell Labs
возрождают
Они планировали сделать небольшой патч
заплатка), который перерос в отдельную операционную си
стему для мини-компьютера
на
зываться
мы
знаем
PDP-7. Новая операционная система стала
Unics. Именно так - мы не опечатались . Изначально то, что
как Unix, называлось Unics.
' ················································································-
}l,1po 1,i1111,
....... . .............. n.1nux
Первые версии
Unics
были написаны на ассемблере, но позже код был пере
писан на языке высокого уровня С и проект был переименован в
. сделало
Unix. Это
новую операционную систему более портативной и простой в ис
пользовании. Изюминкой (кроме портативности) стала иерархическая фай
ловая сисцма с одним корневым каталогом.
Поскольку холдинг АТ &Т, в состав которого входила
Bell Labs,
подписал
соглашение с правительством США, запрещающее компании продавать про
граммное обеспечение, исходный код
Unix
был доступен бесплатно . В пер
вую очередь его получили научные организации.
В 70-ые годы Калифорнийский университет в Беркли получил лицензию от
АТ &Т. Группа энтузиастов разработала свой вариант
тив, который получил название
UNIX - свой дистрибу
BSD - Berkeley Software Distribution.
В начале 80-ых АТ &Т отказались от концепции бесплатного распростране
ния ПО, Поэтому параллельно существовали две версии
BSD
UNIX -
и коммерческая от АТ &Т. Открытая операционная система
стала популярной , особенно в начале 80-ых, когда
Unix
бесплатная
BSD
сразу
от АТ &Т переста
ла бесплатно распространяться . По вполне понятным причинам компании
АТ &Т это не понравилось , и она подал_а в суд на университет. В результате
университету Беркли пришлось переписать существенную часть кода
заимствованный из
Теперь об
Unix
OpenSource.
-
весь
код .
История зарождения открытого ПО началась в конце
70-х годов прошлого века, когда программист Мэттью Столлман запросил
исходный код драйвера принтера у коллег из Массачусетского технологиче
ского института, но получил отказ . Данный факт обидел Столлмана, которо
го не устраивали ограничения, наложенные на обмен исходниками . Поэтому
он решил создать операционную систему с открытым кодом
-
любой жела
ющий мог бы вносить в нее изменения .
В сентябре
1983 года он
объявил о создании проекта
GNU (GNU's Not Unix),
В основе проекта лежал манифест, который стал фундаментом для лицензии
GPL (General
PuЬ!ic
License),
что и стало началом движения
OpenSource.
Несколько лет спустя Эндрю Таненбаум разработал Uniх-подобную опера
ционную систему
Minix, которая планировалась как учебное пособие для
Minix тогда стоила 69 долларов - довольно недо
студентов. Лицензия на
рого, поэтому в начале 90-ых эта система завоевала популярность среди раз-
работчиков ,
•
•
8 1 8 ---------------------------------------------------------------------------------·
1т111а I
n..inux ........... .
1.2.
Из
Minix
в
Ввt•. 1t•111н· 11 11ш· ра1111111111~ ю t· 1н· 1 t·,1~ 11 11 lfНI
Linux.
l .i1111,
Этап ядра
Собственно, сама операционная система
Minix
не была полноценной опе
рационной системой . Она создавалась для демонстрации основных прин
ципов настоящих (полноценных) операционных систем. Ее полный исход
ный код, который занимал всего
тысяч строк, был опубликован в книге
12
А.Таненбаума «О перационные системы». Данную книгу купил Линус Тор
вальдс
(Linus Torvalds).
В
1991 году Линус установил
Minix, но разочаровался в ней .
на свой компьютер операционную систему
Он принял решение усовершенствовать ее
-
ведь исходный код «Миникса» был доступен со всеми комментариями. Сна
чала он просто переписал программу эмуляции терминала, а затем фактиче
ски взялся за создание собственной операционной системы.
Linux. Конеч
Linux, которую мы знаем, но
она уже тогда была лучше своего прародителя - в ней работали командный
интерпретатор bash и компилятор gcc. Сообщение о создании новой опе
рационной системы было помещено в группу новостей comp.os.minix, там
25
августа
1991
года появилась на свет операционная система
но, это была еще не та операционная система
же предлагалось всем желающим протестировать ее . :Кроме информации о
выходе новой ОС в новостном письме было несколько тезисов относительно
новой операционной системы. Если вкратце , то :
•
Исходный код полностью переписан (то есть
идея , но весь код для
Minix
использовался как
был написан заново).
Linux v.001
• Linux
не будет такой громоздкой как
• Linux
распространяется бесплатно.
Кстати,
изначально Линус
GNU.
называл ядро своей операционной системы
Freaks, но администратору FТР-сервера , на который заливались исходники
новой операционной системь1 , такое название не понравилось и он переиме
новал его в
Linux.
После публикации новости о
сивное развитие
Linux, к
энтузиасты со всего мира ,
•
Linux
в группе
comp.os.minix
началось интен
ее разработке в помощь Торвальдсу подключились
-
ничто так не сокращает расстояния , как Ин
тернет. С момента появления версии
0.01,
которой практически нельзя было
•
················································· ··· ···· ·························· 8 1 1
И IJIO
l .i,111,
...................... n..1nux
пользоваться , до создания версии 1.0, пригодной для обычных пользовате
лей, а не программистов , прошло почти три года (она появилась в марте
1994
года) . Первая версия обладала поддержкой сети (поддерживался протокол
TCP/IP), а также графическим интерфейсом Х Window. Кстати, система Х
Window появилась в Linux еще в 1992 году одновременно с поддержкой
TCP/IP. На секунду, Windows 3.11 , которая появилась в ноябре 1993 году,
поддержкой сети не обладала. Поддержка сети появилась лишь в версии
Windows 3 .11 for Workgroups.
выше коммерческого детища
Первые версии
Linux
Так что с самого начала
Linux
была на голову
Microsoft.
распространялись на обыкновенных дискетах. Всего
было две дискеты: первая содержала ядро , а вторая
-
корневую файловую
систему и необходимые программы. Именно поэтому данный этап в раз
витии
Linux
мы назвали этапом ядра . По сути , кроме ядра и некоторых не
очень сложных утилит в самом начале ничего не было.
Установить подобную версию
Linux
на компьютер мог только специалист.
Чуть позже появились первые дистрибутивы, которые включали то же ядро
и корневую файловую систему, а также программу для установки всего этого
на компьютере. Программа установки поставлялась , как правило, на отдель
ной дискете .
Изначально
Linux
распространялся без лицензии
GPL.
Другими словами,
разработчики могли использовать ядро , модифицировать его, но не могли
перепродавать результаты своих трудов.
1.3.
Этап дистрибутивов
Что такое дистрибутив
Linux?
По сути
-
это ядро и дополнительные
программы. Любой желающий (даже сейчас) может создать собственный
дистрибутив
Linux, определив набор и параметры программ,
входящих в его
состав. Собственно, создать дистрибутив не очень сложно и это под силу од
ному, технически грамотному IТ-специалисту (понятно, когда есть команда,
то работа пойдет быстрее).
Первые дистрибутивы появились в
1992
году. Тогда отдельные энтузиасты
или группы э нтузиастов выпускали разные дистрибутивы (каждый, есте
..
ственно , под своим именем) . Фактически они отличались друг от друга лишь
,
названием и программой установки . В дальнейшем различия между дистри
бутивами стали более существ енными .
........ ... .. .... ........ .. .. ...... .. . . . . . ... . . ... .. .... ... . ......... ... . .. .. . ..
n..1nux ........... .
1
1, 111. 1
1 B11t',' tt· 1111t• 11 с1ш· ра1111с11111~ ю 01i· н· м~ 11 " -' IJIO 1, i1111x
Самый первый дистрибутив, появивший ся в начале
МСС
Interim Linux (Manchester Computing Centre,
0.12
терный центр). Он был создан на базе версии
1992
года, назывался
Манчестерский компью
в феврале
1992
года. Ав
тор дистрибутива ставил перед собой цель усовершенствовать процедуру
установки ядра и добавить несколько полезных функций .
МСС стал примером для всех остальных. Вскоре стали появляться другие
дистрибутивы. Многие из них прожили совсем недолго и мало кому извест
ны, например, дистрибутив
TAMU, разработанный
в Техасском университе
те.
Настоящий прорыв произвел дистрибутив
Softlanding_Linux_ System),
SLS (https://ru.wikipedia.org/wiki/
1992 года, поскольку
графическую систему Х Window
выпущенный в октябре
именно он содержал поддержку
TCP/IP
и
(автор этой статьи помнит, сколько труда тр'ебовалось, чтобы настроить ее).
Впоследствии данный дистрибутив бурно развивался и постепенно транс
формировался в один из самых популярных дистрибутивов того времени
-
Slackware.
Да,
SLS
много не прожил. Всего два года, но зато он послужил основой для
дистрибутива Slackware, который существует и по сей день. Первая версия
Slackware увидела свет 17 июля 1993 года. Slackware - отличный пример
классического дистрибутива. Да, в нем нет всяких модных примочек , как в
UЬuntu, он не обновляется каждые два года, но это тот самый
хотите,
true linux.
Впрочем ,
Gentoo Linux -
Linux.
Если
тоже пример дистрибутива для
настоящих фанатов , обладающих свободным временем .
В
1993 году также появился и второй популярнейший дистрибутив - Debian.
Автор дистрибутива - Иан Мердок. Дистрибутив создан при поддержке FSF
(Free Software Foundation) Столлмана. Изначально задумывался как альтер
натива SLS, но получился даже более удачным. На сегодняшний день явля
ется наиболее удачным и стабильным дистрибутивом в мире. На его базе
был создан ряд других дистрибутивов, в том числе мега-популярный ·дис
трибутив UЬuntu .
Дистрибутивостроение развивалось не только в США. В Германии в
1992
SUSE (Software- und System Entwicklung). Они
первые начали выпускать Linux для бизнес-клиентов. По сути, сначала они
выпускали адаптированную для немецкого рынка версию Slackware.
году была основана компания
Со временем дистрибутивы разрослись до таких размеров , что распростра
нять их на дискетах стало нель з я. Дистрибутив на
50
дискетах
-
-
вполне
реально. А что делать, если, скажем, дискета №41 окажется бракованной?
•
.-.......... --- ...... . ... -- ... ......... -....... --- ..... --.........................
Я ; tро
...................... n.iпux
[,inux
Как раз к тому времени компакт-диски и их приводы немного подешевели.
Компания
Red Hat была одной из первых, выпустивших свою разра,ботку на
CD. Начиная с середины 90-ых, все дистрибутивы Linux постепенно переш
ли на CD, а затем - на DVD . Первая версия Red Hat появилась в 1995 году.
Современные дистрибути вы распространяются, как правило, в виде ISО
образа DVD-диска. Далее этот образ записывается либо на
DVD,
либо на
флешку и производится установка на физический компьютер. С виртуаль
ным еще проще
-
ISО-образ «подсовывается» виртуальной машине и произ
водится установка системы на виртуальный диск .
Мы сейчас не будем рассматривать этапы развития даже самых популярных
дистрибутивов, поскольку ядро унифицировано, а надстройка над ядром
(то есть ПО, входящее в состав дистрибутива) не является предметом этой
книги.
•
. . . --- ----- ----- -- ·- ---- ---. --- ----•----•-- ---- ---· -----.- ---- -- ----·- ---------- -- --·
•
Глава
2.
Основные сведения о
ядре
Я 1 1рс1
2.1.
J, i1111x
....................... rt.inux
Что есть ядро
Говоря о ядре по умолчанию понимаешь, что это основной компонент систе
мы. Вроде бы и так понятно, но информатика
-
наука точная, поэтому давай
те разбираться, какой именно компонент операционной системы называется
ядром и за что он отвечает. Ведь из-за роста возможностей само понятие
операционная система стало очень размытым. Многие считают, что все, что
они видят на экране (кроме прикладных программ) и есть операционная
система . С одной стороны, это так и есть.
Ведь операционная система
-
это та часть компьютерной системы , которая
отвечает за основные функции использования и администрирования.
Сюда же входит ядро, драйверы устройств, системный загрузчик, команд
ная/графическая оболочка, файловая система и базовые системные утилиты.
В общем, только минимально необходимые для работы компьютера компо
ненты. Не является частью операционной системы прикладное ПО
-
тексто
вый редактор , браузер, медиа-проигрыватель и т.д. А вот понятие система
охватывает все ПО на компьютере
-
и операционную систему, и прикладные
программы.
Понятно , что ядро является частью операционной системы . Можно сказать,
что интерфейс пользователя (будь то командная строка или графическая обо
лочка) является внешней частью ОС , а ядро
-
внутренней.
•
E!lt-· ....... -.... -...... --....... --···-· ....... -.--............................... ·-.
n..iпux .... ........... .. .
Ядро
-
1J lalШ 2. Основные
CBC)(CIIIOI о ядре
это программное обеспечение, предоставляющее базовые функции
для всех остальных частей операционной систем,ы.
Именно ядро управляет аппаратным обеспечением («железом») и распре
деляет системные ресурсы . В англоязычной литературе можно встретить
термины супервизор (supervisor), основная часть (core), «внутренности»
(intemals) -
это и есть ядро.
К компонентам ядра относятся:
•
Обработчики прерываний, которые обслуживают запросы на прерыва
ния, поступающие от различных устройств;
•
Планировщик, распределяющий процессорное время между многими
процессами ;
•
Система управления памятью, которая управляет адресным простран
ством процессов;
•
Системные службы, такие как сетевая подсистема и подсистема межпро
цессного взаимодействия.
Обычно ядро находится в привилегированном положении по отношению к
пользовательским программам, то есть у ядра есть полный доступ к «же
лезу» и ко всем областям защищенной памяти . Систем,ные перем,енные
(system state) и обл асть памяти, в которой находится ядро, вместе называ
(kemel-space).
ются пространством ядра
Прикладным программам доступна лишь малая часть ресурсов, они не мо
гут выполнять некоторые системные функции, напрямую работать с аппара
турой, системной памятью (то есть не могут выходить за рамки адресного
пространства, которое выделено прикладной программе ядром).
Прикладные программы взаимодействуют с ядром с помощью системных
вызовов. Посмотрите на рис.
2.1.
Допустим, нашей программе нужно
открыть файл. Для этого она использует системный вызов
open(). Програм
(user mode ), далее она обращается к
конкретном примере - выполняет код
ма работае:r в пользовательском режиме
режиму ядра, которое что-то делает. В
реализации функции
open()
и возвращает какой-то результат (например, код
ошибки или дескриптор открытого файла).
•
•
•
······························ ····· -··············································-
и , ,,
... l ,illll\
•············ · ·········
fl1пux
user application
)
user
mode
system call interface
kernel
mode
open ( )
lmplementation
of open ( )
system call
return
Рис.
2.1.
Программа и системный вызов орепО
Когда прикладная программа выполняет системный вызов, говорят, что ядро
выполняет работу от имени прикладной программы. Более того, говорят, что
прикладная программа выполняет системный вызов в пространстве ядра, а
ядро выполняется в контексте процесса.
В функции ядра входит также управление системным аппаратными компо
нентами, Все платформы , на которых работает операционная система
• (и
Linux
не только) используют механиз.м прерываний (inteпupt). Когда аппаратно
му устройству необходим о как-то в за имодейст вовать с системой, оно
поставляет на шину специальный сигнал, который, в буквальном смысле
слова, прерывает работу процессора : Далее процессор запускает специаль
ную программу в ядре (обработчик прерывания , inteпupt
handler),
причем
все это происходит в реальном масштабе времени . Каждому типу прерыва
ния соответствует определенный номер
-
именно так можно узнать, какой
именно обработчик нужно запустить. Например , при вводе символа с клави
атуры контроллер клавиатуры генерирует прерывание , чтобы дать знать си
стеме, что в буфере клавиатуры есть новые данные , которые еще не обрабо
..
таны операционной системой . Ядро определяет номер прерывания , которое
пришло в систему, и з апускает соответ ствующий обработчик прерывания .
•
-·:. ---... -.. ---- ---. -- --. --- ·- ---- -------- -- -- . -- -. -... -- --. ---- ---... ---- -.
.. -. -
1 11; 111.1
rl1nux ................. .
:'
Оt·1ю1111ыt· t"llt',' H'IIIШ 11 )Цl)t'
Последний обрабатывает данные, поступившие с клавиатуры, и дает знать
контроллеру клавиатуры о том, что ядро готово для приема новых данных.
Во многих операционных системах, в том числе и в
Linux,
обработчики пре
рываний выполняются не в контексте процессов, а в специальном контек
сте прерывания
(interrupt context), который не
. Данный контекст существует специально,
связан ни с одним процессом,
чтобы дать возможность обработ
чику быстро отреагировать на прерывание и завершить работу.
В случае простоя система запускает в ядре в контексте процесса специаль
ный холостой процесс
(idle process),
Поэтому можно сказать, что процессор
всегда находится в одном из трех режимов:
l,
Выполнение прикладной программы в непривилегированном режиме;
2.
Выполнение операций в контексте процесса в привилегированном режи
ме от имени определенного процесса;
3.
Обработка прерываний в контексте прерывания, не связанном с каким-то
процессом.
2.2.
Особенности ядра
Linux
Все сказанное ранее можно отнести к ядру любой операционной системы,
не только
Linux.
Понятно, что у каждого ядра есть свои особенности. Мы
сейчас не будем рассуждать о ядре той же
об особенностях ядра
Linux
Windows,
а лучше поговорим
на фоне ядер других Uniх-подобных систем.
В большинстве своем все ядра
Unix
являются монолитными бинарными
файлами. Они существуют в виде больших исполняем111х образов, которые
выполняются в одном адресном пространстве. Для работы таких ядер тре
буется система с контроллером управления страничной организацией па
мяти
(page memory management unit, MMU).
Такое <<железо» позволяет
защитить память в системе и предоставить каждому процессу уникальное
виртуальное адресное пространство. Для работы
Linux
также нужен
Существуют отдельные реализации, позволяющие работать без
позволяет запускать
рых нет блока ММU.
•
Linux
MMU.
MMU, что
на миниатюрных "3Строенных системах, у кото
-
.--• -------------·- ----------------------------------------.. --. --. --------. ------.
•
Я 1 1ро l,in11x
_·_ ...... __ . __ .......... n.inux
Ранее было отмечено, что ядро
Unix/Linux
является монолитным. А какие
еще ядра бывают? Ядра операционных систем можно разделить на две боль
шие группы по особенностям их построения: м01-юлитные и микроядра.
Монолитное ядро является самым простым и до середины 1980-ых годов
все ядра были монолитными. Монолитное ядро реализовано в виде одного
большого процесса, который выполняется в одном адресном пространстве.
Такие ядра обычно хранятся на диске в виде одного большого статического
бинарного файла . Все службы ядра находятся и выполняются в одном боль
шом адресном пространстве ядра. Взаимодействия в ядре осуществляются
очень просто, потому что все, что выполняется в режиме ядра, выполняется
в одном адресном пространстве. Можно отметить простоту и высокую про
изводительность монолитных ядер.
При ·реализации микроядра обычно разработчики отказываются от одного
большого процесса. Все функции ядра разделяются на несколько процессов,
которые называются серверами. В привилегированном режиме работают
только определенные серверы, а все остальные работают в пользователь
ском. Все серверы изолированы и независимы друг от друга и каждый за
пускается в собственном адресном пространстве. Прямой вызов функций,
как в случае с монолитным ядром ; невозможен. Все взаимодействия с ядром
осуществляются посредством механизма межпроцессного взаимодействия
(IPC, Interprocess Communication). Даже сами серверы взаимодействуют
друг с другом через IPC. Разделение серверов позволяет предотвратить воз
можность выхода из строя одного сервера при выходе из строя другого. Бо
лее того, модульный принцип построения системы позволяет по мере необ
ходимости одному серверу выгрузить из памяти другой сервер.
Наличие дополнительного механизма (речь идет об
IPC)
требует дополни
тельных ресурсов по сравнению с обычным вызовом функций, что приво
дит к падению производительности системы по
сравнению с монолитны
ми ядрами. Типичцый пример микроядра - 'ядро операционной системы
Windows NТ. Подобное ядро используется во всех современных версиях
Windows, включая 1О и 11. В последних версиях Windows все серверы вы
полняются только в пространстве ядра, что является отклонением от перво
начальной идеи микроядра, но позволяет повысить производительность, так
как не нужно постоянно переключаться между пользовательским и привиле
гированным режимами.
Ядро
Linux
..
монолитное, т.е. оно выполняется в одном адресном простран
стве, в режиме ядра . Однако ядро
Linux
позаимствовало некоторые хорошие
-
•
. -- -------.. -... --.. ---... -.. --... -... ---. --... -........ --...... -.... --... .. . --..
1тша 2.
n.inux ................. .
OCIIOBIIЫC СВСДСIIИЯ II sщрс
решения из микроядерной модели: в нем используется модульный принцип
построения, возможность приоритетного
планирования самого себя
программн.ым режимом,
( его называют ядром с приоритетн.ым мульти
или kernel preemption ), поддерживается многопо
точный режим, а также возможность динамической загрузки в ядро внешних
бинарных файлов (модулей ядра). Далее в этой книге мы поговорим об этом
-
вам не нужно собирать ядро, содержащее в себе весь необходимый функ
ционал. Некоторый функционал может быть включен по мере необходимо
сти в ядро посредством загрузки модуля .
Ядро
Linux
не использует никаких функций микроядерной модели, которые
бы могли привести к снижению производительности: все выполняется в ре
жиме ядра с непосредственным вызовом функций вместо передачи сообще
ний. Следовательно, операционная система
Linux -
модульная, многопо
точная, с приоритетным планированием самого ядра.
Рассмотрим следующие особенности ядра
Linux -
то, чем оно отличается от
других Uniх-подобных систем:
•
Ядро
Linux
поддерживает динамическую загрузку модулей ядра . Хотя
ядро и является монолитным, его функционал можно расширить без пе
рекомпиляции ядра путем динамической загрузки исполняемого кода из
модуля.
•
Ядро
SMP (симметричную многопроцессорную об
Современные Unix также поддерживают SMP, но традицион
Unix, существовавшие в момент, когда появилась Linux, такой
Linux
работку).
ные ядра
поддерживает
поддержки не имели.
•
В ядре
Linux
поддерживается приоритетное планирование. В отличие от
традиционных версий ОС
Unix,
ядро
Linux
в состоянии прервать выпол
нение текущего задания, даже если оно работает в режиме ядра. Если го
ворить о
Solaris
и
Unix, то поддержка приоритетного планирования есть только в
IRIX. В большинстве ядер других вариантов такая возможность
отсутствует.
•
В
Linux принята объектно-ориентированная
модель устройств, в которой
поддерживаются классы устройств, события, возникающие ripи горячем
подключении устройств, и файловая система в пространстве пользовате
ля
•
sysfs (userspace device filesystem) .
·---------------------------------------------------------------------------------
...
и 11111 l ,illll\
•
В ядре
•
В ядре
....................... n.1nux
Linux используется интересный подход для поддержки многопо
точности (threads): потоки ни чем не отличаются от обычных процессов.
Linux
отсутствуют некоторые функции ОС
Unix,
которые разра
ботчики посчитали плохо спроектированными, как, например, поддержка
интерфейса
STREAMS,
или поддержка стандартов, которые невозможно
аккуратно реализовать
2.3.
Вереи~ ядра
Linux
Прежде , чем мы приступ к следующей главе, нужно поговорить о версиях и
вариантах ядра. Начнем с вариантов.
Существуут два варианта ядра
-
стабильный (staЫe) и разрабатываемый
(development).
Разрабатываемый вариант переходит в стабильный по окончанию тести
рования. То есть новые стабильные версии ядра обычно выпускаются для
исправления ошибок и предоставления новых драйверов устройств. В раз
рабатываемых версиях ядра допустима некорректная работа некоторых ком
понентов
-
это в порядке вещей, поскольку ядро еще не объявлено стабиль
ным. Поэтому для production-cиcтeм , таких как серверы,, рабочие станции
обычных пользователей подходят только стабильные варианты ядра. Для
энтузиастов, желающих попробовать новые функции ядра, которые еще не
стали достоянием общественности, и помочь сообществу разработчиков
протестировать эти самые новые возможности, как раз и предназначен раз
'рабатываемый вариант.
Понять, какой вариант ядра используется конкретно в вашей системе, очень
просто: по номеру версии. Версию ядра всегда представляют три или четыре
числа. Если числа четыре
ку четвертое число
-
-
-
перед нами
(major)
-
номер младшей версии
dеv-вариант, если четный
dеv-вариант
-
(minor),
а первое
версии. Также можно понять, какое ядро перед
нами по номеру младшей версии. Если он нечетный
• 4.1.2 -
выпуск, посколь
это как раз номер стабильной версии. Третье число
номер выпуска, второе число
основной номер
100% стабильный
-
значит перед нами
стабильный. Рассмотрим примеры:
(minor = 1)
•
8 8 ···············-·-·----·---·---··--··---·---··---·---··---·---··--·----·-·-··-·-··
1J laвa
n.1nux . •................ .
• 4.2 -
2 . Ot·11c111111.1t· c:иt•J tt'IIIHI CI Щ{llt'
стабильный вариант (два последних числа опуще ны), (<стабиль
ность» определяется по четному значению
• 4.2.10.1 -
minor.
стабильный вариант, номер выпуска
бильной версии
(revision)
= 1О ,
номер ста
- 1.
Процесс разработки ядра включает несколько фаз. Вначале разработчики
ядра работают над новыми функциями, что напоминает хаос. Через опре
деленное время ядро оказывается сформировавшимся, и, в конце концов,
объявляется о замораживании функций. Начиная с этого момента никакие
новые запросы на 1щлючение новых функций в ядро не принимаются . Счи
тается, что ядро достигло стабильного уровня и его исходный код заморажи
вается.
2.4.
Выбор ядра при загрузке
У вас (даже если установлен всего один дистрибутив) может быть установ
лено несколько ядер. Напри~ер , вы можете установить дистрибутив, в нем
будет одна версия ядра, а затем установить более новую версию ядра вруч
ную. При загрузке вы сможете выбрать нужную вам версию ядра. На рис.
2.2
показано меню загрузчика
выбрать одну из версий ядра
•
Рис.
2.2.
Astra Linux, где пользователю
- generic или hardened.
предлагается
Выбор ядра при загрузке системы
... -... -. --- -. -. -... --- -- -- ---- ------ . ---- --. -· -- - . ---- . -. -...... ---- --- -- ---. -... . . .
Ядро
Linux
....................... t'l.inux
Вторая версия повышает общую защищенность системы от взлома. Так,
h ardened-ядpo умеет блокировать массу потенциально опасных операций, а
компилятор
hardened-gcc
позволяет защитить компилируемые им програм
мы от взлома типовыми методами вроде переполнение буфера. Грубо гово
ря , если у вас стоит «дырявая» версия программы Х, и ее пытается взломать
хакер , то в обычной системе у него это получится, а в
hardened -
не полу
чится, да еще и в лог запись пойдет.
Номер версии ядра выводится при входе в систему (если вы входите в консо
ли) или его можно узнать командой ипате -а (рис.
что в UЬuntu
20.04
используется версия ядра
Рис.
2.3.
2.3). На рис. 2.3
5.4.С - даже не 5.7.0.
показано,
Команда ипате -а
2.5. Сообщения ядра при загрузке
При загрузке ядро выводит сообщения, просмотреть которые можно коман
дой:
dmesg I les s
. ........
•
1 11, 111.1 _)
n_,nux ................. .
Ot· 1ю11111.1t• t·щ•, 1t•111111 1111щн·
Обычно сообщения ядра понятны сами по себе без особых комм е нтариев .
Например , в самом начале выводится версия ядра и переданные ядру пара
метры :
0.000000) Linux version 5 . 4 . 0- 39 - generic (buildd@lcy01 - amd64-016)
(gcc version 9 . 3.0 (Ubuntu 9 . 3 . 0- 10ubuntu2)) #43 - Ubuntu SMP Fri Jun 19
10 : 28 : 31 UTC 2020 (Ubuntu 5.4.0 - 39 . 43 - generic 5.4.41)
0.000000) Command line :
BOOT_IМAGE=/boot/vmlinuz - 5.4 . 0 - 39-generic
root=UUID=05fd3e4e-1605 - 478c - 8db9 - bбdf62a01ad3
ro quiet splash
Карта физической памяти :
0 . 000000)
0 . 000000)
0 . 000000]
0 . 000000]
0 . 000000]
0 . 000000)
0 . 000000 ]
0 . 000000)
0 . 000000)
0 . 000000)
0.000000)
О . 000000]
BIOS- e820 :
BIOS- e820:
BIOS- e820 :
BIOS- e820 :
BIOS- e820:
BIOS- e820:
BIOS- e820:
BIOS- e820:
BIOS- e820 :
BIOS- e820 :
BIOS- e820:
BIOS- e820 :
[mem
[mem
[mem
[mem
[mem
[mem
[mem
[mem
[mem
[mem
[mem
[mem
0x0000000000000000- 0x000000000009efff] usaЫe
0x000000000009f000- 0x000000000009ffff] reserved
0x00000000000ca000- 0x00000000000cbfff] reserved
0x00000000000dc000- 0x00000000000fffff] reserved
0x0000000000100000- 0x000000001fedffff] usaЫe
0x00000000lfee0000- 0x00000000lfefefff] ACPI data
0x00000000lfeff000- 0x00000000lfefffff] ACPI NVS
0x00000000lff00000- 0x00000000lfffffff] usaЫe
0x00000000e0000000- 0x00000000efffffff] reserved
0x00000000fec00000- 0x00000000fec0ffff] reserved
0x00000000fee00000- 0x00000000fee00fff] reserved
0x00000000fffe0000,- 0x00000000ffffffff] reserved
Сообщит, что найдена SМР-таблица (значит, наша машина является много
процессорной или хотя бы содержит процессор с несколькими ядрами) :
0 . 000000) found SMP
at
МР - tаЫе
at [mem
0x000fбbf0 - 0x000fбbff]
mapped
[ffff8800000fбbf0 ]
Выведет информацию о процессоре:
0 . 694470) smpboot : CPU0 : Intel(R) Core(TM) i5 - 7200U CPU@ 2 . 50GHz
(family: Охб , model: Ох8е , stepping: Ох9 )
0.715491) smp : Brought up 1 node , ·2 CPUs
Частоту процессора и рейтинг в «попугаях»:
•
··---. ·-- ... -·· ......... . -- ·---· ·---. -- -··- -- ...... -... ·-·. ·- -···· ............... --
И , 1р11
l .i1111x
•······················
rtiпux
0.00000 1 ) t sc : Detected 2711 . 997 MHz processor
0 . 71 54 91) smpboot : Total of 2 processors activated (10847 . 98 BogoMIPS )
это псевдорейтинг, который показывает, сколько миллионов
BogoMIPS -
пустых операций процессор может выполнить за секунду. Судить о произво
дительности по этому рейтингу можно только косвенно.
Исследуйте вывод ядра самостоятельно. Уверен, в нем вы найдете много ин
тересного, в том числе и о своей системе.
2.6.
Передача ядру параметров
Поскольку ядро
-
это щ~ограмма, то ней можно передать параметры, влия
ющие на поведение ядра. Первым делом разберемся, как передать ядру па
раметры . Сначала в меню загрузчика нужно выбрать загрузочную запись,
которую вы хотите отредактировать (рис.
2.2).
Далее нужно нажать е для ре
дактирования конфигурации загрузчика. Среди строк конфигурации
найдите строку, которая начинается со слова
загрузки ядра
после него
-
Linux. Сразу
после
«linux»
«linux».
GRUB2
Это и есть строка
указывается путь к ядру, а все, что
это и есть параметры ядра . Отредактируйте имеющиеся пара
метры или добавьте новые параметры в конец строки.
В главе
4
будет показано, как сохранить конфигурацию GRUВ2 (после пе
резагрузки внесенные_ вами изменения будут потеряны, поэтому их нужно
внести в конфигурационные файлы
Ctrl+x
для
Самые основные часто используемые параметры ядра описаны в таблице
2.1.
GRUB2),
а пока нажмите
загрузки с отредактированной вами конфигурацией.
Таблица
2.1.
Часто используемые параметры ядра
Параметр
Linux
Описание
Параметры корневой файловой системы
Указывает устройство, содержащее корневую фай-
rооt=устройство
ловую систему. Вы можете указать, как короткое имя
устройства
(/dev/sdal),
так и
UUID
устройства
.,
. ....... .. ... .. ....... -... -----. -. ---.. --... --. ---... -... --.. -- ... --... -.. -- -.. --...
1J la!Ш 2.
n..inux ----------- -- -----
Ос11ов11ыс CRC) {CIНIЯ () Я ) (рС
Тип корневой файловой системы. Обычно в нем нет
rootfstype=тип
необходимости, поскольку ядро само определяет ти п
ФС
Ядро будет ждать появления устройства с корневой
файловой системой. Вы можете держать ядро на жест-
ком диске, а корневую файловую систему на
rootwait
USB-
д иске. С точки зрения производительности может и
не очень хорошо , но зато неплохо с точки зрения безопасности, когда весь жесткий д иск с данными можно
быстро извлечь и удалить
rootdelay=N
Подождать
N
секунд перед монтированием файловой
системы
Монтирует корневую ФС в режиме «тол ько чтение».
После проверки утилитой/сsk корневая ФС будет
ro
перемонтирована в режим гw
Монтирует корневую ФС в режим «чтение/зап ись».
Но тогда вам нужно отредакти ровать сценарии ини-
rw
циализации системы и удалить из них вызов утилиты
fsck, поскольку
проверять ФС в режиме
,-w этой
ути -
литой нельзя
Параметры , связаю-1ые с аппаратными средствами
llOSCSI
Отключает поддержку
SCSI
nousb
Отключает поддержку
USB
nopcmcia
Откл ючает поддержку РСМСIА-карт
noap1c
дите при загрузке сообщение об ошибке , связанной с
Отключает поддержку
APIC.
Полез ен, если вы уви-
APIC
•
.-... -· ....... -.... -... - ...... , ........... -- .............. -.. -. -. -........ -. -... -. . .
Ящт
l ,i1111x
notlmraid
mem=xxxxM
................•....... n.1nux
Отключает прогр аммные RАID-массивы, созданные
на уровне
BIOS
Задает точный размер оперативной памяти , например ,
mem=4096M
Задает VGА-режим . Можно попросить ядро позволить
vgа=режим
вам выбрать оди н из режимов , передайте ядру такой
пар аметр
- vga=ask
Параметры управления питанием
noapm
acpi=off
Отключает расширенно е управление питанием АРМ
Отключает
.
.
pc1=noacp1
ACPI (Advanced Configuration and Power
Interface)
Отключить
APCI для PCI
Общесистем.ные параметр ы
Позволяет указать систему инициализации. Во многих
системах, если указать в качестве <программа> /Ьin/
bash
init=программа
вы получите тот же однопользовательский ре-
жим, но при этом система не будет запрашивать у вас
пароль
root, поэтому такая
лазейка часто используется
для обхода системы безопасности и несанкционированного доступа
rеЬооt=тип
single
..
quiet
Указывает тиri перезагрузки :
warm (теплая) или cold
(холодная)
Однопользовательский режим, которы й может использоваться для восстановления системы в случае сбоя
Отключает большинство сообщений ядра при загрузке
системы
'
.
. -- ..... . -............. -............................... . ....... . ... .. .... . ... . ... .
1 1:111:1
ainux ........ ......... .
Задает задержку в
2
0t'IIШllll,lt' t'llt', lt'IIIHI II И . ll)t'
N секунд перед выводом следующе
го сообщения ядра. Система будет загружаться очень
boot_delay=N
медленно , лучше дождаться загрузки , выполнить ко
манду
dmesg и
в спокойной обстановке прочитать все
сообщения
•
.. --... -. ----......... ...... ..... -........................................... -....
-
Глава
3.
Компиляция ядра
И 1 tр11
l ,i1111x
...................... n.1nux
В этой главе мы в общих чертах рассмотрим получение исходных кодов,
компиляцию и установку ядра в произвольной Linuх-системе-без привязки
к какому-то дистрибутиву. Однако в каждом дистрибутиве есть свои особен
ности, поэтому мы также рассмотрим весь этот процесс в UЬuntu
получение и установку ядра
3.1.
22.04 -
6.0.
Получение исходников ядра
Исходный код ядра
Linux
можно скачать с сайта
kernel.org.
На этом сайте
доступна как последняя версия ядра, так и архивы с предыдущими версия
ми. Вы можете скачать как полный исходный код, так и инкрементный патч,
позволяющий повысить версию ядра без закачки всех исходников. Такие
патчи удобны, если вы, например, скачали, откомпилировали и установили
ядро, скажем, версии
5.4,
а затем хотите перейти на версию
5.6.
В этом слу
чае вам не нужно опять скачивать исходники, которые довольно объемны, а
достаточно скачать только патч (набор изменений), который превратит вашу
версию
5.4
в более новую
5.6.
•
. . ........................... . .......................................................
t\.inux ____ ~ ____ . _. ______ .
I . 1 ана
] . Ко,11111 . 1я11ш1 я , 1ра
Тhе Unux Kemel Archives
.1,оо..(
Protoeot
Ctint.tctus
FAQ
R~
Srtenews
Loc.aoon
НТТF
T,;n:::м-r.•,.J.~or9fp,;c:
Grт
https:t :9!t_i<efr~!)(9,'
f<S't'NC
~yтx::;;rsync.kerrie'-Or(J/p.11)/
Latest Retease
6.1.6(!)
m,ift!м:
61-n:4
2023,-01-15
s~bl.f'
6.t6
6.0.'19{EOLJ
2023-01•14
(\.,t~ЪЗЦJ
202Н)1-12
{tilJl'DiЩ {pgpJ
st.lЬl.e:
~
longtt!rm: 5,15,88
longtemt 5..IOJ63
{t;,rЬ.JЩ
[pc;;pl
(P4ctl] [mc p«"..h] [>kw d:ff]
(ЬrowиJ
(p,щt,J !кх p,щhJ
{Ьrc;,,-1\.\!'J (<!'·>iП19"\09]
[view c,lfJ
{p.ttd1] {,nc.p.,t::h} [.--,d.;ff) {hra,,,"!:~} [ c . ~ J
2023-а!·\.4 [tart!JЩ lpqpJ (p.tt~h] {tr.( ~t,h] [ww cHfJ f~-s4!] [ < ~
202)-01..14 l~lU {pqp] [patd,j {ll"IC.~td1] ['l!f№tciiff'J {brc-f,;~~J ( c ~ J
2022-12-i9 t~a~ilJ INPI {pact!] {н·к p,.1Ш"IJ {-.,"!t'\", c:,ff] [~""::-eJ [с~~
Ю2.2-12-14 l~J] {pgpJ lp,tdt! firoc. puthJ !'МW o:tf] (Ьw,vstJ { c r ~ J
Lon9term: 5.4.228
longten-n: 4..19.269
longtмn: 4.\4.302
2022-12•14 [t;,ri).1:l] [P9PJ !pгtd1) ['1'!( p.,t::hj {--.-, d:ffJ [orov.-::t] [c:~lo,;j
tDngtem,: 4..9.337 [EOLJ 2023-ОЧ)7 [..1rnai.lJ (P9PJ {~rthj (irx ~,h] !VteW a.ffJ tью,,мJ {(r~togJ
Ur..A~xt: nut-20130t17 2023-0\-17
Other moun:es
Рис.
3.1.
Сайт
Sacial
www.kerneLorg,
Как видите, можно скачать
где можно скачать самые разные версии ядра
tarball
(архив с расширение
tar.gz),
а также патч
(patch).
Однако загрузка исходников с сайта
kemel.org -
это для новичков . Если у вас
уже есть опыт разработки на одном из современных языков программирова
ния, скорее всего, вы уже знакомы с
Git -
Git.
это система версий, позволяющая отслеживать вносимые отдельны
ми разработчиками изменения в проект программного обеспечения.
Примечательно, что
Git также
был разработан Линусом Торвальдсом имен
но для обслуживания исходных кодов ядра
Linux,
когда другие подобные
системы перестали соответствовать его требованиям .
Если опыт работы с
Git у вас
есть, сам будет гораздо проще использовать
git
для получения исходников ядра:
$
gi t clone
•
git://git . kernel.org/puЬ/scm/linux/kernel/git/torvalds/linux.git
·--------------------------------------------------------------------------------- -
}11р11 l.i1111,
...................... n.1nux
После загрузки исходного кода нужно обновить дерево до состояния послед
него обновления, которое сделал Линус. Для этого введите следующее:
$ git pull
Данные команды позволяют загрузить последнюю версию ядра
Linux
с
последними правками . Если нужна определенная версия ядра, тогда, можно
ее указать при получении репозитария:
$ git clone git :
linux - 6 . 2 . gi t
3.2.
// git.kernel.org / puЬ/scm / linux / kernel / g i t / t o rvalds /
Распаковка архива с исходным кодом
Получив исходные коды, нужно их откомпилировать. Архив
кода ядра распространяется в сжатых форматах
.tar исходного
GNU zip (gzip) и bzip2 .
Фо.рмат bzip2 лучше, поскольку он обеспечивает больший коэффициент
сжатия по сравнению с форматом
имя
linux-x.y.z.tar.bz2, где x.y.z -
gzip.
Архив ядра в формате
bzip2
имеет
номер соответствующей версии исходного
кода ядра.
После загрузки файла его нужно распаковать с помощью простой команды.
Если .tаr-архив сжат с помощью утилиты
bzip2,
введите такую команду :
$ tar xvjf linux - x . y .z.t ar . bz2
Если сжатие выполнено с помощью
gzip,
то команда должна иметь следую
щий вид :
$ tar xvzf linux -x. y . z . tar . gz
Обе эти команды позволяют разархивировать и развернуть дерево исходных
кодов ядра в каталог
linux-x.y.z.
При использовании
Git
для получения ис
'
ходного кода ядра и управления им вам не нужно загружать архив в формате
. . ..---------------. --------------. --.. ---. ---. ---.. ---. ----••• -.. ------------. ----.
1 1,111,1 ,
n..1nux ..... .. ........... .
.tar.
Просто введите команду
git clone,
К1ш1111 . 1ш1ш1 ii 1ра
как было описано ранее, и она сама
загрузит и распакует самую последнюю версию дерева исходного кода ядра .
3.3.
Использование п атч ей
Если вы скачали не полный исходный код, а только заплатку (патч), тогда
применить ее можно так :
patch - p l < .. / patch - x . y.z
$
Разумеется , нужно перейти в каталог, содержащий дерево исходных кодов (в
каталог, в который вы распаковали архив с исходниками) и сами исходники
должны существовать (должны быть ранее загруженными).
3.4.
Содержимое каталога с исходным и код ами
После распаковки исходного кода в папку
li"nux-x.y.z вы обнаружите множе
ство подкаталогов . Рассмотрим их содержимое:
исходный код, специфичный для аппаратной платформы .
• arch Ыосk
•
-
слой блочных операций ввода/вывода.
• crypto -
криптографический
• Documentation • drivers -
различная документация.
•
драйверы устройств.
• firmware • fs -
API.
микропрограммы устройств , необходимые для использования
подсистема виртуальной файловой системы и отдельные файловые
системы .
• include -
заголовочные файль1 ядра.
• init -
код для загрузки и инициализации ядра.
• ipc -
код межпроцессного взаимодействия.
,
_
--. --... --.. -------. ----. ---.. ---. ---.. -... --- . --... --.. --.. -.... ---. ----. --- . --
Я . 1ро
[,inux
• kernel -
• lib -
______________________ n..inux
основные подсистемы ядра , такие как планировщик .
вспомогательные подпрограммы.
• nm -
подсистема управления памятью и поддержка виртуальной памяти.
• net -
сетевая подсистема .
• samples • scripts -
сценарии компиляции и построения ядра .
• security • sound • tools • usr • virt -
примеры и демонстрационный код.
модуль безопасности
Linux.
звуковая подсистема.
вспомогательные утилиты для разработки
Linux.
код инициализации пространства польз ователя.
инфраструктура виртуализации.
Кроме подкаталогов в каталоге с исходниками будут несколько файлов.
Самый главный файл
3.5.
- Makefile, содержащий
инструкции по сборке ядра.
Сборка ядра
Сборка ядра достаточно проста и в некоторых случаях даже проще, чем
сборка некоторых других программных продуктов. Но при сборке ядра нуж
но первым делом его сконфигурировать. Ведь ради этого часто и устраивают
перекомпиляцию ядра , поскольку при установке системы ядро то уже отком
пилировано и прекрасно работает. Часто целью перекомпиляции является
добавление нового функционала в ядро - поддержку необходимых драйверов
•
и функций . Поскольку в ядре существует бесчисленное количество функций
и вариантов поддерживаемого аппаратного обеспечения, возможностей по
конфигурации , мягко говоря, много . Процесс конфигурации выполняется с
помощью указания ряда параметров конфигурации в виде
CONFIG_ФУНК
ЦИЯ. Например, поддержка симметричной многопроцессорной обработки
(Symmetric multiprocessing, SMP) устанавливается с помощью параметра
CONFIG_SMP. Если этот параметр установлен, то поддержка функций SMP
включена. Если не установлен , то функции поддержки SMP отключены. Па
раметры конфигурации используются как для определения того , какие фай-
•
. . . . . ...............................................................................
I ~ iaвa
n..inux __________________ _
3.
Ко\11111 . 1я1щя я . 1ра
лы должны быть скомпилированы во время сборки ядра, так и для управле
ния процессом компиляции через директивы препроцессора.
Параметры конфигурации, которые управляют процессом сборки ядра,
бывают двух типов: логические (boolean) и с тремя состояниями (tristate).
Логические параметры могут принимать значение
ло, параметры конфигурации ядра наподобие
yes или по. Как прави
CONFIG_PREEMPT являются
логическими. Параметры конфигурации с тремя состояниями могут nри
нимать значение
yes,
по или
module. Значение module
означает, что данный
параметр конфигурации установлен, но соответствующий ему код должен
быть скомпилир<,шан в виде модуля (т.е. как отдельный объект, который за
гружается динамически). В случае параметров конфигурации с тремя со
стояниями значение
yes
явно указывает на то, что соответствующий код
должен быть скомпилирован в основной файл образа ядра, а не в виде моду
ля. Драйверы устройств обычно определяются параметрами конфигурации
с тремя состояниями .
Параметры конфигурации можно задавать также в виде строк символов или
чисел. Эти параметры не управляют процессом сборки ядра, а позволяют
указать значения , которые встраиваются в исходный код с помощью дирек
тив препроцессора . Например, с помощью параметра конфигурации можно
указать размер статически размещаемого массива.
Ядра многих дистрибутивов компилируются как часть дистрибутива и даже
поставляются в виде RРМ/DЕВ-пакетов. В таких дистрибутивах может быть
несколько уже скомпилированных ядер, например, одно с поддержкой
другое
-
SMP,
без поддержки. Вы можете установить нужный пакет с помощью
обычного менеджера пакетов, ядро установится, а потом выберите его в
меню загрузчика при загрузке системы или настроите автозапуск нужного
ва!-1 ядра.
Но иногда бывает, ч:го ядро нужно скомпилировать, например, для реализа
ции поддержки определенного оборудования, самостоятельно. Или же вы
хотите попробовать новую версию ядра
-
как правило, энтузиасты этим
часто заморачиваются. В любом случае у каждого свои причины перекомпи
лировать ядро, если вам это нужно, то вы должны знать зачем.
Конфигурирование ядра осуществляется или посредством редактирования
файла
.config
или же с помощью специальных утилит. Редактировать вруч
ную можно, если вам нужно включить/выключить
r,Iapy
опций, и вы точно
знаете, как они называются. Во всех остальных случаях нужно использо
вать утилиты конфигурации. Для запуска утилит конфигурации используйте
одну из трех команд :
'-------------------------------------------------------------------------------- -818
Я 1р11 1 . iща
$
- - - ___________________ t'linux
ma ke config
$ make menuco nfig
$
make gconfig
Первая утилита работает в текстовом режиме. Она будет работать всегда, в
отличие от той же
Linux
gconfig,
которая не будет работать , если вы установили
без поддержки графического интерфейса (на серверах он лишний).
Вторая наиболее удобная - она и удобнее, и работает в консоли.
В этих трех утl):литах все параметры конфигурации делятся на категории
вроде Processor Туре and Features (Типы и свойства процессора). При этом
пользователь имеет возможность перемещаться по категориям , просматри
вать параметры конфигурации ядра и, разумеется , изменять их значения.
Иногда бывает так, что вы внесли изменения в конфигурацию , перекомпи
лировали и установили ядро , а система после этого не запускается или же
что-то работает некорректно . Нужно загрузиться с использованием преды
дущего ядра и ввести команду:
$
make defconfig
Данная команда позволяет создать файл конфигурации, содержащий стан
дартные значения параметров для текущей аппаратной платформы . После
этого нужно снова перекомпилировать и установить ядро , либо же попы
таться снова
-
внести изменения в конфигурацию и при этом быть более
внимательным .
Параметры конфигурации сохраняются в файле
.config,
который находится
в корне дерева каталогов исходного кода ядра. Большинство разработчиков
считают, что гораздо проще непосредственно отредактировать этот файл
конфигурации. В самом деле, с помощью любого текстового редактора
достаточно легко выполнить поиск нужного параметра в этом файле и из
менить его значение. После внесения изменений в файл конфигурации или
при использовании существующего файла конфигурации для нового дерева
каталогов исходного кода ядра, его необходимо ратифицировать и обновить
конфигурацию с помощью команды
$ make oldconfig
•
- - ----------------------------------------------···-----···--------------·---------·
1 1,111,1 '
n..lnux .................. .
k°ll\11111 . IIIIIIHI 11
tpa
Эту команду вам также нужно запустить перед сборкой ядра . Параметр кон
фигурации
CONFIG_IKCONFIG_PROC
позволяет сохранить все текущие
параметры конфигурации ядра в виде сжатого файла
его в каталог
config.gz
и поместить
/proc. Это позволит вам легко создать клон текущей конфигура
ции при сборке нового ядра. Если этот параметр конфигурации установлен в
вашем текущем ядре , то просто скопируйте файл
config.gz
из каталога
/proc
и воспользуйтесь им для создания нового ядра, как показано ниже.
$ zcat /p roe / config.gz > . config
$ make oldconfig
После того , как вы сконфигурируете ядро , его можно откомпилировать. Для
этого введите команду :
$ make
Выполнение команды
make
занимает весьма прилично времени. Сколько
именно, зависит от производительности вашего компьютера. Бывает так, что
компиляции ядра нужно ждать несколько часов. Но ничего не поделаешь,
придумайте , чем заняться это время .
3.6.
Компиляция м одулей
После компиляции ядра нужно также откомпилировать модули. Когда вы
настраиваете функции ядра с помощью программы конфигуратора, вы мо
жете ту или иную функцию выключить, включить или же оставить включен
ной в виде модуля
-
вариант М . Включать нужно те функции, которые вам
нужны всегда, а вот если функция постоянно не нужна, например, tюдцерж
ка какого-то устройства, которое потенциально вам может пригодиться, вы
можете оставить ее включенной в виде модуля. После компиляции ядра вам
нужно откомпилировать модули, то есть все функции, которые вы пометили
как М. Для компиляции модулей нужно ввести команду :
$ make modules
•
.. . -- -----...... -..... -. ---. ------------ .. ---------.. -. -. ---.. ----. -... --. ----·. -.
-
Я . tро l,iщ1x
______________________ n..inux
Время выпо.i:~нения этой команды зависит от количества функций, которые
вы отметили как М. Тоже придется подождать некоторое время.
После компиляции модулей их нужно установить:
$ sudo make modules install
3. 7. Установка
ядра
После з авершения процесса сборки ядра его нужно проинсталлировать в
системе . Процесс инсталляции существенно зависит от используемой аппа
ратной платформы и типа системного загрузчика.
Вы можете найти различные руководства в Интернете, описывающие слож
ный процесс установки ядра. В современном мире нужно ввести только две
следующие команды:
$ sudo make install
$ sudo update-grub
Перед вводом второй команды загляните в каталог /Ьооt. В нем должно быть
два файла :
initrd . img-6 . 0.0 - rc7
vm linuz-6.0.0-rc7
Номер версии может у вас отличаться . Первый файл
мяти инициализации
(lnit RАМ Disk),
второй
-
-
это образ диска па
собственно, сам файл ядра.
Вывод второй команды будет примерно таким:
Sourcing file '/ etc/default/grub '
Sourcing file '/etc/ default /g rub.d/init-select.cfg'
Generating grub configuration file ...
Found linux image: / boot / vmlinuz - 6.0.0 - rc7
Found initrd image: /boot/ initrd.img-6.0.0-rc7
. . . ---- --- --------------------------- ---- -------------------- -------------------- _,
1 с1а11а ,
n.1nux .................. .
Found
Found
Found
Found
Found
Fo u nd
К11,11111 . 1шщsr ~цра
l inux i mage : /boot/vmlinuz - 5 . 15 . 0 - 46 - gener i c
initrd image : /boot/initrd .img - 5 . 15 . 0 - 46 - g e ne r ic
linux image : /boot/vmlinuz-5 . 13 . 0 - 30 - gener i c
initrd ima ge : /boot/initrd . img - 5 . 13 . 0 - 30 - gene r ic
memtes t 86+ image : /boot/memtest86+ . elf
memtes t 86+ image : /boot/memtest86+ . b i n
Команда
sudo
нужна для устано вки ядра (первая команда) и обновл ения
конфигурации загруз чика (вторая команда) . После этого можно перезагру
зить систему командой
reboot и
Примечание.
пробовать новое ядро .
Компилировать ядро
вы
можете как обычный
пользователь, а вот для установки ядра нужны полномочия
3.8.
Практический пример: установка ядра
Пbuntu
6.0
root.
в
22.04
Представим , что у нас есть последняя версия дистрибутива UЬuntu. Понят
но, что разработчики дистрибутивов не всегда поспевают за разработчиками
ядра и бывает, что в последней версии дистрибутива версия ядра далеко не
самая последняя . Попробуем проапгрейдить ядро до версии
6.0
(установка
других версий, по крайней мере линейки 6 . х, будет выполняться аналогич
но) на примере дистрибутива UЬuntu.
Первым делом посмотрим , какая версия ядра используется в данный момент:
uname
-а
Вывод будет таким:
Linux ubuntu2204 5 . 15 . 0- 33- generic #34 - Ubuntu SMP Wed
UTC 2022 х86 - 64 х86 - 64 х86 - 64 GNU/Linux
Установим все необходимые пакеты для сборки ядра
-
Мау
18 13 : 34 : 26
без них у вас ничего
не выйдет:
•
·-------------------------------------------------------·-···------------···-····· 8 1 1
.. _·_.................. n.inux
apt install build- essential dwarves pythonЗ libncurses - dev flex
libssl - dev Ьс libelf - dev zstd gnupg2 wget -у
Ьison
После этого можно загрузить исходники ядра :
wget https : // git . kernel . o rg / torvalds / t / linux-6 . 0-rc7 . tar . gz
После загрузки распакуем архив:
tar xvf linux~б . 0 - rc7
cd linux - 6 . 0-rc 7 /
. tar . gz
Скопируем текущую конфигурацию ядра в
.config -
чтобы вы использовали
конфигурацию с включенными опциями , которые включены в вашем ядре .
Иначе может оказаться , что какая-то опция будет выключена, и система бу
дет работать некорректно после сборки ядра :
ер
- v / boot /config - $ (unarne - r ) . config
Запустим программу конфигурации:
rnake rnenuc onfig
t\l'luм:/xвf 6 е e-rc.7 tetn-•l t:<it,ftt a111..Arrow k«ys n•vtg•te the ~f1U, <Enter> selects sub,ienus •«·> (or •f'IPty sl.lt>мnus ••••) , Ht9M.t9tttt-d \.t'tter~ •re i'totk.eys. Press\ng
<V.., tnclud•s# <N> •:itc\ud•s, цt" f'IOdu\~rt z:es f••tuгes. Pres.s <Esc ...<Ese> t.o ex\t, <?> for Help, </> for St!aгch. Legend: [•] bui.lt-1..n
( ) t'l(Ctude-d <f-1;,o l'!Odu\e , > f'IO'duie- cap111>te
IMЮФ№W!4HW
('"}
М--Ь.t t k:ernel
Processor ty~ and features
••• ,.
["} Jltitig•Hons for s~c:utat\ve eмecut\on vulner•b\.\\t1.es (HfW)
P~ r 11.anagt-Nnt •nd дс Р I opt1on.s • • •>
t us opttoos (PCI etc:,) ••• )'
нn"ry E111Jt1t1.ons . ·•• ►
("' ) Hrtuf\\tllt\O'l'I ••• ,.
. t:en.rat arch\tec:ture-de~nd•nt opt1.ons
[•1 f.naЫe \oadab\e мdu\.e 5uppoгt • ••;.
{ •) 1' n1Ь\.~ tlм btcx.k t•у~г • .. ,.
Extcu-tabl. ♦ f1.lt fornats
•··~
№,юrу М!lna~ent optt<0ns
[•]
tц twoгktng support
•· •~
~v\ct Or\.vtrs ••• ,.
Н\е
syste"s
• ·•· >
$Atcur\ty optto"s • • • ►
·•· Crypt09r•ph\.<: API • .. ,.
t \brary rourtnes ••·>
Kitrne\ har::k\ng
Рис.
3.2.
••• ►
Конфигуратор ядра в
Ubuntu 22.04
1
n..inux .................. .
1, 11\,1 \
"'41\\1111 . IШIIШ SI
rpa
Внесите изменения в конфигурацию ядра. Можете ничего не вносить, если
просто хотите научиться перекомпилировать ядро. Обязательно (если вноси
ли изменения) нажмите кнопку
Save.
Далее нужно отключить SYSTEM_REVOCAТION . Это можно сделать ко
манд ами:
scripts/config -- disaЬle SYSTEM REVOCATION KEYS
make localmodconfig
Построим сжатый образ ядра
-
он занимает меньше места на диске :
make bzlmage
Вывод будет примерно таким :
SYNC
include /co nfig /au to . conf.cmd
_HOSTCC scripts/kconfig / conf . o
HOSTLD scripts/kconfig/conf
SYSHDR arch/x86/include/generated/uapi/ a sm/unistd_32 . h
SYSHDR arch/x86/include/generated/uapi/asm/un i s t d_ 6 4. h
SYSHDR arch/x86/include/generated/uapi/asm/unis t d_ x32 . h
SYSTBL arch/x86/include/generated/asm/sysca lls _ 32 . h
SYSHDR arch / x86 /i nclude/generated/asm / un is td_ 32_ ia32 . h
SYSHDR arch / x86 /i nclude/generated / asm/unistd_64 x32.h
После этого соберем и установим модули:
make modules
sudo make modules install
Осталось установить ядро и обновить загрузчик :
sudo make install
sudo update - grub
•
··------------------------··------ ----------···-··--······ ··· ·· · ··················-811
Я , 11ю
l .i1111,
...................... t\.1nux
Перезагружаем компьютер:
reboot
После загрузки введите команду :
uname
-а
Вы должны увидеть версию ядра :
Linux ubuntu2204 6 . 0 . 0 - rc7
Мы видим , что версия ядра изменилась на
6,0,
Собственно, на этом все. В
следующей главе мы поговорим о такой важной части при работе с ядром
Linux
как настройка загрузчика
команда
GRUB -
чтобы вы понимали, что делает
update-grub.
•
............................. ------------... --- ----. ---. ---.. ---. ---. --------. ----. -.
Глава
Загрузчик
4.
GRUB2
Ядро
4.1.
l,inux
...................... n..inux
Загрузчики
Linux
Существует несколько за~узчиков
1
Linux.
На сегодняшний день основным
загрузчиком является GRUВ2, который устанавливается по умолчанию во
всех современных дистрибупrnах
Linux.
Одним из самых "древних" загрузчиков является
загрузчик давно
уже
не
используется
и
GRUB (GRand Unified Bootloader). GRUB
ему
LILO (Llnux LOader).
на
смену
пришел
является более гибким загрузчи
ком и "понимает" _ много разных файловых систем, в том числе
ext2,
ехtЗ,
На смену
Этот
загрузчик
FAT/FAT32,
ReiserFS, XFS, BSDFS.
GRUB
пришел загрузчик
GRUB2.
Его особенности
-
очень запу
танный и неудобный файл конфигурации, но время не стоит на месте, и если
вы хотите использовать последние новинки в мире файловых систем
Linux,
ext4 и загрузку с LVM, вы должны использовать
GRUB2 . Также GRUB2 подцерживает UEFI, но это пригодится вам, только
если вы - счастливый обладатель жесткого диска объема 2 Тб . или больше.
а именно файловую систему
Собственно,
GRUB2 сейчас устанавливается во всех современных дистрибу
тивах, и нет смысла возвращаться на GRUB. Если возникнет необходимость,
вы можете вернуться на обычный GRUB, установив пакет grub-legacy, но
такая возможность есть только для платформы х86.
•
n..inux ................. .
4.2. Конф и гурацио нные
В каталоге
фа йл ы
/etc/grub.d хранятся шаблоны ,
определяющие настройки
Также некоторые его параметры хранятся в файле
шаблонам из
mkconfig
/etc/grub.d
и файлу
/etc/default/grub
GRUB2.
/etc/default/grub . По
программой /usr/sЬin/grub
создается рабочий конфигурационный файл /Ьoot/gruЬ/grub . cfg,
который по задумке разработчиков
GRUB2
вы не должны редактировать
вручную.
Поэтому есть две стратегии настройки
GRUB2.
Первая заключается в непо
средственном редактировании файла /Ьoot/gruЬ/grub.cfg. Загрузчику
все равно , кто или что отредактирует этот файл
-
GRUB2
или вы или программа
grub-mkconfig . Вторая заключается в редактировании файлов из катало
га /etc/grub.d и файла /etc/default/grub. После чего вы будете должны ввести
команду grub-mkconfig для создания файла /Ьoot/gruЬ/grub . cfg по заданным
вами настройкам.
Чтобы решить , какая из стратегий для вас лучше, нужно знать формат и со
держимое всех этих файлов. Начнем с основного файла конфигурации, кото
рый сложнее и длиннее файла конфигурации обычного
Листинг
4.1.
GRUB ( см. лист. 4.1 ).
Файл конфигурации /boot/gruЬ/grub.cfg
#
Не
редактируйте
#
Он
автоматически
#
#
из
#
этот
файл
вручную !
#
генерируется программой grub- mkconfig
/etc/grub .d и на'стройкам из /etc/de fault /g rub
по
ш абло на м
### НАЧАЛО файла /etc/grub . d/OO_header ###
if [ - s $prefix/grubenv ] ; then
load env
fi
# Загрузочная метка по умолчанию
set default= " O"
if [ " ${prev_saved_entry} " ] ; then
set saved_entry= " ${prev_saved_entry} "
save_env saved_ entry
set prev_saved_ entry=
save_env prev_ saved_entry
•
·················································································· C I I
}l , 11ю l,i1111,
......-................ n.1nux
set boot once =true
fi
function savedefault {
if [ -z " ${boot_once} " ]; then
saved_entry= " ${chosen} "
save env saved_entry
fi
function
insmod
insmod
insmod
insmod
load video
vbe
vga .
video bochs
video cirrus
i nsmo~ part_msdos
insmod ext2
# Корневое устройство
set root= ' (hdO , msdosl) '
search --no- floppy - -fs-uuid -- set=root Ь7300e54 -fff5-4f31 - 8002 -Ьea43c64f344
if loadfont /usr/share/gruЬ/unicode . pf2 ; then
set gfxmode=640x480
load video
insmod gfxterm
insmod part_msdos
insmod ext2
set root= ' (hdO,msdosl) '
search - -no-floppy - -fs - uuid - - set = root b7300e54 - fff5-4f31 - 8002 bea43c64f344
set locale dir=($root)/boot/gruЬ/locale
set lang=ru_RU
insmod gettext
fi
t erminal output gfxterm
set timeout=S
### КОНЕЦ файла /etc/grub.d/00 header ###
### НАЧАЛО файла /etc/grub .d /05 debian theme ###
insmo d part msdos
insmod ext2
# Корневое устройство
set root= ' .(hdO , msdosl) '
search --no-floppy - -fs -uuid --set=root Ь7300e54 -fff5-4f31 - 8002 -bea43c64f344
insmod png
if background_image / usr/share/images/desktop- base/joy- grub.png ; then
set color normal=white/Ыack
set color highlight=Ыack/white
-
,
.
. . ................... . .......... . .......................... . .. . . .. . . ............... .
f.t1пux .. _..... _.. _____ ..
l .ic\ lbl
-+. Ja, р~ l'lllh" {;1н В2
else
set menu_ colo r_n ormal=cyan / Ьlue
se t menu co l or_h ig h light=white / Ьlue
fi
###
КОНЕЦ
файла
/etc/grub . d/OS_debi an_t heme ###
### НАЧАЛ О файла /e t c/grub . d / 1 0 linux ###
# Содержит главную загрузочную метку . Далее мы ее рассмотрим подробнее
menue ntry ' DeЬian GNU/Linux, Linux 5.2.0- 4- amd64 ' --class deЬian --class gnulinux -- class gnu -- class os {
load video
insmod gzi o
insmod p&rt msdos
insmod ex t 2
se t root= ' (hdO, msdosl) '
search --n о -П орру -- fs - uuid --s et= r oo t b7300e54 - fff5 - 4f 3 1-8002bea43c64f344
echo 'Загружается Linux 5 . 2.0 - 4 - amd64 ... '
linux / boot /vmlinuz-5. 2 . 0-4-amd6 4 root=UUID=b 7300e54 - fff 5- 4f31-8002bea43c64f344 r o initrd= /insta ll /gtk/i nitrd. gz q ui et
echo' ' Загружается начальный ramdisk ... '
initrd /boot/initrd . img-5. 2 . 0 -4- a md64
menuentry 'Debian GNU/Linux , Lin ux 5 . 2 . 0 - 4 - amd64 (recovery mode)'
-- class debian -- c l ass gnu-linux -- class gnu -- class o s {
load video
insmod gzi o
insmod part msdos
i nsmod ext2
set root= ' (hdO ,msdosl) •·
search --n о -П о рру --fs-uui d -- set=root b7300e54 - fff5 - 4f31 - 8002 bea43c64f344
echo ' Загружается Linux 5.2 . 0 -4-amd64 . .. '
linux / boot/vmlinuz-5. 2 . 0-4- a md 64 root=UUID=b7300e54 - fff5 - 4f31-8002 bea43c64f344 r o single initrd=/install/gtk/initrd . gz
echo ' Загружается начальный ramdisk . .. '
initrd /boot/ initrd . img-5. 2 . 0 - 4 -amd64
}
###
КОНЕЦ
/ etc / grub.d / 10 linux ###
###
###
НАЧАЛ О
/etc/ grub . d /20_ linux_xen ###
/ etc / grub.d /20 linux_xen ###
КО НЕЦ
### НАЧАЛ О /etc/grub . d /20 _memtest 86+ ###
# Метка для mem test86 - пр о граммы для пр о верки
menuentry " Memory test (memt es t 86+ ) " {
insmod part_ msdos
insmod ex t 2
set r oo t=' (hdO,msdosl )'
,
_
памяти
--- ------. -----. . --.... .. . . . . . --. -...... -....................................... .
Я1tро
[,inux
......................
rt.iпux
search -- no - floppy -- fs - uuid -- set=root b7300e54 - fff5 - 4f31 - 8002 bea43c64f344
linuxlб
/boot/memtest86+ . Ьin
menuentry " Memory test (memtest86+ , serial console 115200) " {
insmod part_msdos
insmod ext2
set root= ' (hd 0 , msdosl) '
search -- no - floppy -- fs - uuid -- set=root b7300e54 - fff5 - 4f31 - 8002 bea43c64f344
linuxlб /boot/memtest86+ . Ыn console=ttyS0 , 115200n8
menuentry " M~mory test (memtest86+ , experimental multiboot) "
insmod part_msdos
insmod ext2
set root= ' ( hd0 , msdos 1) '
search -- no - floppy --fs - uuid -- set=root b7300e54 - fff5 - 4f31 - 8002 bea43c64f344
multiboot /boot/memtest86 + multiboot . Ыn
menuentry "Memory test (memtest86+ , serial console 115200 , e xpe rime ntal
multiboot) " {
insmod part_msdos
insmod ext2
set root= ' (hd0 , msdosl) '
search -- no-floppy - - fs - uuid -- set=root b7300e54 - fff5 - 4f31 - 8002 bea43c64f344
multiboot /boot/memtest86+ multiboot . Ыn console =ttyS0 , 115200n8
###
#
КОНЕЦ
Далее
ничего
/etc/grub . d/20_memtest86+ ###
этот
файл
я
немного
сократил ,
поскольку
дальше
в
нем
нет
интересного
Файл огромный и его синтаксис напоминает синтаксис Ьаsh-сценариев. Если
вы просмотрели этот конфигурационный файл, то вы уже догадались, что
делает программа
лога
/etc/grub.d
grub-mkconfig:
она собирает воедино все файлы из ката
(кстати, в листинге
4.1
перечислена большая часть из этих
файлов) и вносит в общий конфигурационный файл из
Основная запись из всего лисцшга
4.1 -
это запись
/etc/default/grub.
menuentry. Именно
в та
ких записях описываются элементы меню загрузчика GRUВ.
•
..................... .. .. .......... ................................................ ,
1, 1ава 4. Jai р~
n.1nux ................. .
1•1111, CIHiВ2
menuentry ' Debian GNU/Linux , Linux 5 . 2 . 0-4-amd64 ' --class debian --class gnulinux -- class gnu -- class os {
load video
insmod gzio
insmod part msdos
insmod ext2
set root= ' (hdO , msdosl) '
search -- no - floppy -- fs - uuid -- set=root b7300e54 - fff5 - 4f31 - 8002 bea43c64f344
echo ' Loading Linux 5 . 2 . 0- 4- amd64 .. . '
linux / boot /vmlinuz - 5 . 2 . 0- 4- amd64 root =UUID=b7300e54 - fff5 - 4f31 - 8002 bea43c64f344 ro initrd=/install/gtk/initrd . gz quiet
echo ' Loading initial ramdisk ... '
initrd /boot/initrd . img - 5 . 2 . 0- 4- amd64
В одинарных кавычках после
menuentry
указывается название загрузоч
ной метки . Далее идут параметры, которые вообще можно не указывать и
от этого DeЬian загружаться не перестанет. В фигурных скобках
конфигурация. Директива
load_video,
load_video -
-
основная
это ни что иное , как вызов функции
которая также описана в этом файле конфигурации. Функция
вставляет некоторые модули (команда
insmod),
необходимые для работы
графического режима. Обратите внимание, что команды
не модули ядра
Linux,
а модули
GRUB2,
insmod
загружают
которые находятся в каталоге /Ьооt/
grub.
Внутри
{}
можно использовать команду
echo
для обозначения различных
этапов загрузки, что и сделано в нашем примере. Можете отказаться от
echo,
на загрузку это никак не повлияет.
Основные команды - это linux и initrd. Первая указывает путь к ядру Linux
и задает параметры ядра. В нашем случае параметр ядра
root
указывает
устройство , на котором находится корневая файловая система . Устройство
указано в виде
UUID. UUID-имeнa очень удобны. Представим, что у вас есть
один жесткий диск SATA и два контроллера. Если вы подключите его ко вто
рому контроллеру, обычное имя изменится (например , было /dev/sda, а стало
/dev/sdb ), а UUID-имя - нет. При желании , вы можете указать имя в старом
формате, например, root=/dev/sdal. Параметр ядра ro задает монтирование
корневой файловой системы в режиме "только чтение" (это нормально, поз
же она будет перемонтирована),
параметр ядра
quiet задает
initrd -
задает файл
RarnDisk,
а последний
"тихую" загрузку ядра , при которой будут выво
диться только самые важные сообщения .
•
................................................................................... . .
Я . 1ро
l.inux
initrd
Команда
Теперь
задает
рассмотрим
Листинг
#
#
#
#
______________________ n.inux
4.2.
Файл
файл
Для
файла
получения
к
файлу
initrd .
/etc/default/grub
( листинг
4.2)
/etc/default/grub
После редактирования
обновления
путь
этого
файла
запустите
команду
' update - g r ub '
для
/boot/gruЬ/gru b.cfg.
полной информации
об
этом
файле
введите
команду
info -f grub - n ' Simple configuration '
# Загрузочный элемент (menuentry по умолчанию)
GRUB DEFAULT=0
# Таймаут
GRUB TIMEOUT=5
# Задает название дистрибутива , не изменяйте эту строку
GRUB DISTRIBUTOR='lsb release -i - s 2> /dev/null 11 echo
# Параметры ядра Linux по умолчанию
GRUB_CMDLINE LINUX_DEFAULT= " quiet "
# Еще одна строка для задания параметров я дра
GRUB_CMDLINE LINUX= " initrd=/install/gtk/initrd . gz "
# Раскомментируйте эту строку ,
#GRUB TERМINAL=console
если вы хотите отключить
графический режим
# Разрешение в графическом режиме
# Вы можете использовать только те режимы , которые
# поддерживает через VBE . Просмотреть список
# таких режимов можно с помощью коман ды 'vbeinfo '
#GRUB GFXMODE=640x480
# Раскомментируйте эту строку , если
# использовать UUID - имeнa устройств
#GRUB DISABLE LINUX UUID=true
# Раскомментируйте , если хотите запретить
#GRUB DISABLE RECOVERY= " true "
# Раскомментируйте , если хотите
#GRUB INIT TUNE= " 480 440 1 "
Как видите , параметры из файла
вы
не
DeЬian'
ваша
видеокарта
хотите
генерирование меток восстановления
получить
гудок
при
/etc/default/grub понятны
загрузке
GRU8
и не нуждаются в
особых комментариях . Но в нем мы узнали о еще одной команде
grub . Так
какую из них использовать
- update- update-grub или grub-mkconfig?
•
са - .. -.-.-. ---------.--.. ----.. --.------------- ------.---.. -. -- --------------------.
n.iпux ................. .
J j шва
4. ·1аrрузчик (;RUB2
На самом деле это почти одна и та же команда. Дело в том , что команда grub-
mkconfig
по умолчанию выводит конфигурацию GRUВ2 на экран , поэтому,
чтобы она записалась в файла /Ьoot/gruЬ/grub.cfg, запускать ее нужно так:
sudo grub -m kconfig >
/ bo o t / gruЬ/grub.cfg
Или же вы можете ввести команду
мое. Другими словами, команда
update-grub, которая сделает то же са
update-grub - это сценарий, который вызы
вает только что приведенную команду. Как по мне, то использовать команду
update-grub удобнее.
Так какую стратегию GRUВ2 использовать? Редактировать шаблоны и пара
метры или сразу конфигурационный файл? Если вы работаете за компьюте
ром в гордом одиночестве и нет и не предвидится других администраторов ,
то тогда можете выбрать ту стратегию, которая вам больше нравится.
Если же есть или планируются другие администраторы, то нужно редакти
ровать шаблоны и параметры вместо редактирования конфигурационного
файла вручную. Дело в том , что если вы внесете изменения непосредствен
но в конфигурационный файл, а потом другой администратор захочет из
менить какой-то незначительный параметр, например, добавить гудок при
загрузке GRUВ2 , то команда
update-grub
перезапишет все сделанные вами
изменения .
4.3.
Выбор метки по умолчанию
Как правило, даже если у вас установлена одна только
Linux, у вас будет
несколько загрузочных меток (несколько записей menuentry). Выбрать метку
по умолчанию можно с помощью параметра GRUВ _ DEFAULТ. Нумерация
меток начинается с О, то есть первой метке соответствует значение О.
После того, как вы установите другой номер метки по умолчанию нужно
ввести команду
update-grub
и перезагрузить систему.
Другими словами, последовательность такая: редактируем файл
grub, изменяем
update-grub .
•
значение параметра
GRUB DEFAULT
/etc/default/
и вводим команду
.. . . ----------------- ---- ----------.... -- .... ----.. --.. --... -... --.. ---. -. -.. --...
-
Я , 1р11 lj1нix
4.4.
...................... fl1nux
Загрузка
Windows
Как правило, если имеете дело с
производственное применение
Linux
Linux, то упор делается на серверы и прочее
Linux, однако вдруг вы захотите установить
на домашний компьютер , скорее всего , ей придется "сожительство
вать" с
Windows,
Чтобы добавить возможность загрузки
тировать файл
/etc/grub.d/40_custom
Windows
из
GRUB2,
нужно отредак
и добавить в него следующие строки:
menuentry " Windows (оп / dev / sdal) "
insmod part_ msdos
insmod ntfs
set root= ' (hdO,msdosl)'
search -- no - floppy -- fs - uuid -- set UUID
drivemap - s (hd O) $ {r o ot }
chainloader +1
Здесь
Windows находится на /dev/sdal и адрес этого раздела указывается в
set root. Значение UUID нужно заменить на UUID вашего Windows-paздeлa.
О том, как "вычислить" UUID раздела, мы поговорим, возможно, в другой
главе. Остальные параметры можете оставить без изменения (еще не забудь
те исправить hdO в drivemap, если Windows установлена не на первом жест
ком диске).
4.5. Пароль загрузчика GRUB2
Загрузчик GRUВ позволял только установить пароль
загрузку определенной метки. Загрузчик
GRUB2
-
или общий, или на
более гибкий в это~ плане,
поскольку вы можете настроить не только пароли, но и логины. Также есть
минимальная система разграничения прав доступа.
Итак, в
GRUB2
есть суперпользователь, который может редактировать
загрузочные метки. Существует возможность восстановить пароль
тем передачи ядру параметра
фигурацию
GRUB2.
init. Но
root
пу
для этого нужно отредактировать кон
Если вы установите пароль суперпользователя, то изме
нить конфигурацию загрузчика вы сможете только после ввода этого пароля .
-
•
----- ....... ····- . ................ ··-·. ---· ..... ·-· ... . ....... · ·-- ------- ·--· ----· .
t\.inux ................. .
Также в
GRUB2
есть обычные пользователи, которые имеют право только
выбир8;ТЬ загрузочную метку. Они не имеют права редактировать конфигу
рацию загрузчика. В принципе, можно обойтись одним паролем суперполь
зователя, но при желании
может довольно гибко разграничить права
GRUB2
пользователей.
Давайте сначала добавим пароль суперпользователя. Для этого в файл
grub.d/00_header добавьте
/etc/
строки:
set s uperuser s =" main_ admin "
p as swo r d ma ih admin 123456789
Первая команда задает суперпользователя
main_admin, а вторая - задает для
admin, root и
него пароль . Старайтесь избегать общепринятых имен вроде
т.д. Так у злоумышленника, который хочет изменить конфигурацию GRUВ2
будет больше неизвестных данных.
Пароль пока в незашифрованном виде и это не очень хорошо. Поскольку
если загрузиться с
LiveCD
или
LiveUSB,
то его можно будет увидеть. Позже
я покажу, как зашифровать пароль.
Обычные пользователи задаются инструкцией
password,
например:
passwo r d me 12345
По сути
main _ admin - тоже был бы обычным пользователем , если
set superusers, которая делает его суперпольз овател ем.
бы не
инструкция
Представим, что у нас есть следующие строки:
set superusers= " main_admin "
p assword main_adm i n 123456789
p assword me 12345
Пользователь
main_admin может загружать операционные
конфигурацию GRUB2. Пользователь те может
системы и редак
тировать
только загружать
операционные системы.
-
Если вы хотите, чтобы определенные метки могли загружать только опреде
,.
л енные пользователи, добавьте к
menuentry параметр --users:
-
.... -- . --... - ... -.... --.. --... -.. -. -------.. ---. - . -- ---. - ----- . -- ....... -......
Я . 1ро
Linux
.. ____________ .. _.. _.. n..inux
menuentry " Windows " -- users me {
insmod part msdos
insmod ntfs
set root= ' (hdO , msdosl) '
search -- no - floppy - -fs - uuid -- set UUID
drivemap - s (hdO) ${root}
chainloader +1
Теперь зашифруем пароль . Введите команду:
grub-mkpasswd- pbkdf2
Программа запросит пароль , зашифрует его и выведет на экран его кэш. Вы
увидите что-то подобное:
grub . pbkdf2 . sha512 . 10000 . 9290F727ED06C38BA 4549 EF7DE25C F5 6 42659
211B7FC076F2D27080136.887CFF169EA83D5235D80047 42AA7D6187 A41E 3 1
87DFOCE14E256085ED97A979080136 . 887CFF169EA8335235D8 0 04 242AA706
187A41E3187DFOCE14E256D85ED97A97357AAA8 FF OA387 1AB9EEFF458392 F4
62F495487387F685B7472FC6C29E293FOAO
Данный хэш нужно указать вместо пароля пользователя. Однако вместо ин
струкции
passwd нужно
использовать password_pbkdf2. Например:
password_pbkdf2 me grub . pbkdf2.sha512 . 1000 0. 9290 F727 ED0 6C38 BA4
549EF7DE25CF5642659211B7FC076F2D27080 1 36 . 887CFF1 69 EA83D523 5D8 0
04742AA706187A41E3187DFOCE14E256D85ED97A979080 1 36 . 887CF F169EA8
335235D8004242AA7D6187A41E3187DFOCE14 E256D85 ED97A9735 7AAA8 FF OA
3871AB9EEFF45839ZF462F495487387 F685B7472FC6C29 E293 FOAO
После изменения файлов из каталога
upgrade-grub для
/etc/grub.d
не забудьте ввести команду
обновления основного файла конфигурации.
•
- - - ---------------·---------------------·-------------- ----- -- --- -------------------·
1; 1а11а 4.
t\.1nux ................. .
4.6.
Ja1 ру 1•11ш (; IHIН2
Установка загрузчика
Команда установки загрузчика такая же, как и в случае с GRUВ:
# / sbin / grub-install
<устройство>
Например:
# / sbin / grub - install / dev / sda
Поскольку
GRUB2
у вас уже установлен, вряд ли вам придется вводить эту
команду. Исключение может составить разве что переустановка всей систе
мы, которая перезапишет загрузочный сектор своим загрузчиком. Поэтому
вам придется загрузиться с
LiveCD,
выполнить
корневой системы и ввести команду
grub-insta/1
для вашей старой
chroot
для установки загрузчика
GRUB2.
4. 7.
Система инициализации
После своей загрузки ядро передает управление систе.ме инициализации.
Цель этой системы
-
выполнить дальнейшую инициализацию системы. Са
мая главная задача системы инициализации
-
запуск и управление систем
ными службами.
Служба (сервис, де.мон)
специальная программа, выполняющаяся в фоно
-
вом режиме и предоставляющая определенные услуги (или, как говорят, сер
вис
-
отсюда и второе название) .
Что превращает обычный компьютер, скажем, в FТР-сервер? Правильно , за
пущенная служба
FTP - тот же ProFTPD или подобная. Вы можете устано
ProFTPD и настроить ее на автоматический запуск системой
вить программу
инициализации. Тогда при каждой загрузке наш компьютер будет превра
щаться в FТР-сервер. Аналогично и с другими сервисами -достаточно уста
новить определенную программу, чтобы превратить компьютер в веб-сервер
или почтовый сервер. Но стоит вам отключить ее и компьютер уже прекра-
•
. . ........ ..
-
-
-
-
-
-
-
-
.
-
....
-
-
-
-
-
-
-
-
.
-
-
-
.
-
-
-
-
. ... .. ·- .. .....
-
-
-
-
-
-
-
-
-
-
-
-
-·
-
-
-
-
-
-
.
-
-
...
...................... t't.1пux
И IJIO l,i1111\
щает предоставлять обеспечиваемые программой услуги, следовательно,
превращается в самый обычный компьютер.
В мире
Linux существовало очень много разных систем инициализации init, upstart, init-ng. Все их рассматривать уже нет смысла, поскольку в совре
менных дистрибутивах используется современная система инициализации
systemd.
systemd -
подсистема инициализации и управления службами в
фактически вытеснившая в 2010-е годы традиционную
Основная ос?бенность
Linux,
подсистему init.
интенсивное распараллеливание запуска служб
-
в процессе загрузки системы, что позволяет существенно ускорить запуск
операционной системы. Основная единица управления
типов модулей являются "службы"
запускаемые
и
управляемые
-
аналог демонов
средствами
модуль, одним из
-
-
наборы процессов,
подсистемы
и
изолируемые
контрольными группами.
4.7.1.
Система инициализации
Принцип работы
systemd используется во многих современных дис
Fedora, UЬuntu, CentOS и openSUSE. На данный
трибутивах, в частности в
момент
-
это самая быстрая система инициализации.
Давайте подумаем, как можно ускорить запуск
upstart -параллельно запускать службы.
Linux?
Можно пойти по пути
Но параллельный запуск
-
хорошо. Нужно учитывать зависимости служб. Например, сервис
жен многим другим сервисам. Пока сервис
d-bus
не всегда
d-bus
ну
не будет запущен, нельзя
запускать сервисы, которые от него зависят.
Если сначала запускать основные сервисы и ждать, пока они будут запуще
ны, а потом уже запускать службы, которые от них зависимы, особого
выигрыша в производительности по сравнению с
сервис
d-bus
init вы не увидите.
Но если
(или любой другой, от которого зависят какие-то другие серви
сы) запускается долго, то все остальные службы будут ждать его.
Как обойти это ограничение? При своем запуске службы проверяют, запу
щена ли необходимая им служба, по наличию файла сокета. Например, в
случае с
d-bus -это
файл
/var/run/dbus/system_bus_sock~t.
Если мы создадим
со. кеты для всех служб, то мы можем запускать их параллельно, особо не
-
беспокоясь, что произойдет сбой какой-то службы при запуске из-за отсут
ствия службы, от которой они зависят. Даже если несколько служб; которым
---------- ---- ----.. --- ----. --... --.. ---.. -------.. -... -.. --- -. ---. -. -.. -- -. ---_,
l .1 1.ша 4.
n..inux ................. .
нужен сервис
d-bus, запустятся раньше·,
чем сам сервис
J:11 f))' 1•11ш (;IHIВ2
d-bus:
ничего страш
ного. Каждая из этих служб отправит в сокет (главное, что он уже открыт!)
сообщение, которое обработает сервис
d-bus
после того, как он запустится.
Вот и все.
Но это не единственное "ухищрение", посредством которого осуществля
ется ускорение запуска компьютера, инициализацию которого производит
systemd.
Эта система инициализации запускает только необходимые серви
сы. Остальные же будут запущены по мере необходимости. Концепция от
OS Х (там система инициализации называется launchd) и в
Windows (концепция отложенного запуска служб). Так что решение не очень
ложенного запуска используется и в других операционных системах
например, в Мае
новое, но зато проверенное.
Основными функциями
•
systemd
являются:
Активация на основании сокетов
-
система инициализации
systemd
прослушивает сокеты всех системных служб. Сокеты передаются
системным службам сразу после запуска сервцсов. Благодаря этому осу
ществляется параллельный запуск сервисов. Также это позволяет переза
пускать сервисы без потери любых отправленных им сообщений , то есть
пока сервис перезапускается, отправленные ему сообщения накаплива
ются, и он сможет их обработать после того, как будет запущен .
•
Активация на основании устройств
- systemd может запустить
опреде
ленные службы, когда станет доступным определенный тип оборудова
ния . Например, вы подключили Bluetooth-aдaптep, может быть запущен
сервис Ыuetooth.
•
Активация на основании
d-bus -
служба инициализации может за
пустить сервисы , которые используют
d~bus для межпроцессного взаимо
действия, например, когда клиентское приложение попытается связаться
с системной службой .
•
Активация на основании путей
- systemd может запустить службу, если
изменится содержание каталога.
•
Управление точками монтирования и автоматическим монтирова
нием -система инициализации отслеживает и управляет точками монти
рования и автоматического монтирования.
•
Снимки системных состояний
-
благодаря этой возможности
systemd
-
может сохранить состояние всех модулей и восстановить предыдущее
состояние системы.
-
-· ... ---.. --.... ---... -........ -... --... -.. -... ---... -.. -. -. -. . --. -. ---. --. . -...
Ищю
•
l ,i1111x
..................... . ,n .lnux
Параллелизация
- systemd
запускает системные службы параллельно
благодаря активации на основании сокетов. Параллельная активация су
щественно сокращает время загрузки системы.
•
Обратная совместимость с
лизации
SysV,
SysV -
поддерживаются сценарии · инициа
что упрощает переход на
systemd.
Однако все устанавли
ваемые в современных дистрибутивах пакеты служб уже адаптированы
под
systemd,
поэтому не нужно надеяться, что во время установки пакета
какого-то сервиса будут установлены SуsV-сценарии. Будут созданы фай
лы, необходимые для запуска сервиса посредством
systemd.
4. 7.2. Конфигурационные файлы systemd
Обилие различных конфигурационных файлов
systemd
может ввести в сту
пор даже бывалого линуксоида, не говоря уже о пользователе, который впер
вые видит
systemd.
Когда я впервые познакомился с
то)Iько одно желание
-
снести ее и установить
systemd, у меня
вместо нее init. Но мы
было
этого
не будем делать. Чтобы разобраться со всеми файлами, нужно понимать, как
работает эта система.
В
systemd
используется концепция модулей (юнитов). Существующие типы
модулей описаны в таблице
Таблица
4.1.
4.1.
Типы модулей системы инициализации
Тип
systemd
Описание
Служба (сервис, демон), которую нужно запустить. Пример
имени модуля :
network.service. Изначально systemd поддерSysV (чтобы управлять сервисами можно
было, как при использовании init), но в последнее время
в каталоге /etc/init.d систем, которые используют systemd
живала сценарии
service
практически пусто (или вообще пусто), а управление сервисами осуществляется только посредством
--
systemd
•
---.---... --.. --... -.. -- -.. ---. -- -.. ---- . -... --.. ---- . --... -... --- .. -... -.... -.. --,
ft1nux ... ........... ·... .
Цель. Используется для группировки модулей других типов. В
target
systemd нет уровней
запуска, вместо них исполь-
зуются цели. Например, цель
multi-user.target описывает,
какие модули должны быть запущены в многопользовательском режиме
Снимок. Используется для сохранения состояния
snapshot
systemd.
Снимки могут использоваться для перевода системы из одного состояния в другое, например, в состояние сна и про-
буждение
Точка монтирования. Представляет точку монтирования.
Система инициализации
mount
systemd
контролирует все точки
монтирования. При использовании
systemd
файл
/etc/fstab
уже не главный, хотя все еще может использоваться для
определения точек монтирования
Автоматическая точка монтирования. Используется для
automount
монтирования сменных носителей
-
флешек, внешних
жестких дисков, оптических дисков и т.д.
Сокет. Представляет сокет, находящийся в файловой системе или в Интернете. Поддерживаются сокеты
socket
AF_ INET6, AF_ UNIX.
AF _INET,
Реализация довольно интересная.
Например, если сервису
кет
service l .service соответствует соservice l .socket, то при попытке установки соединения с
service l .socket будет запущен service l .service
Устройство . Представляет устройство в дереве устройств .
device
Работает вместе с
правила
udev,
udev:
если устройство описано в виде
то его можно представить в
модуля
•
systemd в
виде
device
path
Файл или каталог, созданный где-то в файловой системе
scope
Процесс, который создан извне
··-····· ··· ·· ··· ···· ·-····················· ······································· -
И IIНI
__ .................... n..iпux
l , i,111 \
Управляет системными процессами , Представляет собой
slice
группу иерархически организованных модулей
Представляет область подкачки (раздел подкачки) или файл
swap
подкачки (свопа)
Представляет собой таймер системы инициализации
timer
systemd
Модули хранятся в следующих каталогах:
• /etc/systemd/system/ -
обладает самым высоким приоритетом . Здесь со
держатся модули, которые созданы и управляются системным адми ни
стратором .
• /run/systemd/system/ -
модули, созданные во время выполнения. Приори
тет этого каталога ниже , чем каталога
/etc/systemd/system/, но
выше , чем
у /usr/liЬ/systemd/system .
•
/usr/liЬ/systemd/system/
-
модули , которые установлены из пакетов .
Типичный файл модуля типа
Листинг
4.3.
service приведен
в листинге
Типичный файл модуля типа
4.3 .
service
[Unit]
Description=Daemon to detect crashing apps
After =syslog . target
[Service]
ExecStart= / usr / sbin / ab r td
Type=f o rking
[Install]
WantedBy=mul t i - user . target
В секции
Unit содержится
общая информация о сервисе . Эта с екция есть и в
других модулях , а не только в сервисах .
•
. ...................................... .......... - ... --- - ---· .............. ······ . . .
n.1nux ................. .
Секция
Service
содержит информацию о сервисе. Параметр
ExecStart
опи
сывает команду, которую нужно запустить. Параметр Туре указывает, как
сервис будет уведомлять
Секция
Install
об окончании запуска.
systemd
содержит информацию о цели, в которой должен запускать
ся сервис . В нашем случае видно , что сервис будет запущен при активации
цели
multi-user.target.
Вы можете использовать эту "болванку" для написания собственного серви
са, который потом нужно поместить в файл /etc/systemd/system/имя _ cepвиca.
service.
После этого нужно перезапустить саму
новом сервисе:
systemd,
чтобы она узнала о
.
# systemctl daemon - reload
Цели
4.7.3.
Теперь поговорим о целях . Файлы целей
пировки вместе других юнитов
модуль цели
systemd
graphical.target, который
*.target
предназначены для груп
через цепочку зависимостей. Так,
используется для запуска графическо
го сеанса , запускает системные службы
GDM (файл gdm.service) и Accounts
Service (accounts-daemon.service), а также активирует цель multi-user.target.
В свою очередь, цель multi- user.target запускает другие системные службы,
например , D-Bus (dbus.service) и активирует другие цели вроде basic.target.
В
systemd имеются предопределенные
цели , которые напоминают стандарт
ный набор уровней запуска.
Некоторые цели называются
ших пользователей
runlevelN.target,
init на systemd, а именно:
• poweroff.target (runlevelO .target) -
чтобы упростить переход быв
завершение работы и отключение
системы;
• rescue.target (runlevell.target) -
однопользовательский режим, среда вос
становления;
• multi- user.target'(runlevel2.target, runlevelЗ.target, runlevel4.target) -
много
пользовательский режим, без графического интерфейса;
•
············································································ ······ -
И , 1р11
l .illll\
...................... rtinux
• graphical.target (runlevel5.target)- многопользовательский режим с графи
ческим интерфейсом;
• reboot.target
(runlevelб.target)
-
завершение работы и перезагрузка
системы.
Управление службами осуществляется с помощью программы
systemctl.
Подробнее о службах мы, возможно, поговорим в другой главе, а пока раз
беремся, как использовать
• systemctl halt -
systemctl для
завершения работы системы:
останавливает систему;
• systemctl poweroff • systemctl reboot -
выключает систему;
перезагружает систему.
Многим пользователям будет удобнее использовать старые команды
poweroff и reboot.
ha/t,
Но все же теперь вы знаете, qто есть альтернативные спо
собы завершения работы.
4.8. Управление
systemd
сервисами при использовании
При использовании системы инициализации
systemd управление службами
systemctl. Команда systemctl ис
в таблице 4.2 представлены не все ее
осуществляется посредством программы
пользуется для разных целей, поэтому
параметры, а только те, которые имеют отношение к сервисам.
Таблица
4.2.
Параметры программы
systemctl
Параметр
Описание
start <имя.service>
Запускает сервис
stop <имя.service>
Останавливает сервис
•
............................................ ................ ..................... ...
•
I J 1aнa
n..inux _________________ _
-+. Загр~иш, CRtlB2
restart <имя.service>
Перезапускает сервис
try-restart <имя.service>
Перезапуск сервиса только, если он запущен
reload <имя.service>
Перезагружает конфигурацию сервиса
status <имя.service>
Отображает подробное состояние сервиса
is-active
Отображает только строку
<имя.service>
пущен) или
list-units --type service
--all
active (сервис
inactive (остановлен)
за-
Выводит состояние всех сервисов
Включает сервис (обеспечивает его автомати-
еnаЫе <имя.service>
ческий запуск)
Отключает сервис (сервис не будет автомати-
disaЫe <имя.service>
чески запускаться при запуске системы)
reenaЫe <имя.service>
list-unit-files --type service
Деактивирует сервис и сразу его использует
Выводит список всех сервисов и сообщает,
какие из них активированы, а какие
-
нет
Примеры:
# systemctl start httpd.service
# systemctl stop httpd
Первая команда запускает сервис
Обратите внимание, что
Бывалые пользователи
".service"
Linux
httpd (веб-сервер),
вторая
-
останавливает.
можно не указывать.
сразу заметят удобства. Ран-ее, чтобы отклю
чить службу на определенном уровне запуска, нужно было удалить ее сим
волическую ссылку из определенного каталога. Аналогично, чтобы служба
запускалась на определенном уровне запуска (например , в графическом ре
жиме), нужно было создать символическую ссылку. Сейчас всего этого нет,
а есть только команды епаЫе и disaЬle, что стало гораздо удобнее .
•
.------ ---------------------- ---------------- ------------- ------------------------ -
Глава
5.
Как ядро управляет
процессами
Я , 1ро l,i1шx
5.1.
......................
n..iпux
Что такое процесс
Процесс-это код (программа), находящийся в состоянии выполнения.
Также процесс
-
это не только исполняемый программный код, а еще и на
бор ресурсов (открытые файлы и сигналы, ожидающие обработки, внутрен
ние данные ядра, один или несколько потоков выполнения
tion)),
а также сегмент данных программы
(data section),
(threads of execu-
который содержит
глобальные переменные.
Потоки
(threads),
выполнения
кода,
которые
часто
называют
просто
потоками
представляют собой объекты, выполняющие определенные дей
ствия внутри процесса. В каждом из потоков содержатся уникальный счет
чик команд
(program counter),
стек пjюцесса и набор регистров процессора.
Планировщик ядра на самом деле управляет выполнением отдельных
потоков, а не процессов. В традиционных Uniх-подобных операционных
системах каждый процесс содержал только· один поток. Но в современных
системах многопоточные программ1~r (т.е. программы, в которых запускается
более одного потока выполнения команд) используются довольно часто.
-
•
. . . .. -.... --.. ---.. --·. ---. ---.. ---. ---. ·- -.. - -.. --.. -. -. ---.. --.. ---. ·- -· .. -... --..
•
! ~ шва
n..inux .................. .
5. Как
я . 1ро ~прав.1яс1 11ронсссаш1
Процессы в современных ОС предусматривают наличие двух виртуальных
ресурсов: виртуалыюго процессора
Благодаря
VCPU
(VCPU) и виртуальной памяти (VRAM).
для процесса создается иллюзия, что они монопольно ис
пользуют весь компьютер, не смотря на то, что физический процессор могут
использовать сотни других процессов .
VRAM позволяет процессу распреде
лять оперативную память компьютера и управлять ею так, как будто он один
владеет всей памятью в системе.
Сама по себе программа процессом не является. Процесс - это выполняюща
яся программа и набор ресурсов . Может существовать несколько процессов,
выполняющи:х одну и ту же программу. Также несколько процессов могут
совместно использовать одни и те же ресурсы, такие как открытые файлы
или адресное пространство . Процесс начинает существовать с момента соз
дания. В операционной системе
с системного вызова
fork() ,
Linux
существование процесса начинается
который создает новый процесс путем полного
копирования уже существующего . Процесс, вызвавший
fork(),
называется
порождающим , или родит ел ьским
(parent),
рожденным, или дочерним
Родительский процесс после этого про
(child).
а новый процесс именуют по
должает свое выполнение , а дочерний начинает выполняться с одного и того
же места
-
с момента возврата из системной функции
возврат из системной функции
fork()
fork().
В результате
выполняется из ядра дважды: один раз
в родительском процессе, а второй раз
-
в порожденном .
Если в одном из процессов нужно выполнить другую программу (не поро
дить новый процесс этой программы, а именно вызвать другую программу),
то нужно использовать функцию ехес(), которая создает новое адресное про
странство и загружает в него новую программу. В современных ядрах
функция
fork()
Linux
на самом деле реализована через вызов системной функции
clone().
Выход из процесса осуществляется с помощью функции
exit(),
которая за
вершает выполнение процесса и освобождает все занятые им ресурсы. Роди
тельский процесс может выдать запрос о состоянии завершенных дочерних
процессов с помощью вызова системной функции
одному
процессу
подождать
завершения
wait4(),
другого
которая позволяет
указанного
процесса.
После завершения процесса он переводится в специальное состояние зомби
(zombie),
которое используется для представления завершенного процесса
до того момента, пока порождающий его процесс не вызовет системную
функцию
•
wait()
или
waitpid() .
... . . . . . . . . . . . . . . . . .. . . . . . . . . ... . . . . . . . . . . . .. . . . . . . . . . . . .. . .. . . . . .. . . ... . . . . . . . . . .
-
Я , 1ро
5.2.
l.i1111x
...................... n..inux
Структуры , связанные с процессами
5.2.1.
Список задач и структура процесса
Список процессов хранится в ядре как двусвязный циклический список, ко
торый называется списком задач. Каждый элемент этого списка описывает
один запущенный процесс и называется дескриптором процесса , Дескрип
тор процесса имеет тип
<linux/sched,h>,
task_struct,
а сама структура определена в файле
Структура довольно объемна и полное описание ее полей
можно найти по адресу :
https ://docs, huihoo,com/doxygen/linuxlkernel/3, 7/s tructtask_ s truct. html
Посмотрите на рис ,
задач
(task list),
5, 1,
На нем показано, что представляет собой список
Это двусвязный циклический список, элементами которого
являются структуры типа
task_struct.
atruct tuk..atruct
atruct tt1•k..•truct
unsign.ed long state;
lnt pdo;
UAsigned long ро11су;
struct tasl(_s1n.Юt •parent:
struct llst_head tasks;
process descriptor pkl...J pid;
г
the task 11st
Р41с.
5.1.
Список задач
Каждый процесс динамически размещает структуру
struct task_struct.
Linux,
симальное количество процессов, которое может быть создано в
ничивается только объемом физической памяти и равно:
Мак
огра
•
- - - ....................................... ·-··· ----- ·- ---- ... ·-·- ·- -- .. -. --··· .... .
l . 1,1н,1:, Kai-: s1.1p11 ~щ1ав. 1wt>1 111ю11ссса\111
ainux -------------------
max threads
mempages /
что для архитектуры
Например , на машине
(THREAD_SIZE/PAGE SIZE) / 2;
IA32 означает, как правило, num_physpages/4.
с 2GB памяти, возможно создать 128k потоков. Кро
ме того, этот предел может быть изменен в процессе исполнения, передачей
значения КERN_МАХ_THREADS в вызове
procfs:
sysctl(2),
•
или через интерфейс
# cat / proc / sys/kernel/threads - max 32764
# echo 100000 > /proc/sy s /kernel / threads-max
# cat /proc/sys/ke rnel /thread s-max 100000
# gdb -q vmlinux /proc/kcore
Core was generated Ьу ·воот_IМАGЕ=240 ас18 r o root=306
video=matrox : vesa : 0xllB '.
#О О хО in ?? ()
(gdb) р max_threads $1 = 100000
Множество процессов в Linux-cиcтeмe представляет собой совокупность
структур struct task_struct, которые взаимосвязаны двумя способами :
•
1.
Как хеш-массив, хешированный по
2.
Как кольцевой двусвязный список, в котором элементы ссылаются друг
pid
на друга посредством указателей р-> next_task и р->prev_task.
Хеш-массив определен в
include/linux/sched.h
как
pidhash:
#define PIDHASH_SZ (4096 >> 2) extern struct task_struct
*pidhash[PIDHASH_SZ] ;
#define pid_hashfn (х) ( ( ( (х) » 8) л (х)) & (PIDHASH_SZ - 1))
Задачи хешируются по значению
pid,
вышеприведенной хеш-функцией,
которая равномерно распределяет элементы по диапазону от О до
1. Хеш-массив
PID_ MAX-
используется для быстрого поиска задачи по заданному
с помощью inlinе-функции
find _task_Ьу_pid(),
определенной в
include/linux/
sched.h:
•
pid
.-. --. ----------------------. ----------------------- ----------------· ----------- ---
Я . 1ро l,i1111x
...................... n..inux
static inline struct task_struct *find_task_by_pid(int pid) {
struct task_struct *р , **htaЫe = &pidha sh [pid_hashfn(pi d)] ;
f o r(p = *htaЫe ; р && p - >pid != pid; р = p - >pidha sh_nex t);
return р ;
Задачи в каждом хеш-списке (т.е . хешированные с тем же самым значением)
связаны указателями
p->pidhash_ next/pidhash_pprev, которые используются
hash_pid() и unhash_pid() для добавления/удаления заданного
в/из хеш-массив . Делается это под блокировкой (spinlock) tasklist_
функциями
процесса
lock,
полученной на запись.
Двусвязный список задач организован таким образом, чтобы упростить на
вигацию по нему, используя указатели
p->next_task/prev_ task. Для прохож
for_each_task() из
дения всего списка задач, в системе предусмотрен макрос
include/linux/sched.h:
#define for _ each task(p)
!= &init task ; )
\ for
(р
&init task
(р
p->next_task)
Перед использованием
for_each_task() необходимо получить блокировку
tasklist_lock на чтение. Примечательно, что for_each_task() использует init_
task в качестве маркера начала (и конца) списка- благодаря тому, что задача
с pid=O всегда присутствует в системе. Функции, изменяющие хеш-массив
и/или таблицу связей процессов, особенно fork(), exit() и ptrace(), должны
получить блокировку (spinlock) tasklist_lock на ЗАПИСЬ. Что особенно ин
тересно - перед записью необходимо запрещать прерывания на локальном
процессоре, по той причине, что функция send_ sigio(), при прохождении
по списку задач, захватывает tasklist_lock на ЧТЕНИЕ, и вызывается она из
kill_fasync() в контексте прерывания . Однако если требуется доступ только
для чтения , запрещать прерывания нет необходимости. Теперь, когда доста
точно понятно представлено как связаны между собой структуры
можно перейти к рассмотрению полей
В других версиях
UNIX
task_struct,
task_ struct.
информация о состоянии задачи разделяется на две
части:
•
В одну часть выделяется информация о состоянии задачи (называется
...
'proc structure', которая включает в себя состояние процесса, информацию
планировщика и пр.) и постоянно размеща·ется в памяти;
•
.. . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . .. . . . . . . . . . . . . . .. . . . . . . . .. . . .. . . . . . . . . . . . . .. . . ..
.
) 1 1ава 5. Ка1, s1 tpo ~••р:111. 1щ•1 Щ)1щсt·са~111
t'.l1nux .................. .
•
Другая часть, необходима только во время работы процесса
('u area',
кото
рая включает в себя таблицу дескрипторов, дисковые квоты и пр.).
Единственная причина такого подхода - дефицит памяти. Современные опе
рационные системы (не только
Linux,
но и другие, современная
FreeBSD
например) не нуждаются в таком разделении и поэтому вся информация о
состоянии процесса постоянно хранится в памяти.
5.2.2.
Поле
Состояния процесса
state структуры task_struct
объявлено как:
volatile long state ; /* -1 unrunnaЫe ,
#define TASK RUNNING О
#define TASK INTERRUPTIBLE 1
#define TASK UNINTERRUPTIBLE 2
#define TASK ZOMВIE 4
#define TASK STOPPED 8
#define TASK EXCLUSIVE 32
Спецификатор
volatile
в объявлении
О
p->state
runnaЫe,
>О
stopped */
означает, что это поле может
изменяться асинхронно (в обработчиках прерываний):
• TASK_RUNNING -
указывает на то, что задача "вероятно" находится в
очереди запущенных задач
(runqueue). Причина, по которой задача мо
TASK_RUNNING, но не помещена в runqueue в
том, что пометить задачу и вставить в очередь - не одно и то же. Если
заполучить блокировку runqueue_lock на чтение-запись и просмотреть
runqueue, то можно увидеть , что все задачи в очереди имеют состояние
TASK_RUNNING. Таким образом , утверждение "Все задачи в runqueue
имеют состояние TASK_RUNNING" не означает истинность обратного
жет быть помечена как
утверждения . Аналогично, драйверы могут отмечать себя (или контекст
процесса, под которым они запущены) как TASK_INTERRUPТIBLE (или
TASK_UNINTERRUPТIBLE) и затем производить вызов
торый удалит их из
•
процесс остается в
runqueue (исключая
runqueue) .
schedule(),
ко
случай ожидания сигнала, тогда
.. . . . . . -............ --. ---.. ---... -... -- ... -.. ---. -. -. --......... -... -.. -- -... -... . .
Я . 1ро
l ,inux
..... _____ ............ n.inux
• TASK_ INTERRUPTIBLE -
задача в состоянии "сна", но может быть "раз
бужена" по сигналу или по истечении таймера.
• TASK_UNINTERRUPТIBLE -
подобно
TASK_ INTERRUPТIBLE,
только
задача не может быть "разбужена".
• TASK_ZOMBIE -
задача, завершившая работу, до того как родительский
процесс ("естественный" или "приемный") произвел системный вызов
wait(2) .
• TASK_ STOPPED -
задача остановлена, либо по управляющему сигналу,
либо в резул_ьтате вызова
• TASK EXCLUSIVE зуется
только
ptrace(2).
не имеет самостоятельного значения и исполь
совместно
UNINTERRUPТIBLE (по
с
TASK_ INTERRUPТIBLE или с TASK_
OR). При наличии этого флага, будет "раз
бужена" лишь эта задача, избегая тем самым порождения проблемы
"гремящего стада" при "пробуждении" всех "спящих" задач. Флаги за
дачи представляют не взаимоисключающую информацию о сост0янии
процесса:
unsigned long flags; /*
/**
флаги
процесса ,
определены ниже* /
Флаги процесса*/
#define PF ALIGNWARN OxOOOOOOO l /* Print alignment warning msgs * /
/* Not implemented yet , only for 486* /
#define PF_STARTING Ох00000002 / *создание* /
#define PF_EXITING Ох00000004 / *завершение* /
#define PF_FORKNOEXEC О х 00000040 / * создан , но не запущен* /
#define PF_SUPERPRIV Ох00000100 / * использует привилегии суперп ользователя* /
#define PF DUMPCORE Ох00000200 / * выполнен дамп памяти* /
#define PF SIGNALED Ох00000400 / * " убит " по сигналу* /
#define PF MEМALLOC ОхОООООВОО / * Распределение памяти* /
#define PF VFORK Ох00001000 / * " Разбудить " родителя в mm_release */
#define PF USEDFPU Ох00100000 / * задача использует FPU this quantum (SМР) */
Переход процесса из одного состояние в другое показан на рис.
5.2.
В коде ядра часто необходимо изменять состояние процесса. Предпочти
тельнее всего для этой цели использовать функцию:
set_task_state (task, state) ; / *
Перевести задачу
' task '
в состояние
' state ' */
. . . . - - - - - - - - - - - - - - - - - - - - - - - - - - - - - • - - - • - - - - • - - - • - - - - - - - - - - 1.. - - - - - - - - - • - - - - • - - - - - - - - _ ,
.
n.inux _. __ . __________ . _..
которая устанавливает указанное состояние для указанной задачи . По мере
необходимости эта функция также предоставляет барьер памяти
barrier),
(memory
чтобы гарантированно изменить состояние задачи на других про
цессорах. В остальных случаях это эквивалентно выражению:
ta sk - >state
state ;
~
~
sc/leduler Ф ~c hes tвsk to run:
schedule( ) ~ !ls conte><t_sw!tch( )
~ -"'"-''"
Рис.
5.2.
Состояния процесса
Существует и другая функция,
set_current_state(state), вызов которой эющ
set_task_state(current, state). Данная функция и другие, связанные с
описаны в файле <linux/sched.h>.
валентен
ней ,
5.2.3. Дескриптор
Структура
task_struct
процесса
выделяется с помощью распределителя
slab
для обе
спечения повторного использования объектов и "раскрашивания" кэша. В
•
.-. - ------ ------------ ----- - -- ------------. ----------------------. ~ --. -- -. --- ------ -•
Я , tlJII
l , illll\
...................... n.1nux
ранних версиях ядра
Linux (до
версии
2.6) структура task_struct хранилась в
конце стека ядра каждого процесса. Это позволяло архитектурам с неболь
шим количеством регистров, таким как х86, вычислять местоположение
дескриптора процесса с помощью указателя стека без использования допол
нительного регистра для хранения местоположения.
В современных версиях, когда дескриптор процесса динамически создает
ся с помощью распределителя плит, была создана новая структура,
thread_info.
struct
Данная структура снова находится в нижней части стека (для
стеков, которые растут вниз) и наверху стека (для стеков, которые растут
вверх). Новая структура также упрощает вычисление смещения его значе
ний для использования в ассемблере.
Procesa
КerneJ
Stack
. . - - - - - - - - - - - . - hlgtlest memory address
Start of Stac;k
1 - - - - - - - + - - - - - - f • .s tacl(
polnter
struct thread_struct
current" t hread_info {} •- - - - - - - - - - - • lowest memory adl;Jre$&
thread_i nfo hat а pointerlothe pl'II08$S descrlptor
the proce11'$ struct task_struct
Рис.
Структура
thread_info
5.3. Дескриптор процесса
определена в
struct thread inf o {
и стек ядра
<asm/thread_info.h> и имеет вид :
•
. . ..--............... -.......... --- ... -·. ----. . . ....... .. .. .. . ..... -. -· .. ........ ... .
n..1nux . ................. .
struct task struct
struct ехес domain
unsigned long
unsigned long
u32
s32
mm_segment_t
struct restart Ыосk
unsigned long
u8
*task;
*exec_domain;
flags;
status;
cpu;
preempt count;
addr_limit;
restart_Ыock;
prev ious_esp;
supervisor_stack(OJ;
};
Структура
thread_info
размещается в конце системного стека, выделенного
для каждой задачи. В ней есть элемент
структуру дескриптора задачи
task,
task_struct.
который указывает на реальную
Система идентифицирует процессы по значению уникального идентифика
тора процесса
(process identification, PID).
Идентификатор
число, представленное с помощью скрытого типа
pid_t,
PID -
это целое
который обычно
соответствует целому типу со знаком
int. Однако для обратной совмести
мости со старыми версиями ОС Unix и Linux максимальное значение этого
параметра по умолчанию ограничено значением 32768 (что соответствует
типу данных short int). По желанию его можно увеличить до 4 млн.
Для этого нужно отредактировать файл
процесса сохраняется ядром в поле
<linux/threads.h>. Идентификатор
pid каждого дескриптора процесса. Это
максимальное значение является важным, потому что оно определяет макси
мальное количество процессов, которые одновременно могут существовать
в системе .
Хотя значения
32768
вполне достаточно для офисного компьютера, для
больших серверов может потребоваться запустить значительно больше про
цессов. Чем меньше это значение, тем скорее нумерация процессов будет на
чинаться сначала, что приводит к нарушению полезного свойства: бОльший
номер процесса соответствует процессу, который запустился позже. Если
обратная совместимость со старыми приложениями не нужна, то админи
стратор может увеличить максимальное значение идентификатора процес-
•са прямо
pid_max.
во время работы системы, отредактировав файл
/proc/sys/kemeV
Как правило, в ядре для идентификации задачи используется прямая ссылка
на соответствующую структуру
•
task_struct.
По сути, в большей части кода
.. . . .. .. ...... ··· · ··· ....... .. ........... .......................................... .
Ядро
Linux
.. .... .......... .. . .. .
t\.iпux
ядра, работающего с процессами, выпол няется обращение прямо к полям
структуры
task_struct.
Нам нужно иметь возможность быстро находить
дескриптор процесса, выполня ем ого в данный момент. Специально для это
го создан макрос
current. Конкретная
реализация этого макроса зависит от
используемой аппаратной платформы. В некоторых аппаратных платформах
указатель на структуру
task_struct,
соответствующую выполняемому в на
стоящий момент процессу, сохраняется в специальном регистре процессор а,
что намного ускоряет доступ к ней. В ряде других архитектур, в частности
х86 , с ограниченным набором регистров процессора общего назначения ис
пользуется тот факт, что структура
th,-ead_info
располагается в стеке . Это
позволяет очень э ффективно вычислить ее адрес и , соответственно, опреде
лить адрес структуры
task_struct.
Чтобы получить адрес структуры
thread_info на платформе х86 и определить
13 бит указателя
стека . Для этой це.riи предусмотрена функция current_thread_info(). Соответ
значение параметра
current,
нужно замаскировать младшие
ствующий код на языке ассемблера выглядит так:
movl $ - 8192 , % еах
andl %esp , % еах
В этом фрагменте кода подразумевается , что размер стека составляет
8
8192 нужно использо
вать число 4096. Окончательно значение параметра current получается пу
тем разыменования значен ия поля task полученной структуры thread_info:
Кбайт. Если размер стека составляет
4
Кбайт, вместо
current thread info( )- >task ;
5.3.
Контекст процесса
Одной из самых важных частей процесса является исполняемый программ
ный код, который считывается из исполняемого файла (executaЬle) и в ыпол
няется в адресном пространстве процесса . Обычно выполнение программы
осуществляется в пространстве польз ователя. Когда в программе выполня
ется вызов системной функ ции или воз никает исключител ьная ситуация ,
программа входит в пространство ядра.
•
. . ......... ........................................................................ ..
Глава
n.inux .................. .
5. Как ядро у11рав. 1яс1 11ро11ссса,111
С этого момента говорят, что ядро "выполняется от имени процесса" и все
это происходит в контексте процесса . В контексте процесса макрос
current
работает корректно . При выходе из режима ядра пр оцесс продолжает выпол
нение в пространстве пользователя, если в это время не появляется готовый
к выполнению бол е е при о р итетный процесс. В таком случае управление
передается пл анировщ ику, который и выбирает для выполнения наиболее
приоритетный проце сс.
Системные функции и обр аботчики исключительных ситуаций имеют в ядре
строго определенный интерфейс. Процесс м ожет начать выполнение в про
странстве ядра 1ол ько п осредством одного из этих интерфейсов
-
любые
обращения к ядру возм ожны только через эти интерфейсы .
5.4. Созд ание
нового
npouecca
и его з аверш ение
В литературе м ожно встретить самые разные о пределения термина "про
цесс" , начиная от " экземпляр испол няемой пр ограммы " и з аканчивая "то, .
что является р езул ьтатом работы системного вызова
Linux,
clone(2)
или
fork(2)" . В
существует тр и типа процессов:
1.
Фонов ые задачи ;
2.
Потоки ядра;
3.
Пользовательс ки е задачи .
Потоки ядра порождаются с помощью функции
лает системный вызов
clone(2)
kemel_thread(),
в режиме ядра . Потоки ядра обычно не име
ют пользовательско го адр есного пространства, т. е.
му они явно выз ывают
которая де
exit_mm(),
p->mm = NULL, поэто
daemonize().
например, через функцию
Потоки ядра вс егда имеют прямой доступ к адр есн ому пространству ядра .
Получают pid из нижнего диапазона. Р аботают в нул евом кольце защиты и,
следовательно , имеют в ы сший приоритет во вс ех оп ерациях ввода/вывода и
имеют преимущество п ер ед планировщи ко м зад ач .
Пользовательские задачи создаются через системные вызовы
fork(2)c
•
•
И тот и другой обр ащаются к
clone(2)
или
kemel/fork.c: do_fork().
•
... ................................................. ............................... .
\
Я 1 •ро
l,i11ux
..... . ........ .... . . .. n.1nux
Давайте рассмотрим , что же происходит, когда пользовательский процесс де
лает системный вызов
fork(2) . Хотя fork(2)
и является аппаратно-зависимым
из-за различий в организации стека и регистров , тем не менее, основную
часть действий выполняет функция
и размещена в
do_ fork(),
которая является переносимой
kemel/fork.c.
При ветвлени и процесса выполняются следующие действия:
1.
Локальной переменной
retval
присваивается значение
-ENOMEM,
кото
рое возвращается в случае невозможности распредел ить память под но
вую структуру задачи.
2.
Если установлен флаг
CLONE_PID в
параметре
clone_.flags, тогда возвра
щается код ошибки (-ЕРЕRМ). Наличие этого флага допускается, только
если
do_ fork() была вызвана из фонового потока (idle thread), т. е. из зада.
pid == О (только в процессе загрузки). Таким образом , пользователь
ские потоки не должн ы передавать флаг CLONE_PID в clone(2), ибо этот
чи с
номер все равно не "проскочит".
· з. Инициализируется
current->vfork_sem (позднее будет очищен потомком).
Он используется функцией sys_ vfork() (системный вьrзов vfork(2), пере- •
дает clone_ flags = CLONE _ VFORКICLONE _ VMISIGCHLD) для того, что
бы "усыпить" родителя пока потомок не выполнит mm_release(), напри
мер, в результате исполнения ехес() или exit(2).
4.
В памяти размещается новая структура с помощью макроса
struct().
alloc_task_
На х86 это прои~водится с приоритетом
главная причина, по которой системный вызов
GFP_ КERNEL . Это
fork(2) может "заснуть".
Если размести,ть структуру не удалось, то возвращается код ошибки
-ENOMEM.
5.
Все поля структуры текущего процесса копируются во вновь созданную
структуру посредством присваивания *р
= *current.
Позднее , в поля, ко
торые не наследуются потомком , будут записаны корректные значения.
6.
Для сохранения реентерабел ьности кода, выполняется
7.
Если "родитель" является пользовательским ресурсом , то проверяется
-
не превышен ли предел RLIMIТ_NPROC , если превышен
-EAGAJN, если нет - у вели чивается
uid p->user->count.
вращается код ошибки
цессов для заданного
8.
blg kernel lock.
-
тогда воз
счетчик про
Если превышено системное ограничение на общее число задач
threads,
возвращается код ошибки
-EAGAJN.
- max_
•
. .......................................... .... ....... ..............................
1 ·. 1ава
n.inux __________________ _
9.
5.
Как я . 1ро ~ 11ран.1яе1 11ро11ессаш1
Если исполняемый формат программы принадлежит домену исполнения,
поддерживаемому на уровне модуля, увеличивается счетчик ссылок соот
ветствующего модуля.
10 . Если исполняемый формат программы принадлежит двоичному формату,
поддерживаемому на уровне модуля, увеличивается счетчик ссылок соот
ветствующего модуля.
= О).
12.Потомок помечается как 'not-swappaЫe' (p-> swappaЫe = О).
11. Потомок помечается
13 . Потомок
как
переводится
p->state = TASK
'has not execed' (p->did_ ехес
в
состояние
т.е.
UNINTERRUPТIBLE
14.Устанавливаются флаги потомка
случае простого
TASK_UNINTERRUPТIBLE,
fork(2),
15 . Вызовом функции,
это будет
p->flags в соответствии с clone_flags;
p->flags = PF _ FORКNOEXEC.
kemel/fork.c:get_pid(), реализующей
(p->pid) .
в
быстрый алго
ритм поиска, находится pid потомка
16.Далее инициализируется остальная часть структуры
task_struct потомка .
pidhash и потомок ак
тивируется. Обратите внимание на установку p->exit_signal в значение
clone_flags & CSIGNAL, которое для fork(2) может быть только SIGCHLD,
и на установку p->pdeath_signal в О. Сигнал pdeath_signal используется,
В самом конце структура хешируется в таблицу
когда процесс лишается "родителя" (в случае его "смерти") и может быть
получен/установлен посредством команд
системного вызова
PR GET/SET_PDEATHSIG
prctl(2)
Задача создана. Для завершения задачи имеется несколько способов.
•
Выполнить системный вызов
•
Передать сигнал, приказывающий "умереть" ;
•
Вынужденная "смерть" в результате возникновения некоторых исклю
exit(2);
чений;
•
Вызвать
bdflush(2)
с
func
== 1
(эта особенность
Linux
оставлена для
сохранения совместимости со старыми дистрибутивами, которые имели
строку
'update'
в
/etc/inittab kupdate).
на сегодняшний день эта работа выполняет
ся процессом ядра
•
..
.-------------------------. - ----------------------------------------------------·,
•
Я 1 tро
1-inux
......... •............. n..1nux
Имена функций, реализующих системные вызовы, в
с префикса
sys _,
Linux
начинаются
но они , как правило, ограничиваются только проверкой
аргументов или платформа-зависимой передачей информации, а фактиче
ски всю работу выполняют функции
do_.
Это касается и
которая
sys_exit(),
вызываетdо_ехit() для выполнения необходимых действий. Хотя, в других
частях ядра иногда встречается вызов
do_exit()
из
sys_exit (),
на самом деле вызьшается
kemel/exit.c.
Обычно уничтожение процесса инициируется самим процессом. Это проис
ходит, когда. в самом процессе вызывается системная функция
exit().
Причем
это может произойти как явно , когда вся работа программы сделана и нужно
завершить ее работу, так и неявно , при выполнении возврата из основной
процедуры любой программы с именем
main().
Другими словами , компилятор языка с помещает вызов функции exit() в код,
который выполняется посл е воз врата из процедуры
main().
Процесс также
может быть заверш ен непреднамеренно . Так происходит, когда процесс по
лучает сигнал и л и во з никает исключительная ситуация , которую тот не мо
жет обработать ил и проигнорировать. Независимо от того, каким образом
завершается процесс , основную массу работы выполняет функция
определенная в фа йл е
do_ exit(),
kemel/exit.c.
После окончания р аботы функции
do_exit()
дескриптор завершившегося
процесса все е щ е существует в системе , но сам процесс находится в состоя -
1-1ии ЗОJ116и и не может выпол няться . Как уже говорилось выше, это позволяет
системе получить информацию о дочернем процессе после его завершения.
Следовательно , освобождение ресурсов после завершения процесса и уда
ление
его дескриптора
должны
происходить
в
разные
моменты
времени
..
После того как род ител ьский процесс получил информацию о завершенном
дочернем проце ссе , л ибо уведомил ядро, что эта информация ему больше не
нужна, структур а
task_struct дочернего
Семейство функций
wait()
реализовано через единственную (и достаточно
сложную) системную функцию
ствие
-
процесса освобождается.
wait4().
Она выполняет стандартное дей
приостанавливает выполнение вызывающей задачи до завершения
одного из ее дочерних процессов. При этом функция возвращает идентифи
катор
PID
завершенного дочернего процесса. При вызове функции
wait4()
передается указатель на область памяти, которая после возврата из функции
будет содержать код завершения дочернего процесса.
Когда приходит время окончательно освободить дескриптор процесса, 13ызы
вается функция
release_task(), которая
выполняет указанные ниже операции:
•
. . .. . . .. . .. . . . . .. . . ... .. -- ............................................... . ....... .. . .
Г.11ава
n..inux ___ ____ _____ . __ ___ _
•
5. Как
ядро yr,paBJIЯCI Щ)ОЦССС,1\111
Вызывается функция_exit_ signal(), в которой затем вызывается функция
_ unhash_process(). Из последней функции вызывается еще одна функция
- detach_pid(), - которая удаляет процесс из хеш-таблицы идентифика
торов пр о цессов pidhash и сам процесс из списка задач.
•
В функции
_exit_signal()
освобождаются абсолютно все ресур с ы , кото
рые продолжают использоваться в завершившемся процессе, а также под
биваются статистические данные использования системных- р е сурсов .
•
Если завер шившаяся задача была последним членом группы потоков , а ее
лидер находится в состоянии зомби, то функция
release_task() уведомляет
род ительский·процесс лидера группы, находящегося в состоянии з омби.
•
Из функц ии
release_task() вызывается функция put_task_struct(), в которой
освобождаются страницы памяти, содержащие системный стек процесса
и структуру
держащая
5.5.
thread_info, а также
структуру task_struct.
освобождается блочная кеш- п амять , со
Потоки
Благодаря потокам
(threads)
появляется возможность выполнения несколь
ких потоков команд в общем адресном пространстве памяти. Потоки также
могут совместно использовать открытые файлы и другие ресурс ы . Потоки
позволяют р еализовать режим
( concuпent programming)
одновремен ного выполнения
пр ограмм
и обеспечить истинный параллелизм на мн огопро
цессорны х системах.
Реализ ация п отоков в операционной системе
ния ядра
Linux
Linux
уникальна. С точки зре
не существует отдельной концепции потоков. В ядре
Linux
все потоки реализованы в виде стандартных процессов. В нем нет никакой
особенной семантики для планирования выполнения потоков или каких-ли
бо особенных структур данных для представления потоков.
Поток
-
это просто процесс, который использует некотор ы е ресурсы
со вместно с другими процессами .
Каждый поток имеет свою структуру
task_struct и
с точки зрения ядра явля
ется обычным пр оцессом, который (так уж случилось!) совме стно исполь
зует с другими процессами общие ресурсы, такие как адресно е простран
ство
•
.
.. . . . --- -... --- ... --. -- . ·-- --- -- ---- ---. -.. --. -··- --·- --- -- .. -- ---· ....... ·- ----... ..
Я : 1ро
Linux
______________________ n..inux
В других операционных система, таких как
Windows,
все немного иначе.
В них существуют средства дл я явной поддержки потоков в ядре, ко
торые называют
lightweight process (процессы с быстрым переключением
- процесс с быстрым переключением контек
ста - свидетельствует о разнице в философии, принятой в Linux и других
операционных системах. В этих системах потоки - это абстракция, которая
контекста). Само название
обеспечивает облегченные и более быстрые с точки зрения выполнения бло
ки кода, по сравнению с обычными тяжеловесными процессами. Для опера
ционной системы
Linux
потоки
это просто способ совместного использо
-
вания ресурсов несколькими процессами, которые и так имеют достаточно
малое время переключения контекста.
Для создания потоков используется та же функция
clone(),
но ей передаются
флаги, указывающие на то, какие ресурсы должны использоваться
совместно,:
clone(CLONE_VM
CLONE FS
CLONE FILES
CLONE SIGHAND ,
О) ;
Резул ьтат выполнения этого кода будет таким же , как и при выполнении
обычной функции
fork(),
за исключением того, что адресное пространство,
ресурсы файловой системы, дескрипторы файлов и обработчики сигналов
останутся общими . Другими словами, и новая задача, и родительский про
цесс являются тем , что в народе популярно называется потоками.
Для сравнения вы зов обычный функции
cl o ne(SIGCHLD ,
Функцию
vfork()
fork()
может быть реализован так:
О) ;
можно реализовать следующим образом:
clone(CLONE_ VFORK
CLONE VM I SIGCH LD ,
Флаги, которые передаются системной функции
О );
clone(),
указывают особен
ности поведения нового процесса и конкретизируют, какие именно ресурсы
должны быть общими для родительского и дочернего процессов, Далее при
ведены флаги системной функции
h>, и вызываемый ими эффект:
clone(),
описанные в файле
<linux/sched.
Глава
n.inux ______ ____ ________ _
• CLONE_FILES -
Как ядро управляет процессами
родительский и дочерний процессы совместно исполь-
зуют открытые файлы.
• CLONE FS -
5.
•
информация о файловой системе будет использоваться
совместно.
• CLONE_IDLETASK -
установить значение
PID
в О.
создает новое пространства имен для дочерней за
• CLONE_ NEWSNS дачи.
•
CLONE_PARENТ
-
родительский процесс для вызывающего процесса
становит~я родительским для дочернего.
• CLONE_ SETТID -
возвращает значение идентификатора TID в простран
ство пользователя.
• CLONE_ SETTLS -
для дочернего процесса создать новую область ло
кальных данных потока.
• CLONE_SIGHAND -
у родительского и дочернего процессов будут об
щие обработчики сигналов и сигналы блокирования.
• CLONE_SYSVSEM SEM UNDO.
• CLONE_THREAD -
общей
будут
семантика
обработки
флага
родительский и дочерний процессы будут принад
лежать одной группе потоков.
• CLONE_VFORК - родительский
процесс будет находиться в заморожен
ном состоянии, пока дочерний процесс не возобновит его работу.
• CLONE_ UNTRACED - запретить трассирующему процессу
ние флага CLONE_PTRACE для дочернего процесса .
• CLONE_ STOP STOPPED.
использова
запустить процесс и перевести в состояние
• CLONE_CHILD_ CLEARTID -
TASK
очистить идентификатор ТID для дочер
него процесса.
• CLONE_CHILD_SETTID -
установить идентификатор
TID
для дочерне
го процесса.
•
CLONE_PARENТ_SETЦD
-
установить идентификатор
TID
для роди
тельского процесса.
• CLONE_ VМ - у родительского и дочернего процессов будет общее адрес
ное пространство .
, _------- ----------- -.. --. -. ---. ---. -------. --.. --. ------------- . -- - .. --- ----. --- -
...................... t'1.1пux
}l ,1po J,i1111,
Часто требуется выполнить в ядре некоторые операции в фоновом режиме,
В ядре такая во зможность реализована в виде потоков ядра
(kernel thread) -
обычных процессов, которые выполняются исключительн о в пространстве
ядра . Существенным отличием между потоками ядра и обычными процес
сами является то, что потоки в ядре не имеют своего адрес ного пространства
(значение указателя тт для них равно
NULL).
Эти потоки работают 'fолько
в пространстве ядра, и их контекст не переключается в пространство поль
зователя. Тем не менее , потоки ядра планируются и вытесняются так же, как
и обычные проце ссы.
Потоки ядра в
Linux выполняют определенные задачи. Самые важные из
- .flush и ksoftirqd. Чтобы увидеть список таких потоков в вашей систе
Linux, воспользуйтесь командой ps -ef Их довольно много! Потоки ядра
них
ме
создаются во время начальной загрузки системы другими такими же потока
ми. Это и понятно , поскольку поток ядра может быть создан только другим
потоком ядра . В ядре эти потоки обрабатываются автоматиче ски : все новые
потоки ядра разветвляются от специального процесса
kthreadd,
запущенного
в ядре . Интерфейс для порождения нового потока ядра из существующего
описан в файле
<linux/kthread.h> и
приведен ниже.
stru ct task_s truct *kthread_create (int (*threadfn) (vo i d *data) ,
void *dat a ,
const c h a r na mefmt[]
Новая задача создается процессом
kthread, запущенн ым в ядре , с помощью
clone(). В новом процессе будет выполнять
ся функция threadfn(), которой передается аргумент data. Процессу будет
присвоено имя , указанное в переменной namefmt, а в списке аргументов
вызова системной функции
переменной длины указываются параметры форматировани я в стиле функ
ции
printf()
языка С. После создания процесс находится в н езапущ енном
состоянии (unrunnaЫe
образом
вызвать функц ию
state). Для его запуска нужно явны м
wake_up_process(). Чтобы создать процесс и
сразу же
отправить его н а выполнен ие , можно воспользоваться еди нственной функ
цией
kthread_run :
111ава
r.linux __________________ _
5.
Как sщро у11равш1с 1 11ронссса~111
st r uct t ask_str uct *kthread_ run (int ( *threadfn) (void *data ) ,
void *data ,
const char namefmt[] ,
... )
Описанная выше процедура запуска процесса в ядр е реализована в виде
макроса, в котором вызываются обе функции ,
process(),
kthread_ create()
и
wake _up _
как показано ниже.
После запуска поток ядра продолжает выполняться до тех пор , пока в нем
не будет вызвана функция
do_exit(), либо пока в какой-либо другой части
kthread_stop() . В качестве параметра этой
структуры типа task_struct, возвраще нной ранее
ядра не будет вызвана функция
функции передается адрес
функцией
kthread_ create():
int kthread_st op (stru ct task struct *k)
5.6.
Планировщик
Работа планировщика заключается в разделении
CPU
между нескол ькими
процессами. Реализация планировщика размещена в файле
Соответствующий заголовочный файл
(прямо
kemel/sche,d.c.
include/li nux/sched.h подключается
или косвенно) фактически к каждому файлу с исходным текстом .
ядра.
Поля
task_struct, которые
• p->need_resched -
используются планировщиком:
это поле устанавливается если
schedule()
должна быть
вызвана при 'первом удобном случае' .
• p->counter -
число тактов системных часов , оставши хся · д о окончания
выделенного кванта времени , уменьшается по таймеру. Когда значение
этого поля становится меньше либо равно нулю , то в н его записы вается
ноль и взводится флаг
p->need_resched. Иногда это поле называют "дина
мическим приоритетом" ('dynamic priority') процесса потому как он мо
жет меняться .
•
... . . . . --- -- -.... -- ---- ...................... -- ... -- ............................. --
Я . tро (,i1111x
• p->priority -
______________________ rt.inux
статический приоритет процесса, может изменяться только
через системные вызовы , такие как
или
• p->rt_yriority- приоритет реального
•
nice(2), POSIX.1 Ь sched_ setparam(2)
4.4BSD/SVR4 setpriority(2).
времени
(realtime priority).
р->policy- политика планирования, определяет класс планирования зада
чи. Класс планирования может быть изменен системным вызовом
sched_
setscheduler(2). Допустимые значения: SCHED_ OTHER (традиционные
процессы UNIX), SCHED_FIFO (процессы реального времени POSIX.1Ь
FIFO) и SCHED_RR (процессы реального времени POSIX round-roЬin).
Допускается комбинирование любого из этих значений с SCHED_ YIELD
по ИЛИ (OR) чтобы показать, что процесс решил уступить CPU, напри
мер, при вызове sched_yield(2). Процесс реального времени FIFO будет
работать до тех пор, пока не: а) запросит выполне1:1ие блоковой опера
ции ввода/вывода , Ь) явно не отдаст
CPU
или с) будет вытеснен другим
процессом реального времени с более высоким приоритетом
в
p->rt_priority). SCHED_RR то
(значение
же самое, что и SCНED_FIFO, за исклю
чением того, что по истечении выделенного кванта времени, процесс по
мещается в конец очереди
runqueue.
Алгоритм планировщика достаточно прост, несмотря на очевидную слож
ность функции
schedule().
Сложность функции объясняется реализацией
трех алгоритмов планирования, а так же из-за учета особенностей
SMP
(мультипроцессорной обработки).
5. 7.
Управление процессами из консоли
5.7.1.
:Командырs,
nice
и
kill
Получение информации о процессе
Современные операционные системы устроены так, что каждому процессу
присваивается уникальный номер
- PID (Process ID, ИД
процесса), исполь
зуя который можно управлять процессом, например, можно завершить про
цесс или изменить его приоритет.
•
88- ------. --------------------------------------------------------------------------.
n.lпux ...... __ ......... __
Узнать
PID
1 :11а11а
5.
1{,щ sщро у11раш1щ•1 IIJ)OЦ('CC:IMII
можно с помощью команды ps. Команда ps , введенная без па
раметров, просто показывает список процессов, запущенных на текущем
терминале. Видно, что сейчас запущен bash и сама команда ps (правда, на
момент завершения вывода процесс с
ID 975
уже не будет существовать , но
на момент самого вывода такой процесс существовал), см. рис.
Рис.
5.4.
Комаида
5.4.
ps
Параметр -а позволяет вывести список всех процессов пользователя.
Посмотрите на рис.
соли
t t у1 -
5.5
на консоли ttyЗ запущена программа
nano, на
кон
программа р s.
Рис.
5.5.
Команда
ps
-а
Если нужно вывести процессы какого-то определенного пользователя, тогда
используйте параметр -и:
$
p s - u r oo t
•
.. . . . ----.. -................................... -... -.................. -............ .
Я J •ро
- - -- ---· · · -·· · ·-·-···-t\.iпux
l.inux
Вывести абсолютно все процессы можно с помощью опции -А . Обратите
внимание на регистр опции! Поскольку в системе проце ссов будет- очень
много , лучше перенаправить вывод программы на команду less для более
удобного про смотра (рис.
$ ps
-А
5.6):
I less
Ри с. 5. ба. Команда
Ри с.
5.66.
Ко;ианда
ps
ps
-А
-А
I
I
l ess
less
(начало вывода)
(завершение вывода)
•
- - ------------------------------····-·· ··········-···--··---··--· ·--··---··--··--·-·
Гла ва
n..inux .................. .
5.
Как ядро управш1ет процессами
Примечание. Для выхода из программы
less нажмите
q на
кла
виатуре. Листать вывод можно стрелками вверх и вниз.
Команда ps сортирует процессы по PID. Колонка ТТУ - это терминал, к кото
рому привязан процесс . Если в этой колонке вы видите знак
?, значит,
про
цесс не привязан ни к одному из терминалов. Как правило , это системные
процессы-службы. Они запускаются без привязки к терминалу. Чтобы
отобразить только процессы без привязки к терминалу, используется опция
-х (рис.
5.7).
Рис.
Колонка STAT -
5. 7.
Команда
ps
-х
I less
это состояние , в котором находится процесс. Возможные
з начения для этой колонки приведены в таблице
5.1.
Обратите внимание:
колонка STAT есть только , когда программа з апущена с параметром -х. Если
программа запущена с другими параметрами, например , -А, вместо нее
будет колонка TIME, которая сообщает занимаемое процессом процессорное
время.
•
•
•····· · ···························································--··············8 8
...................... а1пuх
И , tро l , i1111\
Таблица
5.1.
Возможные состояния процесса
Описание
Состояние
Процесс в непрерывном сне (как правило, ожидает вво-
D
да/вывода)
Выполняется в данный момент
R
20 секунд, поR или в состоя-
Ожидание (то есть процесс "спит" менее
s
еле чего он переходит или в состояние
ние
т
D)
Процесс остановле~
То же, что и Т, но причина остановки
t
-
останов отлад-
чиком
w
Процесс в свопинге (подкачке)
х
Процесс мертв, вы его никогда не увидите
z
его родителем, то есть процесс-родитель еще не считал
Процесс-зомби
-
он уже завершен, но не "похоронен"
код завершения
У команды
ps
есть несколько синтаксисов установки параметров. Мы ис
пользовали ВSD-синтаксис . Например, для вывода всех процессов в стан
дартном синтаксисе используется команда -е, а в нашем случае
-
-А. Вы
вольны использовать любой синтаксис, но в случае с ВSD-синтаксисом про
грамма
ps выводит дополнительное состояние процесса (работает подобно
ps в системе BSD). Дополнительное состояние процесса описа
программе
но в таблице
Таблица
5.2.
5.2. Дополнительное состояние процесса
(ВSD-синтаксис)
Состояние
Описание
<
Высокий приоритет
•
. .. ............................................................... . ........ . ... . . .. .
n.1nux .................. .
N
Низкий приоритет
L
У процесса есть страницы, заблокированные в памяти
s
Это лидер сессии
/
Процесс является многопотоковым
+
Находится на первом плане в группе процессов
Последняя колонка вывода ps - это смо. Она содержит команду, которой был
запущен процесс. Не просто название исполнимого файла, но путь (если он
был указан в команде) и переданные программе параметры .
Если программа была запущена без указания полного пути к исполнимому
файлу, и вы хотите знать, где он находится, введите команду whi c h, напри
мер:
$ which nan o
/ Ьin / nano
Если вам нужно узнать
PID
определенного процесса, но вам не хочется про
сматривать длинный список системных процессов, используйте команду
grep, как фильтр. Например, следующая команда позволит нам узнать PID
процесса
# ps
-А
sshd (это
SSH-cepвep):
I grep sshd
Если такой процесс не запущен, вывод будет пуст. Или же вы получите вы
вод вроде этого:
929 ?
0 0: 0 0:0 0 ss hd
Изменение приоритета процесса
Когда мы знаем
PID
процесса, мы можем изменить его приоритет. В неко
торых случаях полезно изменить приоритет процесса. Например, можно
•
·········--··········--···---·-·-···-··-····-·-·---······---·---···-··--···--·····-8i8
Я .· tро l,iш1x
......................
n.iпux
повысить приоритет процесса, выполняющего резервное копирование, что
бы программа успела за ночь создать все необходимые резервные копии и
чтобы этот процесс утром уже не мешал нормальной работе сервера .
Запустить программу с определенным приоритетом можно командой nice :
# nice - n
<приори т ет>
команда
Здесь приоритет задается от
-20
аргументы
(максимальный приоритет) до
19
(мини
мальный). Есл.и процесс уже был запущен, и вы не можете его прерывать, но
повысить приоритет нужно, используйте команду
# renice -n
<приоритет>
-р
renice: ,
PID
Аварийное завершение процесса
Если процесс завис и его нельзj_! завершить, как обычно, тогда для его ава
рийного завершения используется команда kill. Формат вызова этой ко
манды следующий:
$ kill
[опции]
PID
Конечно, перед этим нужно узнать
команда kill
PID
процесса
PID
процесса . На рис.
5.8
изображена
в действии: сначала я вывел список процессов , чтобы узнать
nano (1035), затем
я ввел команду kill
10 35 , чтобы "убить"
этот процесс. Наконец, я вывел список процессов еще раз , чтобы убедиться,
что процесс папа завершен.
Используя параметры программы , можно по-разному завершить процесс ..
Самый эффективный сигнал 9 (КJLL) - означ<1ет аварийное завершение про
цесса. Программа не может игнорировать или как-либо обработать этот про
цесс.
Если нужно попытаться корректно завер шить работу программы, ей отправ
ляют сигнал 15
(ТЕRМ), означающий , что программа должна освободить
все занятые ресурсы, сохранить все данные. Вот только если программа за-
•
. .. .. . . . .. .. . . . . ... .. .. ... .. .... .. . ... . .. . .. . .. . ... . . . .. . . .. ...... .. . ....... .. . .. . . .
Глава
n.i~ux __________________ _
5.
Как ядро у11раш1яс1 11роцссса\11t
висла и не отвечает на запросы пользователя , этот сигнал мало чем поможет,
но попытаться стоит.
[ rootl• 1ш:,,
Р ID ТГУ
llшs
t
1из~•
Ш1 :fШ :ИН
1 t., 1:i
11?.'} t t,Jt
1 root l• 1ос,, l lн,:: t
Hli
111 \..111
1 гооt f• l11c,1 11111. 1
111
Рис.
Сигнал 1 9
• 111 1'"
TIME
(STOP)
НН:НН
5.8.
,1
СМJ)
н,1но
р;
Н!У,
Использование команды
kill
позволяет временно приостановить работу программы, а
сигнал 18 (CONT) - возобновить приостановленный ранее процесс.
Для сетевых служб полезен сигнал 1 (НUР), означающий, что процесс дол
жен перезапуститься и перечитать файл конфигурации. Полезно, когда вы
изменили файл конфигурации и хотите, чтобы демон был перезапущен (хотя
для этого правильнее использовать команду
при получении сигнала
se r v i ce).
Обычная программа
1 завершает работу.
Пример отправки сигнала:
$ k i ll - 9 1035
Если вам лень получать
пользуя команду
PID
killa l l ,
процесса, можно завершить его и по имени, ис
например:
$ killall nano
•
·-------···--··--·-·-···--·---··--····--------··--·-·-·-·······--·-··········--··- - 8 8
И .' tро l,i1шx
......... . ............ t'l.1nux
Вот только если в вашей системе есть два процесса с именем папо, например,
один на консоли
tty2,
а другой
на
-
tty4,
то будут завершены оба процес
са. Если это то, что вам нужно , используйте
лучше использовать команду
kil l
killall, в противном случае
для завершения именно того процесса,
который можно завершить .
Еще есть команда xkill, позволяющая "убить" программу, имеющую гра
фический интерфейс. Такие программы можно завершить и командой
но программа
xkill
kill,
предоставляет графический метод завершения . После
ввода этой команды указатель мыши примет вид черепа . Для завершения
программы нужно щелкнуть по ее окну.
5. 7.2.
Команда
top
Как было отмечено ранее, программа ps по умолчанию сортирует процессы
по колонке
PID,
а не по колонке TIME. Конечно , можно использовать раз
личные параметры программы, чтобы добиться нужного нам вывода, но все
равно программа не будет показывать ситуацию в реальном времени. Если
же вам нужно знать, что происходит с вашими процессами в реальном вре
мени, вам нужно использовать программу
..
Рис.
5.9.
top
Команда
(рис.
top
5.9).
•
. . .. . . . . . . . ------------------------.. ---. -- -... -.. -- -... ---. -. ---.... -... -...... -.
t\.1пux .................. .
1 1ава :-.
Kai..: il. tJIO ~••рав. 1щ•1 11po11rcc:l\111
Назначение колонок программы описано в таблице
Таблица
5.3.
Колонки программы
top
Описание
Колонка
PID
PID
USER
грамму)
Приоритет процесса
Значение
NI
RES
процесса
Владелец процесса (пользователь, запустивший про-
PR
VIRT
5.3.
nice
Виртуальная память, которая используется процессом
Размер процесса, который не перемещается в область
подкачки
SHR
Разделяемая память, используемая процессом
s
Состояние процесса
¾CPU
Процессорное время , занимаемое процессом в данный
момент
¾МЕМ
ТIМЕ+
Память, используемая процессом
Процессорное время , которое было потрачено с момента запуска процесса
Команда запуска процесса
COMMAND
При просмотре списка программы top
вы можете управлять сортировкой
процессов с помощью нажатия клавиши
торой сортируется список процессов
выполняется по колонке
•
F, которая изменяет колонку, по ко
(рис . 5.10). По умолчанию сортировка
%CPU .
.--------. -----. -----------. --- --- ------------- --·----------- --------.---. --.. ---.-tllll
Я J tl)CI l ,illll\
Рис.
.:.................... n.inux
5.10.
Выбор колонки, по которой осуществляется сортировка
Нажатие клавиши
<U> показывает только процессы определенного пользо
<U> нужно будет ввести имя пользователя , процессы
вы хотите просмотреть , или нажать Enter, чтобы просмотреть про
вателя. После нажатия
которого
цессы всех пользователей.
5.7.3.
Информация об использовании памяти и дискового
пространства
Хотя управление памятью и ди·сковым пространством не совсем относит
ся к управлению процессами, но эти самые процессы активно "поедают",
как память, так и дисковое пространство, поэтому иногда полезно знать, как
просмотреть информацию об использовании памяти (команда
кового пространства (команда df ), см. рис.
free )
и дис
5.11.
•
ID- -.---.. --.. ---.. --.. ---.. -... ----.--.. --... --.. --... -.. ---.. --.. --... --.. ---.. -...
1J1a11a 5.
t'l.1nux .................. .
Рис.
5.11.
Кол,анды
К:11, sщро )'lll)ШIJ ISI{' 1 IIJ)OЦ~t· t·:1м11
free
и
df
-Н
Программа fr e e выводит информацию об использовании памяти (Mem) и
подкачки (swap). Колонка total - это общее количество памяти в килобай
used - использованное количество памяти (тоже в килобайтах), f r ee свободно памяти , shared - разделяемая память , buff/ cache - размер кэша,
availaЫe - общий объем доступной памяти.
тах,
Параметр -Н команды
df означает вывод информации об объеме в удобных
для восприятия человеком единицах , то есть в мегабайтах и гигабайтах.
Обратите внимание на значение buff/ cache в выводе команды f r ee . Оно
показывает сколько памяти задействовано под буфер ввода/вывода и кэш. В
нашем случае (рис.
5.11) -
примерно
323
Мб. На реальном сервере это зна
чение будет гораздо выше. Немного освободить память можно , очистив кэш.
Для этого введите команду:
sync ; echo 3 > /proc/sys/vm/drop caches
Сначала мы командой
sync сбрасываем содержимое буферов на диск, а за
тем уничтожаем кэш . Если просмотреть затем информацию об использова
нии памяти , то вы увидите , что размер кэша был уменьшен почти в три раза
(рис.
•
5.12).
Однако помните , что эта команда может негативно отразиться
.----.---. ---. -----------------------.-. ---.-----. -. ------------. -----------------tll!I
Я , tро [,i1шх
...... ________________ n..inux
на стабильности системы и на скорости ее работы. Не всегда очистка кэша
таким вот варварским образом
Рис.
5.12. До
это хорошо .
-
sync; echo 3 > /proc/sys/vm/
drop_ caches
и после ввода комаиды
5. 7.4.
Команда
Команда f user
fus e r позволяет узнать, какой процесс открыл тот или иной ресурс,
например , файл или сетевой порт. Примеры использования программы:
f user - va 23/tcp
fu ser - va /chroot/etc/resolv.conf
В первом случае мы получим идентификатор процесса, открывшего ТСР
порт 23, во
resolv.conf.
втором
-
идентификатор процесса, открывшего файл
Что делать далее
процесс командой
-
/chroot/etc/
решать вам , например, можно "убить" этот
kill .
•
I D--.--------------.. ---.-.----- -.----------.-.----.------------.------.-----.-----.
n.inux ___ ____ ____ : ______ _
Глава
5.
Как ядро у11равляет 11роцессам11
В этой важной главе мы разобрались , как ядро управляет процессами из
нутр и и как управлять процессами из командной оболочки .
•
.------------.--.- ----. ---.. ---.------.. -------.-.--. --------. ------------... -.. ----1118
Глава
6.
Обработка прерываний
Я , 1ро
l,inux
...................... n..inux
6.1. Что т акое
прерывания
Прерывания позволяют аппаратным устройствам взаимодействовать с про
цессором. Например, при наборе на клавиатуре контроллер клавиатуры (или
другое устройство, которое обслуживает клавиатуру) генерирует прерыва
ние , чтобы объявить операционной _системе о том, что произошли нажатия
клавиш. Прерывания
-
это специальные электрические сигналы, которые
аппаратные устройства посылают процессору. Процессор получает преры
вание и дает сигнал операционной системе о том, что ОС может обработать
новые данные. Аппаратные устройства генерируют прерывания асинхр,он
но по отношению к тактовому генератору процессора
-
прерывания могут
возникать непредсказуемо , в любой момент времени. Следовательно, работа
ядра может быть прервана в любой момент для того, чтобы обработать пре
рывания .
Физически прерывания производятся электрическими сигналами, которые
создаются устройствами и направляются на входные контакты микросхемы
контроллера прерываний. Контроллер прерываний в свою очередь отправ
ляет сигнал процессору. Процессор выполняет детектирование сигнала и
•
прерывает выполнение работы для того, чтобы обработать прерывание.
al-·--·--------·----·----------------·---··--------·-----------··-··--·············· ·
•
t'liпux
1J iaвa
__________ ... ____ _
(1. Обрабо~ 1,а
11pt·p1.111:11111ii
После этого процессор извещает операционную систему о том, что произо
шло прерывание и операционная система может соответствующим образом
это прерывание обработать.
Различ ные устройства связаны со своими прерываниями с помощью уни
кальных числовых значений, соответствующих каждому прерыванию. От
сюда следует, что прерывания, поступившие от клавиатуры, отличаются от
прерываний , поступивших от жесткого диска. Это позволяет операционной
системе различать прерывания и иметь информацию о том, какое аппаратное
устройство произвело данное прерывание . Поэтому операционная система
может обслуживать каждое прерывание с помощью своего уникального об
работчика.
Идентификатор ы , соответствующие прерываниям, часто называются лини
ями запросов на прерывание (inteпupt
request lines, IRQ lines) . Обычно это
IRQ, равное О, IRQ, равное 1, - прерывание клавиатуры. Одна
некоторые числа. Например , для платформы РС значение
это прерывание таймера, а
ко не все номера прерываний жестко определены. Прерывания, связанные
с устройствами шины
PCI,
например, назначаются динамически. Друг.пе
платформы, которые не поддерживают стандарт
PCI,
имеют анал огичные
функции динамического назначения номеров прерываний. Основная идея
состоит
в
том,
что
определенные
прерывания
связаны
с
определенными
устройствами, и у ядра есть вся эта информация. Аппаратное обеспечение,
•чтобы
привлечь внимание ядра, генерирует прерывание вроде "Была нажата
клавиша! Ее нужно обработать".
6.2.
Обработчики прерывания
6.2.1.
Что такое обработчик прерывания?
Обработчиком прерывания
(interrupt handler)
называется функция, кото
рую вызывает ядро в ответ на поступление определенного прерывания.
Каждому устройству, которое может генерировать прерывания, в ядре соот
ветствует свой обработчик прерывания. Например, одна функция обрабаты
вает прерывание от системного таймера , а другая
-
прерывания, сгенериро
ванные клавиатурой . Обработчик прерывания для определенного устройства
•
.--... -----.---.----.. --....... --.. ---.-------.. ----.--.------------.----.--------ID
Ящю
l,inux
. _-_ ................... rL.inux
является частью драйвера этого устройства
-
кода ядра, который управляет
устройство~.
В
Linux
обработчиком прерывания является обычная функция, написанная
на языке С
-
ничего фантастического в обработчике прерывания нет. Все
функции-обработчики должны соответствовать определенному прототипу,
чтобы ядро могло стандартным образом передавать информацию обработ
чику, а во всем остальном
-
это обычные функции.
Обработчики прерываний вызываются в специальном контексте , который
называется коюпекстом прерывания
(interrupt context).
В этом контексте код
не может быть блокирован.
Прерывание может возникнуть в любой момент времени, поэтому обработ
чик прерывания может быть вызван когда угодно. Крайне важно, чтобы об
работчик прерывания выполнялся очень быстро и возобновлял управление
прерванного кода как можно скорее. Поэтому, хотя для аппаратного обеспе
чения и важно , чтобы прерывание обслуживалось немедленно , для осталь
ной системы важно, чтобы обработчик прерывания выполнялся в течение
максимально короткого промежутка времени.
Обработчик прерывания , как минимум, должен отправить подтверждение
устройству, что прерывание получено. Конечно, в реальной жизни обработ
чик прерывания выполняет гораздо более сложную работу. Например, об
работчик прерывания сетевой карты должен скопировать пакеты из памяти
сетевого адаптера в память компьютера и обработать их. Как видите, это
гораздо больше, чем просто отправить подтверждение, что прерывание по
лучено .
6.2.2.
Регистрация обработчика прерывания
Как уже было отмечено , обработчик прерывания является частью драйвера
устройства, который управляет аппаратным устройством . С каждым устрой
ством связан свой драйвер и есл'и устройство использует прерывания (в
большинстве случаев это так), драйвер должен зарегистрировать обработ
чик прерывания.
Регистрация обработчика осуществляется с помощью функции
определенной в
request_irq(),
linux/interrupt.h:
1111-....................................................................... ~ ........ '
1а lа ва
n..inux _________________ _
/ * r e qu e st_irq : за н имает ука з а нн ую
int requ e st_ irq (unsigned int i rq,
irq_handler_ t handler ,
unsigned l6ng flags ,
const char *name ,
void *dev )
Первый параметр
-
линию
(1 . Ofipafio I К.1 llf)t• p1,1щ11111i1
IRQ * /
это номер прерывания. Для некоторых устройств вроде
клавиатуры, таймера, номер прерывания жестко закреплен. Для большин
ства других устройств это значение определяется динамическим путем.
Второй параметр
-
указатель на функцию обработчика прерывания. Эта
функция вызывается операционной системой в момент получения сигнала
прерывания. Следует обратить внимание на специфический прототип функ
ции-обработчика.
typedef irqreturn t
(*irq_handler t ) (in t , vo id * );
Обратите внимание на специфический прототип этой функции . Ей переда
ются два параметра , а она возвращает значение типа
irqreturn_t.
Эту функ
цию мы рассмотрим чуть позже .
Третий параметр , .fiags, может быть равен О или содержать битовую маску
1
флагов , представленных в заголовочном файле
linux/interrupt.h.
Рассмотрим некоторые из флагов:
• IRQF _DISABLED -
если данный флаг установлен, то во время выпол
нения обработчика прерываний все прерывания будут запрещены. Если
флаг не установлен , то при выполнении обработчика прерываний все
другие прерывания, кроме собственного, разрешены. В большинстве об
работчиков прерываний данный флаг не устанавливается, поскольку
запрещать все прерывания -
это плохая идея. Да'нный флаг используется
для критичных по времени обработчиков прерываний , которые должны
выполняться очень быстро.
• . IRQF _ SAMPLE_ RANDOM -
•
этот флаг указывает, что прерывания, сгене
рированные данным устройством, должны вносить вклад в пул энтропии
.
ядра . Последний обе спечивает генерацию истинно случайных чисел на
основе различных случайных событий. Если этот флаг указан, то момен
ты времени , когда приходят прерывания , занос ятся в пул в виде энтропии.
.-----.. --- ------.. --· ·-· -............ -· .......... ·-.. ·-...................... -·· ·-1111
'
Н , 11111
l ,illll\
_.............. _...... n.1nux
Этот флаг нельзя устанавливать, если устройство генерирует прерывания
в предсказуемые моменты времени (как, например , системный таймер)
или на устройство может повлиять внешний злоумышленник (как, напри
мер, сетевое устройство).
• IRQF _ ТIMER - этот флаг указывает, что данный обработчик прерывания
обслуживает системный таймер.
этот флаг указывает, что данный номер
• IRQF _SHARED -
IRQ
может
совместно использоваться несколькими обработчиками прерываний. Его
нужно использовать при регистрации обработчика прерываний, если по
следний использует одну и ту же линию
IRQ
с другими обработчиками
прерываний . Если флаг сброшен, то для одной линии
IRQ
может суще
ствовать только один обработчик прерывания.
Четвертый параметр
(name)
содержит АSСП-строку, описывающую устрой
ство , связанное с данным обработчиком прерывания . Например, для обра
ботчика прерывания клавиатуры персонального компьютера данный пара
метр содержит строку
"keyboard".
Текстовые имена устройств используются
для взаимодействия с пользователями с помощью интерфейсов
/proc/irq
и
/
proc/interrupts.
Пятый параметр
(dev)
вающих общие линии
используется в обработчиках прерываний, обслужи
IRQ.
При освобождении обработчика (этот процесс
будет рассмотрен ниже) в параметре
dev
указывается уникальный иденти
фикатор, который позволяет удалить только требуемый обработчик из задан
ной линии
IRQ.
Без этого параметра ядро не смогло бы определить, какой
именно обработчик прерывания следует удалить с данной линии
линия
IRQ
используется монопольно, то в качестве параметра
ется значение
NULL.
Если линия
IRQ
IRQ. Если
dev указыва
используется совместно несколькими
обработчиками прерываний, то вы должны указать для каждого из них уни
кальный идентификатор.
В случае успеха функция
ненулевое
-
request_irq()
возвращает нулевое значение. Если
есть ошибка. В случае ошибки обработчик не регистрируется.
Чаще всего возвращается значение
выбранная линия
IRQ
E_BUSY,
указывающее на то, что
используется в другом обработчике прерывания и
либо вы, либо автор другого драйвера забыл указать флаг
IRQF_SHARED.
Пример захвата прерывания:
•
•
1111· ································· ·····•"··························
··-············
1 1 1а11а
t\.1nux ................. .
(1. Ofi1•afiщ
1,.:1
щн.·1н,11ш1111ii
i f (request_irq(irqnum, inthndl r ,
printk(КERN_ERR
IRQF_SНARED , "some_device", some_dev))
"some device : cannot register IRQ %d\ n", irqn);
return -EIO;
В этом примере в параметре
irqnum указывается запрашиваемый номер IRQ.
Параметр inthndlr определяет обработчик этой линии IRQ, которая может
совместно использоваться, поскольку указан флаг IRQF_SHARED. Имя
устройства "some_device", а в параметре some_dev передается значение
идентификатора устройства dev. В случае ошибки мы пишем в лог ядра
сообщение об ошибке .
При выгрузке драйвера устройства из памяти компьютера необходимо от
менить регистрацию обработчика прерывания и по возможности заблокиро
вать линию
IRQ.
Для этого вызывается следующая функция :
void free irq(unsigned int irq , void *dev)
Если указанная линия
IRQ
используется монопольно, то эта функция уда
ляет обработчик прерывания и блокирует линию
IRQ.
Если линия
IRQ
ис
пользуется совместно с другими обработчиками прерываний, то удаляется
обработчик, соответствующий параметру
dev.
Линия
IRQ
блокируется толь
ко тогда, когда будет удален последний обработчик прерывания. При
совместном использовании линии
IRQ уникальный идентификатор требует
ся для того, чтобы отличать друг от друга различные обработчики , связан
ные с одним и тем же номером
IRQ.
Это позволяет в функции
free_irq()
уда
лять нужный обработчик. В любом случае (совместного или монопольного
использования линии
IRQ),
если параметр
dev
не равен значению
NULL,
то он должен соответствовать тому обработчику, которы й удаляется. Вызов
функции
6.3.
free_irq()
должен выполняться из контекста процесса.
Пишем собственный обработчик
прерывания
Как вы догадались, самое сложное
-
это не зарегистрировать обработчик,
а написать его. Прототип функции-обработчика прерывания выглядит так:
•
.................................................................................·-1111
Ящю
l,inux
...................... t\..inux
static irqreturn t inthndlr(int irq , void *dev)
Описание функции соответству~т прототипу второго аргумента handler, ко
торый передается функции request_irq(). В первом параметре, irq, задается
числовое значение номера линии запроса на прерывание , которую будет
обслуживать обработчик. Несмотря на то, что это значение передается об
работчику прерываний, оно используется очень редко, в основном в диагно
стических сообщениях, выводимых в системный журнал.
Второй параметр является уникальным идентификатором устройства, он
должен совпадать с параметром
dev, который
передан функции
request_irq()
при регистрации обработчика прерывания.
Функция-обраб отчик может возвращать одно из двух значений типа
irqreturn: IRQ_ NONE и IRQ_HANDLED.
Первое
-
если обработчик преры
вания обнаружил , что устройство, которое он обслуживает, не является ис
точником прерывания. Второе
- если обработчик вы з ван правильно. Также
IRQ_RETVAL(val). Если значение параметра
val не равно нулю, то макрос возвращает значение IRQ_HANDLED, ина
че возвращается з начение , равное IRQ_NONE. Эти специальные значения •
можно использовать макрос
позвол.яют проинформировать ядро о том, генерирует ли устройство пара
зитные (т.е. необрабатываемые) прерывания . Если все обработчики пре
рывания , которые обслуживают данную линию
IRQ_NONE, то ядро
ный тип возвращаемого значения,
int .
IRQ, возвращают
значение
может обнаружить проблему. Заметим, что этот стран
irqreturn_t,
просто соответствует типу
Подстановка типа используется для того , чтобы обеспечить
совместимость с более ранними версиями ядра, у которых не было подоб
ной возможности .
Настал момент истины: попробуем написать настоящий обработчик преры
вания, который используется в драйвере часов реального времени
clock, RTC).
(real-time
Это самый простой пример обработчика прерывания для кон
кретного устройства. Код , рассмотренный далее, находится, как правило, в
файле
drivers/char/rtc.c.
При загрузке драйвера
RTC
вызывается функция
rtc_init(),
которая инициа
лизирует драйвер. Также она регистрирует обработчик прерывания, как по
казано далее :
•
1111-----·· .... ·-................ ··----.--.·------·. ---·. --·-------------.---.-------.
•
t\.iпux ........... •...... .
1 JJaвa (1 . Обрабс111,а 11pt•pы11:11111i1
/ * Регистрация обработчика rtc interrupt на r tc ir q * /
if (request_ irq(rtc irq , rtc int e rrupt , IRQ F_SHARE D, "rtc",
(void *)&rtc_ port)) {
printk ( КERN_ERR " rtc : cannot register IRQ %d\n ", rt c_irq);
return - EIO ;
Номер прерывания хранится в переменной
rtc_irq
и зависит от конкретной
аппаратной платформы . Для РС
б отчик прерывания
- это 8. Второй параметр указывает обра
rtc_interrupt. Благодаря установке флага IRQF _ SHARED
этот обработчик , по мере необходимости , может совместно с другими обра
ботчиками использовать общую линию IRQ. Значение четвертого параметра
определяет имя устройства
- "rtc" . Поскольку устройство RTC может ис
IRQ, в пятом параметре передается уникальное
параметра dev.
п ользовать общую линию
ля устройства значение
Обработчик прерывания выглядит так:
s tatic irqreturn t rtc interrupt(int irq , void *dev )
{
spin_lock(&rtc_lock);
rtc irq_data += 0xl00 ;
rtc_irq_data &= ~0xff ;
rtc_irq_data 1= (CMOS_READ(RTC_ INTR_FLAGS ) & 0xF0 );
if (rtc status & RTC_TIMER_ON)
mod_timer(&rtc_irq_timer , jiffies + HZ/rtc f re q + 2 *HZ / 1 00 );
spin unlock(&rtc lock) ;
spin lock(&rtc task lock) ;
if (rtc callback)
rtc_callback->func(rtc_callback - >private_data );
spin_unlock(&rtc task_ lock);
wake_up_interruptiЫe(&rtc_wait) ;
kill fasync(&rtc_async_queue, SIGIO , POLL IN );
return IRQ_HANDLED;
Данная функция вызывается всякий раз , когда наша система получает пре
рывание от устройства
RTC. Обратите
внимание на вызовы функций спин
бл окировок. Первая группа вызовов гарантирует, что к переменной
data
•
rtc_irq_
не будет конкурентных обращений со стороны других процессоров на
..........................................-....................................... -1111
И , (JНI J,i1111\
...................... t'1.1nux
многопроцессорной машине. Вторая группа вызовов защищает в аналогич
ной ситуации поля структуры
rtc_callback.
У переменной
тип
rtc_irq_data
информация об устройстве
unsigned /ong.
RTC,
В ней будет храниться
которая обновляется при поступлении
каждого прерывания и отражает состояние прерывания. Далее, если запу
щен генератор периодических сигналов, обновляется значение системного
таймера с помощью функции
mod_timer().
Таймеры будут описаны в сле
дующей главе.
Во второй части кода, которая отделена пустой строкой , запускается функ
ция обратноrо вызова, если таковая была установлена. Драйвер
RTC
позво
ляет устанавливать данную функцию, которая может быть зарегистрирована
извне. В результате она будет запускаться при каждом прерывании, которое
приходит от устройства
RTC.
Функция-обработчик возвращает значение
IRQ_HANDLED,
чтобы указать,
что прерывание от данного устройства корректно обработано.
6.4. API драйверов
высокого уровня
Ранее мы рассмотрели функции
request_irq()
и
free_irq() -
это основные
функции для обработки прерывания. Первая из них запрашивает установ
ку обработчика прерывания с заданным номером, вторая
работчик . Кроме этих функций в таблице
6.1.
-
освобождает об
приведены другие функции,
которые могут вам понадобится . Описание всех этих функций можно найти
по адресу:
https ://www, kernel. org/doc/html/v4.12/core-api/kernel-api, html
Таблица
6.1. Дополнительные АР/ высокого уровня
Функция
Описание
Отключает выбранную линию прерывания. Включения и отключения являются вложенными. Эта
функция ожидает завершения всех ожидающих
disaЬ/e_irqO
обработчиков
IRQ для
этого прерывания перед
возвратом. Если вы используете эту функцию,
удерживая ресурс, который может понадобиться
обработчику
IRQ,
вы попадете в мертвую блоки-
ровку
(deadlock)
~,
....................................................................................
Глава
r.linux ___ ______________ _
епаЬ/е_irqQ
disaЬ/e_irq_ поsупсО
(только
SMP)
synchronize_irqQ
(только SMP)
irq_set_irq_ typeQ
6. Обработка 11рерыва1111й
Включает выбранную линию прерывания
Отключает линию прерывания без ожидания.
Функция должна вызываться из контекста прерывания
Ждать ожидающих обработчиков
IRQ
(на других
процессорах)
Устанавливает тип триггера прерывания для задан-
ного
IRQ
Включает/выключает режим управления питанием при пробуждении, по умолчанию этот режим
irq_set_irq_wakeQ
отключен. Включение данного режима позволяет
указанному прерыванию пробуждать систему из
состояния сна
irq_ set_ handler_
dataO
irq_set_chipQ
irq_set_ chip_dataO
6.5.
Устанавливает данные обработчика прерывания
для заданного прерывания
Устанавливает чип
IRQ
для заданного прерывания
Устанавливает данные чипа для заданного прерывания
Контекст прерывания
При выполнении обработчика прерывания ядро находится в контексте пре
рывания. Напомним, что контекст процесса
-
это режим, в котором ра
ботает ядро, выполняя работу от имени процесса, например, выполнение
вызова системной функции или потока ядра .
•
.--- ------ ------.-----.---.--.--. -----------.----. ----.-- ---.. -------.. --.---.--- --1111
Ядро
______________________ n..inux
l.inux
В контексте процесса макрос
current
возвращает указатель на связанную с
ним задачу. Более того, поскольку при вызове функций ядра не происходит
переключение конт екста процесса , система может приостановить выполне
ние текущей задачи и переключиться на выполнение другой.
В отличие от контекста процесса конт екст прерывания не связан ни с од
ним процессом . По этому макрос
current
не имеет особого смысла, хотя он
и возвращает указатель на процесс , выполнение которого было прервано.
Поскольку в контексте прерывания нет сопровождающего его процесса, этот
контекст нельзя перевести в состояние ожидания. Дело в том, что тогда бы
нарушилась р 4 бота системного планировщика: нельзя перепланировать кон
текст в котором нет задачи. Поэтому некоторые функции ядра не могут быть
вызваны из контекста прерывания . Если функция может переводить процесс
в состояние ожидания , то ее нельзя вызывать в обработчике прерывания, а
это, в свою очередь , ограничивает набор функций, которые можно использо
вать в обработчиках прерываний.
Контекст прерывания является критичным ко времени выполнения, посколь
ку на время обработки прерывания выполнение некоторого программного
кода прекращается . Код же самого обработчика прерывания должен быть
простой и быстрый . Использование в нем циклов проверки состояния чего
либо
(busy loop)
крайне нежелательно , хотя и возможно . Это очень важный
момент. Всегда следует помнить, что обработчик прерывания прерывает ра
боту некоторого кода. В связи со своей асинхронной природой обработчики
прерываний должны быть юlк можно более быстрыми и простыми. Макси
мально возможную часть работы необходимо изъять из обработчика преры
вания и переложить на его нижнюю половину, которая выполняется в более
подходящее время .
Во время конфигурации системы можно определить размер стека обработ
чика прерывания . Исторически так сложилось , чtо обработчик прерывания
не имел собственного стека . Вместо этого он должен был использовать стек
ядра прерванного процесса. Стандартный размер стека ядра составляет две
страницы памяти , что обычно соответствует
16
Кбайт
-
для 64-разрядных.
Поскольку подразумевается, что обработчики прерываний используют об
щий стек, они должны очень экономно расходовать память в этом стеке. Ко
нечно, размер стека ядра будет всегда ограничен, поэтому при разработке
любого кода ядра следует всегда иметь это в виду.
•
ID ---------------------------------------,-----------------.. ---.. --. -----. ------.-.
•
1J 1ава
n..inux _________________ _
6.6.
Функция
(1. Обрабо1 ка 11рсрына1111ii
do_ IRQ()
Рассмотрим весь процесс обработки прерывания:
1. Первым делом устройство инициирует прерывание путем отправки элек
трического сигнала контроллеру прерываний по аппаратной шине. Если
нужная линия запроса на прерывание не запрещена, контроллер преры
ваний отправляет сигнал прерывания процессору. В большинстве аппа
ратных платформ это происходит путем подачи сигнала на специальный
вход микросхемы центрального процессора.
2.
Если прерывания в процессоре разрешены (иногда они могут быть запре
щены), процессор завершает выполнение текущей машинной команды,
запрещает прием новых прерываний, осуществляет переход на специаль
ный адрес в памяти и начинает выполнять программный код, который на
ходится по данному адресу. Сей заранее предопределенный адрес памяти
был заранее сконфигурирован ядром и является точкой входа в обработ
чики прерываний.
3.
Вход в систему обработки прерываний в ядре начинается со строго опре
деленной точки, так же, как и при вызове системных функций, вход в
ядро выполняется через преопределенный обработчик исключительных
ситуаций . Для каждой линии
IRQ
в памяти машины предусмотрена своя
уникальная точка входа, куда и переходит процессор, после чего он на
чинает выполнять расположенный там код. Именно таким образом ядро
узнает о номере
IRQ
произошедшего прерывания. В точке входа сначала
сохраняется в стеке значение номера прерывания и значения всех реги
стров процессора, которые относились к прерванной задаче. После этого
ядро вызывает функцию
4.
Функция
IRQ?
do_IRQ()
do_IRQ().
определяет, задан ли обработчик для данной линии
Если нет, тогда вызывается функция
ret_from _intr()
и происходит
возврат к выполнению прерванного кода.
5.
Если обработчик прерывания задан, тогда вызывается функция
IRQ_event(),
handle_
IRQ,
которая выполнит все обработчики для заданной линии
а затем выполнит функцию
ret_from_intr()
для выхода из прерывания и
возвращения к выполнению прерванного кода
.
.-------... ------------------.-----.-------------.. ----------------.. ---. -.-------81111
Я , tро
Linux
Функция
...................... n .i n ux
do_IRQ()
определена так :
unsigned int do IRQ(struct pt regs regs)
Поскольку соглашение о вызовах функций в языке С предусматривает раз
мещение их аргументов в вершине стека, первоначальные значения всех ре
гистров процессора, которые были сохранены ассемблерной программой в
точке входа, передаются в функцию
do_IRQ()
через структуру
pt_regs.
Так
как в этой стру!(Т)'ре также сохраняется значение номера прерывания, функ
ция
do_ IRQ()
может его легко извлечь . После вычисления значения номера
IRQ
функция
do_IRQ()
отправляет уведомление о получении прерывания и
запрещает генерирование прерываний по данной линии . Для обычных ма
шин платформы РС эти действия выполняются с помощью функции
mask_
and_ack_8295A().
Далее в функции
do_ IRQ() выполняется проверка, что для данной линии IRQ
зарегистрирован корректный обработчик прерывания , что этот обработчик
разрешен и не выполняется в данный момент. Если все эти условия выпол
няются , то вызывается функция
kemel/irq/handle.c,
handle_IRQ_event(),
определенная в файле
которая запускает установленные для данной линии
IRQ
обработчики прерывания.
Код этой функции следующей:
irqreturn_t handle irq_event(struct i rq_desc *desc )
{
irqreturn_t ret ;
desc- >istate &= ~IRQS PENDING ;
irqd_set(&desc - >irq_ data , IRQD IRQ_I NPROGRESS );
raw_spin_ unlock(&desc - >lock );
ret = handle irq_event_percpu(desc) ;
raw spin_lock(&desc - >l ock );
irqd_ clear(&desc - >irq_data , IRQD_ IRQ_I NPROGRE SS );
return ret ;
•
a i t ·········· · ·······································································
l ~ 1ава
n..inux ................. .
()_
Обрабо1ка 11рсрыв.11111ii
Поскольку сегодня машины , в основном , являются многопроцессорными , то
сама функция handle_irq_event() передает управление функции handle_irq_
event_percpu(), которая, в свою очередь , возвращает значение , сгенерирован
ное функцией _handle_irq_event_percpu(), которая и делает всю основную
работу:
i r qreturn t handl e irq_event_percpu (struct i rq_desc *desc)
{
irqreturn t r e tval ;
retval = _handle irq event_percpu (desc) ;
add_interrupt_ randomness (desc - >irq_data . irq) ;
if ( ! irq_settings_no_debug (desc ))
note inter r upt (desc , retval) ;
return retval ;
irqreturn t
handle irq_event_percpu (st r uct irq_desc *desc)
{
irqreturn t retval = IRQ_NONE ;
unsigned int irq = desc - >irq data . 1rq;
s truct irqaction *action ;
record irq_t i me (desc );
for each_ action of_desc(desc , acti o n)
irqreturn t re s ;
/*
*
force_irqthreads , о тметить
*/
if (irq_settings_can_thread(desc) &&
! (action - >flags & (IRQF_NO_THREAD
IRQF_ PERCPU
IRQF_ ONESHOT)))
lockdep_hardirq_threaded() ;
Если это
со ответствующим
IRQ
{
будет
передано под
его
образом .
trace irq handler entry(irq , act1on) ;
res = action - >handler(irq , action->dev_id) ;
trace irq_handler_ exit(irq , action , res) ;
if (WARN_ONCE (! irqs disaЬled ()," irq
interrupts \ n ",
irq , action - >handler))
local irq disaЬle() ;
•
%и
handler %pS
enaЫed
...................................--.... -.. --.. --... --..... -.--....... ---.... -----ID
И , 1рс1 l.i1111,
......................
ft1пux
switch (res) {
case IRQ_WAKE THREAD :
/*
Перехватьrвать
но
не
драйверы,
настроившие
возвращающие
функцию
WAKE_THREAD,
потока
*/
if (unlikely(!acti on - >thread_fn ))
warn_no_thread(irq, action);
break;
_irq_wake thread(desc, action);
break;
default:
break;
retval 1= res;
return retval;
Функция
ret_from_intr()
и код входа в прерывание написаны на языке ас
семблера. В этой функции проверяется, есть ли ожидающий запрос на пере
планирование процессов.
6.7.
Интерфейс
Файловая система
/proc/interrupts
procfs -
это виртуальная файловая система, которая
существует только в памяти ядра и обычно монтируется на каталог
Чтение или запись файлов в файловой системе
procfs
/proc.
приводит к вызовам
функций ядра, которые имитируют чтение или запись обычных файлов. Ха
рактерный пример
-
файл
/proc/intem1pts,
который содержит статистику,
связанную с прерываниями в системе.
Ниже приведен пример вывода из этого файла на однопроцессорном персо
нальном компьютере с двумя процессорами.
•
ID-.. ------------.-.--... ---.-.... -.-----.-.-.-------.---.. ---.---.. ---.. -. -----.---.
t.\.1пux ...... .. .. . ...... .
1
CPU0
CPUl
9
3
о
о
о
о
о
о
о
1:
6:
8:
9:
10 :
11 :
12 :
14 :
15:
24:
25 :
о
о
36586
123 08
] 6:
о
о
27 :
28 :
17773575
8537896
22966247
3567412
29:
о
о
о
32
о
о
15
о
о
о
о
30 :
20576365
о
NMI :
о
о
LOC : ~019558061 1070751773
SPU :
О
О
PMI :
о
о
I WI :
199664
251886
RTR :
о
о
43403577
RES :
36422980
CAL :
7991667
1712248
TLB:
402860
409492
Т RМ :
о
о
THR :
DFR:
о
о
о
о
МС Е :
о
о
МСР :
30468
30468
ERR :
MIS :
PIN :
event
NPI :
PIW :
1:111а (, . Ofipafi111 i-:1 щ1t·р1.11ш11111i
I O- APIC
1 - edge
i 80 42
I O-APIC
6- edge
iloppy
I O- APIC
8-edge
r tc0
I O-APIC
9- fas t e oi
a c pi
I O-APIC 1 0- fasteoi
v irtio2
IO-APIC 11 - fasteoi
uhci hcd : usЫ
IO-APIC 12-edge
i8042
IO-APIC 14 ~e ctge
ata_piix
IO-APIC 15 -e dge
ata_piix
PCI - MSI 65536 - edge
virtiol -config
PCI-MSI 65537-edge
virtiol-virtqt.Eues
PCI-MSI 49152-edge
virtio0 -config
PCI - MSI 49153 - edge
virtio0 - input . 0
PCI-MSI 49154-edge
virtio0-output.0
PCI-MSI 98304-edge
virtio3 - config
Pcr~мsr 98305 - edge
v irtio3 - req.0
Non - maskaЫe interrupts
Local timer interrupts
Spurious interrupts
Performance monitoring interrupt s
IRQ work interrupts
APIC ICR read retries
Rescheduling interrupts
Function call interrupts
TLB shootdowns
Thermal event interrupts
Threshold APIC in t err up ts
De ferred Err or APIC i nte rrupts
Machi ne che ck exceptions
м·achine chec k polls
о
о
о
о
Pos t e d - i n t e r rupt notificat i o n
о
о
о
о
Nes t ed p o s ted- interrupt e v ent
Po s t ed- in t err upt wakeup event
Первый столбец содержит номер линии
IRQ.
Линии
IRQ
для которых не
установлен обработчик, не отображаются. Во втором столбце указывается
общее количество полученных прерываний по данной линии
IRQ.
На много
процессорных платформах здесь будет отображено несколько столбцов (по
•
..--.-------------.. --.---..--_._--------------.------.. ---.. --.----.. --.----.---.--ID
Ядро
l,inux
...................... n.inux
числу процессоров), в которых указывается общее количество прерываний
для каждого процессора.
GleЫaravel .tt p
о
- roo\@85.193.80.192:22 - Bitv,se xterm - root@916661-ca932 16: -
Рис.
6.1.
Интерфейс
х
lproclinterrupts
В следующем столбце (номер столбца зависит от количества процессоров,
если процессор один , то это 3-ий столбец, если два
-
4-ый и т.д.) указы
вается контроллер прерываний, обрабатывающий данное прерывание. Зна
чение
XT-PIC
соответствует стандартному программируемому контроллеру
прерываний компьютера IВМ РС. Для систем, оснащенных устройством
APIC,
1/0
для большинства прерываний в качестве контроллера прерываний бу
дет указано значение
10-APIC-level или 10-APIC-edge. И,
наконец, в послед
нем столбце отображается имя устройства, связанного с прерыванием. Это
имя передается в виде параметра
devname функции request_irq(), как гово
IRQ совместно используется несколь-
рилось выше . Если какая-то из линий
•
ID- ------------"" -""""" ----"----. ----.--. ----------.-----------------------------.. -.
1 , ,ана
n..1nux ................. .
кими устройствами (как
IRQ4
(1. Ofipaбo 11,а 11pt•111,шa1111ii
в нашем примере), то в последнем столбце
будут перечислены имена всех зарегисrрированных для данной линии
IRQ
устройств.
··;··············································································-ID
Глава
7.
Таймеры и отслеживание
хода времени
Sl11po l,i1111x
7.1.
....................... n.1nux
Учет времени в ядре
Ядро помимо всего прочего, занимается также и учетом времени. Причем
учет времени является одной из важнейших функций ядра, поскольку в ядре
есть множество функций, которые запускаются по сигналам времени, а не
по событиям. Другими словами, есть функции , которые запускаются, если
произошло какое-то событие . А есть функции, которые вызываются по жест
кому графику, например,
100
раз в секунду. Ядро может запланировать ра
боту на выполнение в момент времени, который наступит спустя
1 секунду
относительно текущего момента .
Говоря о планировании времени , нужно разделять понятия абсолютного и
относительного времени . Если нужно выполнить некоторую работу в буду
щем, скажем, спустя
1 минуту
относительно текущего момента
-
учет абсо
лютного времени не нужно, только отн о сительного , то есть относительно
текущего момента нужно отсчитать
60
секунд. А вот е сли нужно выполнить
работу в определенное время, например, в
23 :00, тогда нужен учет абсолют
ного времени.
аа-
•
-------------------------------.----.----------.---... -....... -............... -..
1
~lnux ................. .
1
1,11\, 1
7 ·1а1нн·р1.1
11 111 ('. l(' Жllll:11111(' \11, 1:1 IIJl('\1('1111
Имеются отличия в реализации обработчиков событий, возникающих пери
одически, и тех, которые планируются на выполнение ядром в некоторый
фиксированный момент времени в будущем. События, возникающие пе
риодически (скажем, каждые
50
мс), генерируются системным таймером.
Последний представляет собой программируемое аппаратное устройство,
которое генерирует аппаратные прерывания с фиксированной частотой. В
обработчике этого прерывания, которое называется прерыванием от тайме
ра
(timer interrupt), обновляется значение системного времени
и выполняют
ся периодические действия. Системный таймер и его прерывания являются
основной движущей силой, отвечающий за работу операционной системы
Linux.
Также мы . поговорим о динамических таймерах
(dynamic timers) ___:
средствах, позволяющих планировать события, которые выполняются один
раз, после истечения некоторого интервала временц .
С точки зрения компьютера концепция времени является неопределенной.
Чтобы получать информацию о текущей дате и управлять системным вре
менем, ядро должно взаимодействовать с системным аппаратным обеспече
нием. Данное "железо" содержит системный таймер, используемый ядром
для измерения прошедшего времени. Внутри системного таймера находит
ся кварцевый резонатор, обеспечивающий очень точное значение периода
вырабатываемых импульсов. Такой же резонатор используется в цифровых
электронных часах или тактовом генераторе процессора. Системный тай
мер вырабатывает эти импульсы с заранее заданной частотой, на
зываемой частотой импульсов. Как только истекает период очередного
импульса, процессору посылается прерывание от таймера, в результате чего
вызывается специальный обработчик прерывания.
Ядру известна частота импульсов системного таймера, поэтому оно может
вычислить интервал времени, прошедший между двумя прерываниями от
таймера. Данный интервал времени между двумя импульсами системного
таймера называется периодом следования импульсов и измеряется в долях
секунды и равен обратному значению частоты системного таймера. Абсо
лютное значение времени соответствует текущему значению времени суток
и очень важно для работы пользовательских приложений. Ядро в состоянии
отследить это время просто потому, что оно обрабатывает прерывания от
таймера. В ядре предусмотрено семейство системных функций, позволяю
щих пользовательским приложениям получать информацию о дате и време
ни дня.
Время непрерывной работы системы
(system uptime)
является относитель
ным и отсчитывается от момента последней перезагрузки системы. Оно
•
•
........ ........... .. ..................... ... ..... ... .............................. . .
и ' IIНI
1.ill 11 \
......... . ............. r.l1nux
используется как в системных, так и в пользовательских приложениях . Во
многих программах требуется знать интервал времени , прошедший между
двумя событиями. Проще всего его измерить как разность между двумя зна
чениями времени непрерывной работы системы, считанными в нужные мо
менты.
Прерывания от таймера очень важны для управления работой всей опера
ционной системой. Существует большое количество функций ядра, которые
система запускает в зависимости от хода времени. Также ряд функций запу
скается периодически по сигналу прерывания от таймера, например , обнов
ление значени.й времени, обновление абсолютного значения времени, запуск
обработчиков всех динамических таймеров и т.д . Многие из этих функций
выполняются при каждом прерывании таймера, то есть работа делается с
частотой системного таймера.
7 .2.
Таймеры ядр а
Когда нам нужно запланировать действия на позднее время без блокирова
ния текущего процесса до наступления момента времени , лучшим инстру
ментом являются таймеры ядра. Такие таймеры используются для планиро
вания выполнения функции в определенное время в будущем , основываясь
на тактовых тиках, и могут использоваться для различных задач
-
напри
мер, опрос устройства путем проверки его состояния через регулярные про
межутки времени, когда оборудование не может генерировать прерывания .
Другим типичным использованием таймеров ядра является отключение
двигателя
HDD
или завершение другой длительной операции выключения .
В таких случаях задержка возвращения из
c/ose
создала бы ненужные (и
неожиданные) трудности для прикладной программы. Наконец, само ядро
использует таймеры в ряде ситуаций , включая реализацию
schedule_timeout.
Таймер ядра является структурой данных , которая инструктирует ядро для
выполнения заданных пользователем функций с заданным пользователем
аргументом в заданное пользователем время . Реализация находится в
timer.h>
и
kemel/timer.c
<linux/
и более подробно поговорим об этом далее в этой
главе.
Функции, которые были запланированы для запуска, почти наверняка не ра
ботают, пока выполняется процесс , который их регистрирует. Вместо этого ,
они запускаются асинхронно. До сих пор все, что мы сделал и в наших при-
111-....... --... --....·... -... -... -... --... --... -.. -... -.... --........ -........ -... -.'
t.\.1пux .................. .
мерах драйверов
-
1
1, 11 1. 1 7
1а11\н· р1.111111cн· :.i-i111a1111t· ,н 1а 111н· \lt·1111
это работа в контексте процесса, выполняющего систем
ные вызовы. Когда запущен таймер, процесс, который запланировал его, мо
жет спать, выполняться на другом процессоре, или, что вполне возможно,
вообще завершиться.
Такое асинхронное выполнение напоминает то, что происходит, когда вы
полняется аппаратное прерывание. В самом деле, таймеры ядра работают
как результат "программного прерывания". При запуске в атомарном кон
тексте этого рода на ваш код налагается ряд ограничений. Функции таймера
должны быть атомарными всеми способами, но есть некоторые дополни
тельные вопро~ы, вызванные отсутствием контекста процесса. Теперь мы
введем эти ограничения; они будут рассматриваться снова в нескольких
местах в последующих главах. Повторение делается потому, что правила для
атомарных контекстов должны усердно соблюдаться, или система окажется
в тяжелом положении. Некоторые действия требуют для выполнения кон
текст процесса.
Когда вы находитесь за пределами контекста процесса (то есть в контексте
прерывания), нужно соблюдать следующие правила:
•
Не разрешен доступ к пользовательскому пространству. Поскольку от
сутствует контекст процесса, нет пути к пользовательскому пространству,
связанному с любым определенным процессом.
•
Указатель
current не
имеет смысла в атомарном режиме и не может быть
использован, поскольку соответствующий код не имеет связи с процес
сом, .который был прерван.
•
Не может быть выполнено засыпание или переключение. Атомарный код
не может вызвать
schedule
или какую-то из форм
wait_event
и не может
вызвать любые другие функции, которые могли бы заснуть. Например,
вызов
kmalloc( ... , GFP_КERNEL)
идет против правил. Семафоры также
не должны быть использованы, поскольку они могут спать.
Код ядра может понять, работает ли он в контексте прерывания, вызова~
функции in_inteпupt( ), которая не имеет параметров и возвращает ненуле
вое значение, если процессор в настоящее время работает в контексте пре
рывания, аппаратного или программного. Функцией, связанной с
inteпupt(), является
in_atomic().
in_
Она возвращает ненулевое значение, когда
переключение не допускается; это включает в себя аппаратный и программ
ный контексты прерывания, а также любое время, когда удерживается
'----........................................................................... ··ID
И . 1ре1
l .illll\
....................... n.1nux
спин-блокировка. В последнем случае,
current может быть действительным,
но доступ к пользовательскому пространству запрещен, поскольку это мо
жет привести к переключению. Каждый раз , когда вы используете
rupt(),
in_interin_atomic() тем, что вы
объявлены в <asm/hardirq.h>.
следует рассмотреть вопрос, не является ли
действительно имеете в виду. Обе функции
Еще одной важной особенностью таймеров ядра является то, что задача мо
жет перерегистрировать себя для запуска снова в более позднее время. Это
возможно , потому что каждая структура
timer_list не
связана со списком ак
тивных таймеров перед запуском и , следовательно, может быть немедленно
перекомпонов·ан~ где угодно. Хотя переключение на одну и ту же задачу сно
ва и снова может показаться бессмысленной операцией, иногда это бывает
полезно. Например, это может быть использовано для реализации опроса
устройств.
Кроме того, стоит знать, что в многопроцессорных системах таймерная
функция (функция, запускаемая таймером) выполняется тем же процессо
ром, который ее зарегистрировал для достижения лучшего расположения
кэша, когда это возможно . Поэтому таймер, который перерегистрирует себя,
всегда запускается на том же процессоре.
7 .3. API
таймера
Ядро предоставляет драйверам ряд функций для декларации , регистрации
и удаления таймеров ядра. Ниже приводится фрагмент кода, показывающий
основные стандартные рлоки:
#include <linux /timer.h>
struct timer list
/* . .. * /
unsigned long expires ;
void (*function) (unsigned l o ng) ;
unsigned long data ;
};
void init_ timer(struct timer_list *timer) f
struct timer_list TIMER_INITIALIZER( function , _expires ,
...
void add_timer (struct timer_list * timer) ;
int del_timer(struct timer_list * timer) ;
. . . -... --..
data );
•
---. ---. ---....... . -... -. -. -... --... -... --.. ---.. --... -... -... --.. -.. -.
l . 1 ана 7.
n..inux ................. .
Taii,1cpы 11 OIC. ICЖIIВallllC \О, Щ вpc\lCIIII
Структура данных включает в себя больше полей, чем показано в нашем
фрагменте , но продемонстрированные три поля предназначены для доступа
снаружи кодом таймера. Поле
expires
представляет значение
таймер ожидает для запуска; в это время функция
данными
data
jiffies, которое
_ function вызывается с
в качестве аргумента . Если нужно передать много объектов в
аргументе, можно собрать их в единую структуру данных и передать указа
тель, приведя к
unsigned long,
это безопасная практика на всех поддержива
емых архитектурах и она довольно распространена в управлении памятью.
Значение
expi~es
не является типом
jiffi.es_ 64,
поскольку не ожидается , что
таймер сработает очень далеко в будущем и на 32-х разрядных платформах
64-х разрядные операции медленны.
Структуры должны быть проинициализированы перед использованием.
Данный шаг гарантирует, что все поля правильно настроены, в том числе
те, которые не видимы для вызывающего. Инициализация структуры может
быть осуществлена с помощью вызова
init_timer или
присвоением
TIMER_
INIТIALIZER статической структуре, в соответствии с вашими потреб
ностями . После инициализации , но перед вызовом
add_timer(),
можно из
менить три открытых поля . Чтобы отключить зарегистрированный таймер
до его истечения, вызовите функцию
примера,
/proc/jitimer
del_timer(). Модуль jit
включает файл
(для "только по таймеру") , который возвращает стро
ку заголовка и шесть строк данных . Строки данных показывают текущее
окружение, где выполняется код; первая создается файловой операцией
остальные
-
read,
по таймеру. Следующий вывод был записан во время компиля
ции ядра:
ca t /proc/ji t imer
t i me
de l ta in irq
33565837
о
о
33565847 10
1
33565857 10
1
33565867 1 0
1
33565877 10
1
33565887 10
1
В этом выводе, поле
delta
time
pi d
1269
1271
1 273
1273
1274
1274
cpu command
о
cat
sh
о
о
сррО
о
сррО
о
cc l
ccl
о
является значениемji.ffiеs, когда код запускается,
является изменением
jiffies
относительно предыдущей строки,
это логическое значение, возвращаемое
•
inirq in_interrupt, pid и command относят-
·-··-·-····--------···------ ------------------··--····--······-········-·········· -
И IIНI
I
................... . ... r.t.iпux
illll\
ся к текущему процессу и ери является номером испол ьзуемого процессора
(всегда О на однопроцессорных системах) .
Если вы прочитаете
/proc/jitimer при
выгрузке системы , вы обнаружите , что
контекстом таймера является процесс О , задача простоя
вается
"swapper"
(idle), которая
назы
("планировщик своппинга") в основном по историческим
причинам .
Таймер используется для генерации данных
дые
1О
/proc/jitimer по ум олчанию
каж
тикав, но при загрузке модуля можно изменить значение , установив
параметр
tdelay (timer delay, задержка таймера) .
Следующий · отрывок кода показывает часть jit, связанную с таймером
jitimer.
Когда процесс пытается прочитать наш файл , мы устанавливаем тай
мер следующим образом:
unsigned l ong j = jiffies;
/* запо лняе м данные для нашей таймерной
data - >p re vjiffies = j ;
data - >buf = buf2 ;
data->loops = JIT ASYNC LOOPS ;
функции* /
/* ре г истрируем таймер*/
data - >timer . data = (unsigned long)data ;
data - >timer . function = jit_timer_fn;
data - >timer .e xpires = j + tdelay ; /*параметр* /
add_ time r ( &data - >timer) ;
/*
ждем заполнения
буфера* /
wait_event_interruptiЬle(data - >wait,
API
!data- >loops) ;
таймера включает в себя несколько больше функций, ч ем те , которые
введены выше . Следующий набор завершает список предложения ядра :
int mod_timer(struct timer list *timer , u nsigned l o ng expires) ;
Данная функция осуществляет обновление времени истечения срока тай
мера. Функция
mod_ timer()
может быть вызвана при неактивных таймерах,
также, как обычно используется
add_timer().
Рассмотрим следующую функцию:
•
llt- -----------. --------------------------------------------------------------------.
1
n.1nux ................. .
1, 11 \, 1
1 1.111\lt' lll •I
II IIICH' Жlll\atlllt' \111:1 Bpt'\1('1111
int del_timer_ sync(struct timer_list *timer);
Работает как ц
del_timer(),
но также гарантирует, что когда она вернется,
таймерная функция не запущена на каком-то процессоре. Данная функция
используется, чтобы избежать состояний состязания на многопроцессор
ных системах, и аналогична
del_timer()
на однопроцессорных ядрах. Этой
функции в большинстве ситуаций следует отдавать предпочтение перед
del_
Она может "заснуть", если вызывается из неатомарного контекста,
timer().
но наход~тся в активном ожидании в других ситуациях.
Будьте очень осторожны, вызывая
ровок,
-
del_timer_sync()
при удержании блоки
если таймерная функция попытается получить ту же блокировку,
система может заблокироваться. Если эта таймерная функция перерегистри
рует себя, вызывающий должен сначала убедиться, что эта перерегистрация
не произошла ; обычно это достигается установкой флага
"shutting down"
("выключить") , который проверяется таймерной функцией .
Следующая функция
- timer_pending():
int timer_pending(const struct timer list * timer) ;
Возвращает истину или ложь, чтобы показать, будет ли таймер в настоящее
время запланирован для запуска, чтением одной из скрытых полей струк
туры.
7.4.
Реализация таймеров ядра
Обычно вам не нужно знать , как реализованы таймеры ядра, чтобы их ис
пользовать. Но их реализация интересна и стоит посмотреть на их внутрен
ности.
Реализация счетчиков была разработана, чтобы соответствовать следующим
требованиям и предположениям:
•
•
Управление таймером должно быть максимально легким .
··················································································-
Я , tро (,i1111x
•
___ ___ ...... _______ .... n.inux
Конструкция должна позволять увеличивать количество активных тай
меров.
•
Большинство таймеров истекают в течение нескольких секунд или, самое
большее, минут, в то время как таймеры с длительными задержками до
вольно редки.
•
Таймер должен работать на том же процессоре, который его зарегистри
ровал.
Решение, созданное разработчиками ядра, основано на копии структуры
данных для каждого процессора. Структура
timer_list включает в себя ука
base. Если base является
затель на такую структуру данных в своем поле
NULL, таймер
не запланирован для запуска ; в противном случае, ук-азатель
говорит, какая структура данных (и , следовательно, какой процессор) за
пускает его.
Всякий раз, когда код ядра регистрирует таймер (через
add_timer или mod_
timer), операции в конечном итоге выполняются internal_add_timer (в kemeU
timer.c), которая, в свою очередь, добавляет новый таймер в двусвязный спи
сок таймеров в рамках "каскадной таблицы", связанной с текущим процес
сором.
Каскадные таблицы работают так : если таймер истекает в следующих тиках
от О до
255,
он добавляется в один из
256
списков, посвященных таймерам
малого диапазона, используя самые младшие биты поля
expires.
Если он истекает дальше в будущем (но до
16384 тиков), он добавляется в
expires. Для таймеров истека
ющих еще позже, тот же прием используется для битов 15-20, 21-26 и 2731. Таймеры с полем времени окончания еще дальше в будущем ( что может
один из
64
списков на основе битов
9-14
поля
случиться только на 64-х разрядных платформах) делятся на задержки со
значением
Oxffffffff и таймеры
с
expires
в прошлом планируются для запуска
в следующем тике таймера (таймер , который уже истек, иногда может быть
зарегистрирован в ситуациях высокой нагрузки, особенно если вы работаете
с вытесняющим ядром) .
После запуска
_run_timers, он
запускает все отложенные таймеры на теку
щий тик таймера . Ecлиjif.fies в настоящее время является кратной
256,
функ
ция также заново делит один из списков таймеров следующего уровня на
256
списков короткого диапазона, возможно каскадируя один или несколь
ких других уровней также в соответствии с битовым представлениемjif.fiеs .
•
118----- -- -------. --..... ----- -- ------ --- --..... -- ---- --....... -- ----- -- ------. ---- --·
n.inux .................. .
[ ; ~ава
7.
Taiiмcp1,1 и OICJ ICЖIIB.НIИC Xl))ta нрсмс1111
Это подход, хотя и чрезвычайно сложный на первый взгляд, выполняется
очень хорошо как с несколькими таймерами, так и с большим их числом.
Время, которое необходимо для управления каждым активным таймером,
не зависит от количества уже зарегистрированных таймеров и ограничено
несколькими логическими операциями над двоичным представлением поля
expires.
Накладным расходом, связанным с этой реализацией, является па
мять для
64
512
заголовков листов
(256
краткосрочных списков и
списков более длительных диапазонов), то есть
Функция
_run_timers,
как показано
/proc/jitimer,
4 Кб
4
группы из
памяти.
будет запущена в атомар
ном контексте. _Кроме уже описанных ограничений, это приносит интерес
ную особенность: таймер истекает только в заданное время, даже если вы
не работаете на вытесняющем ядре и процессор занят в пространстве ядра.
Вы можете видеть, что происходит, когда вы читаете
режиме и
/proc/jitimer с высоким приоритетом.
/proc/jitbusy в
фоновом
Хотя система кажется прочно
заблокированной системным вызовом с активным ожиданием, таймеры ядра
все же работают нормально.
Таймер ядра далек от совершенства, он страдает от дрожания и других арте
фактов, вносимых аппаратными прерываниями, а также другими таймерами
и другими асинхронными задачами. Хотя таймер, связанный с простым циф
ровым вводом/выводом, может быть достаточен для таких простых задач,
как запуск шагового двигателя или другой любительской электроники, это
обычно не подходит для производственных систем в промышленных усло
виях. Для выполнения таких задач вам, скорее всего, придется прибегнуть к
расширению ядра для реальнQго времени.
•.......................... -...·.· ............................--....................tlll
•
Глава
8.
Управление памятью
Sl ,tJIO J,i1111x
...................... n.1nux
Подсистема работы с оперативной памятью в
достаточно многогран
Linux -
ная конструкция. Чтобы разобраться в ее деталях, нужно целенаправленно
погрузиться в тему, с обязательным чтением исходников ядра, но это нужно
не каждому. Для разработки и эксплуатации серверного программного
обеспечения важно иметь хотя бы базовое представление о том, как она ра
ботает, но, как показывает практика, не многие администраторы и разработ
чики обладают подобными знаниями.
8.1.
Какая бывает память?
8.1.1.
Физическая и виртуальная
Начнем с самих азов. Представим, что у нас есть сервер (без разницы
физический или
VDS),
скажем, с
16 Гб оперативной памяти . Что это значит?
Именно столько в нем есть физической памяти. Для тех, кто забыл: физи
ческая память (или "ОЗУ 1 ",
"RAM2",
"оперативка")
-
это энергозависимая
память, установленная в компьютере. Для ее работы требуется непрерывный
поток электричества. Перебои с электропитанием или внезапное выключе-
..
2
Оперативное запоминающее устройство
Random Access Memory
•
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . .
1т111а Х . Yнp,111. ll'Ш1l' ШIMSI 11,Ю
r.t..inux ................. .
ние компьютера могут привести к стиранию хранящихся в ней данных. Кро
ме того , эта память является линейно адресуемой. Другими словами, зна
чения адресов памяти увеличиваются линейным образом. На физическом
компьютере оперативная память представляет собой набор модулей
( 1 или
более) памяти, установленных в слоты на материнской плате компьютера
(рис.
8.1).
Рис.
8.1.
Оперативная па.мять
Задача распределения доступных ресурсов между исполняемым программ
ным обеспечением, в том числе и физической памяти , лежит на плечах
операционной системы, в нашем случае
Linux.
Для обеспечения иллюзии
полной независимости , она предоставляет каждой из программ свое неза
висимое виртуальное адресное пространство и низкоуровневый интерфейс
работы с ним. Такая схема избавШ!"ет их от необходимости знать друг о дру
ге, размере доступной физической. памяти и текущей ее занятости.
Адреса в виртуальном пространстве процессов называют логическими.
Для отслеживания соответствия между физической и виртуальной памятью
ядро
Linux
использует иерархический набор структур данных в своей слу
жебной области физической памяти (только оно работает с ней напрямую),
а также специализированные аппаратные контуры, которые в совокупности
называют
8.2 показано место MMU в структуре управления
TLB на данном рисунке - это буфер преобразований
(Translation Lookaside Buffer). О нем мы еще поговорим.
MMU 3 .
На рис.
памяти. Аббревиатура
•
Memory Management Unit
.
.........."-.""" .. "" ... ""." "" -.. "" .... ". -... "" .. """. -"... "" .. """ .. """." "". -"" "-."" 1111
И 1ро
...................... n.,пux
l .i,111,
Процессор
Фto> . ,..pect1
Фма. '-Afl8C
Фма. "-АР8С
Ф,,3 _ '-АJ)К
12
13
'4
Физи чески й адрес
ФIQ. ,..pecflN
ОЗУ
Рис.
8.2. MMU и
физическая память
Следить за каждым байтом памяти в отдельности было бы накладно,
поэтому ядро оперирует достаточно большими блоками памяти
ми, типовой размер которых составляет
4 килобайта (4096
-
страница
байт).
На аппаратном уровне, как правило, есть поддержка дополнительного уров
ня абстракции в виде "сегментов" (?Перативной памяти, с помощью которых
можно разделять программы на части. В отличие от других операционных
систем, в
Linux
она практически не используется
-
логический адрес всегда
совпадает с линейным ( адресом внутри сегмента, который сконфигурирован
фиксированным образом).
Физическая
страницы
память разделяется на
(page).
отдельные
фрагменты,
называемые
Практически вся внутренняя системная обработка памяти
производится на постраничной основе . Размер страницы зависит от исполь
зуемой архитектуры. Обычно размер страницы равен
asm/page.h
определена константа
PAGE_SIZE,
4096
байт или
4
Кб. В
задающая размер страницы
для используемой архитектуры. Для 64-битных систем нужно заглянуть в
файл
page_64.h.
Если посмотреть на адрес памяти (без разницы какой - виртуальный или фи
зический), можно увидеть , что он делится на номер страницы и смещение
внутри этой страницы. Например, если используются страницы по
байт,
12 младших значащих бит являются
4096
смещением, а остальные , старшие
биты, указывают номер страницы. Если отказаться от смещения и сдвинуть
оставшуюся часть адреса вправо, результат называют номером страничного
1111-.----------------.---.----.-------.. -------.---.---------... -.. --.. -.. ----.----_,
1 1а11а Х . ~ IIJ),Ш. lt'llllt' 11а,н111,Ю
n..inux ................. .
блока
(page frame number, PFN).
Сдвиг битов для конвертации между но
мером страничного блока и адресами является довольно распространенной
операцией; макрос
PAGE_SHIFT сообщает,
сколько битов должны быть сме
щены для выполнения этого преобразования.
8.1.2.
Файловая и анонимная
У приложений существует много способов выделить себе память для тех
или иных ·нужд. Высокоуровневые языки программирования и библиотеки
часто прячут от разработчиков, какой из них в реальности использовался
и другие детали (хотя их всегда можно это узнать с помощью
strace).
Если
углубляться в особенности каждого доступного варианта, можно написать
книгу только по управлению памятью. Вместо этого предлагаем разделить
их на две, на мой взгляд, крайне важные группы по тому, какую память они
выделяют:
•
Файловой памяти однозначно соответствует какой-либо файл или его
часть в файловой системе . Первым делом в ней находится исполняемый
код самой программы. Для прикладных задач можно запросить отобра
жение файла в виртуальное адресное пространство процесса с помо
щью системного вызова
mmap() -
после чего с ним можно работать как с
любой другой областью памяти без явного чтения/записи. Что будет при
этом происходить с данными в файловой системе и что будут видеть дру
гие процессы "отобразившие" этот же файл зависит от настроек.
•
Любую другую выделенную память называют анонимной, так как ей не
соответствует никакой файл. Сюда попадают как переменные в стеке, так
и области , выделенные с помощью функций вроде
malloc (к слову, за сце
ной для выделения больших блоков памяти они обычно тоже используют
mmap
с особым набором настроек, а для всего остального
- brk/sbrk или
выдают ранее освобожденную память).
На первый взгляд отличия не выглядят чем-то особенным, но тот факт, что
области файловой памяти именованы, позволяет операционной системе эко
номить физическую память , порой очень значительно , сопоставляя вирту
альные адреса нескольких процессов , работающих с одним и тем же фай
лом , одной физической странице в памяти . Это работает прозрачно, начиная
•
...................................... ..... .................... ... ... .. .. ... .........
И , tfНI l ,illll\
...................... n.1nux
от кода запущенных нескольких копий приложений, заканчивая специально
сконструированными под эту оптимизацию систем.
8.1.3.
Вытесняемая и невытесняемая память
Суммарный объем используемой виртуальной памяти всех программ
запросто может превышать объем доступной физической памяти. При этом
в каждый конкретный момент времени приложениями может использовать
ся лишь небольшое подмножество хранимых по виртуальным адресам дан
ных. Это означает, что операционная сисrема может откладывать не исполь
зуемые в данный момент данные из оперативной памяти на жесткий диск
("вытесняя"" их из памяти), а затем при попытке к этим данным обратиться
-
скопировать обратно в физическую оперативную память. Этот механизм
официально называется
ло подразумевают
личие в том, что в
major page fault, но под просто page fault как прави
тоже его, так как minor page fault мало кого заботит (от
случае minor ядру удается найти запрашиваемые данные
уже загруженньiми в память с какой-то другой целью и обращения к диску в
итоге не происходит).
На время восстановления запрашиваемых приложением данных его выпол
нение прерывается и управление передается ядру для выполнения соот
ветствующей процедуры . Время, которое потребуется, чтобы приложение
смогло продолжить свою работу, напрямую зависит от типа используемого
жесткого диска:
•
Прочитать 4Кб данных с обычного серверного жесткого диска
занимает порядка
1О мс,
7200rpm
при хорошем стечении обстоятельств чуть мень
ше . Если вытесненных страниц оказывается много, запросто могут на
бегать заметные доли секунды (как условным пользователям, так и на
внутренних приборах, в зависимости от задачи).
клические
pagefaults,
Особенно опасны ци
когда есть две или более регулярно используемые
области памяти, которые вместе не помещаются в физическую память,
поэтому бесконечно вытесняют друг друга туда-обратно. При этом диск
вынужден делать честный
seek, что само по себе тоже может быть некста
ти . Например, если с этим же диском работает какая-либо база данных .
•
Если используется
отсутствия
SSD,
то ситуация несколько более радужная
механического
движения
примерно на порядок меньше, около
аналогичная
1 мс
операция
-
из-за
занимает
•
или ее доли, в зависимости от
•
1111··················································································
1с1а11а
ainux ................. .
Х. У11рав~ 1с1111с шtl\HJ I ыо
типа и конкретной модели диска. Но годы идут, а
SSD
так и остаются
нишевым, компромиссным продуктом по цене-объему. Если настольные
варианты
SSD стали дешевле , то цены на серверные дешевле не стали. Да
и нужно учитывать не только цену одного гигабайта хранимой информа
ции, но и ресурс .
Примечание. Для сравнения: если бы страница уже была в па
мяти, то при обращении к ней счет шел бы на сотни наносекунд .
Это почти на
4
порядка быстрее, чем
Примечание о ресурсе
SSD.
pagefault, даже
на
SSD .
В своем распоряжении автор этой
книги имеет два ноутбука. Первый покупался очень давно и с
целью повышения производительности на него был установлен
SSD
от Кingston на
480
Гб. Думаю, по размеру вы догадались,
что стоил он тогда, наверное, дороже , чем весь ноутбук. Так
вот этот
SSD
проработал чуть более года. На втором ноутбуке
был изначально установлен
проработал свои
3-4
SSD Samsung Evo,
который честно
года, а потом при запуске система начала
"ругаться", что его срок вышел . Никаких ошибок S.M.A.R.Т. не
показывал, просто один из счетчиков
ных часов
-
-
количество отработан 0
превысил запрограммированное значение. Видимо,
даже сам производитель не ожидал, что он столько проработает.
Пришлось заменить его новый во избежание потерь информа
ции. К слову, оригинальный жесткий диск на первом ноутбуке до
сих пор отлично работает. Вот и посчитайте стоимость н,е только
гигабайта информации при покупке нового устройства , но и то ,
что за один и тот же срок
HDD
SSD
вы поменяете несколько раз, а
будет работать. Поэтому далеко не все администраторы
на серверах спешат переходить на
SSD
(хотя на дворе уже
год), а предпочитают проверенные и более ресурсные
2023
HDD. Тем
более, если речь идет о сервере, где частота обращений к диску
в разы выше, чем на пользовательском ноутбуке.
Стоит отметить, что с точки зрения приложения все это прозрачно и являет
ся внешним воздействием, то есть может происходить в самый не подходя
щий, с точки зрения решаемой им задачи, момент.
Думаю, понятно, что приложения , которым важна высокая производитель
ность и стабильное время отклика, должны избегать pagefault'oв всеми
доступными методами, к ним и перейдем .
•
........... ..... ....... ........... .. ... ............................................ .
Я , {ро
l,inux
_____ _____ ___ __ . ____ ___ n.inux
8.1.4. Разные типы
ОС
адресов
как уже было отмечено, является системой с виртуальной памя
Linux,
тью, а это означает, что адреса, видимые пользовательскими программами,
не соответствуют напрямую физическим адресам , используемым оборудо
ванием.
Виртуальная память вводит слой абстракции, позволяющий ряд приятных
вещей. Так, при использовании виртуальной памяти программы, выполняю
щиеся в системе, могут выделить гораздо больше памяти, чем доступно фи
зически; более того , даже один процесс может иметь виртуальное адресное
пространство больше физической памяти системы. Виртуальная память по
зволяет также программе использовать разные ухищрения с адресным про
странством процесса , в том числе отображение памяти программы в память
устройства.
ОС
Linux
имеет дело с несколькими типами адресов , каждый со своей соб
ственной семантикой. К сожалению , в коде ядра не всегда четко понятно, .ка
кой именно тип адреса используется в каждой ситуации , так что разработчик
должен быть осторожным.
Разберемся , какие типы адресов используется в
Linux:
• Пользовательские виртуальные адреса - •обычные адреса, видимые
программами пространства пользователя. Такие адреса могут быть 32
или 64 разрядными , в з ависимости от архитектуры (не стоит забывать,
что Linux может запускаться на разнообразных мини-компьютерах,
встроенном оборудовании , которое все еще 32-битное, в отличие от пер
сональных компьютеров и серверов , которые уже давно стали 64-битны
ми). Каждый процесс имеет свое виртуальное адресное пространство.
•
Физические адреса
-
адреса, которые используются между процессо
ром и памятью системы. В зависимости от архитектуры, они также могут
быть
•
32
или
64 разрядными.
Адреса шин
-
адреса, используемые между периферийными шинами и
памятью. Зачастую они такие же, как физические адреса, используемые
процессором, но это не обязательно так. Некоторые архитектуры мо
гут предоставить бл ок управления па.1v1ятью ввода/вывода (1/0 memory
management unit, IOMMU), который переназначает адреса между шиной и
оперативно й памятью. IOMMU может сделать жизнь легче несколькими
способ ам и (например , делая разбросанный в памяти буфер выгля дящи ~
1 1 8 ----·-----------··--···- -·-- ------·---·---···--- -- --·---·· --···-··- -·· ·- -··- ---··'
1 1 1ава Х . Y111J:шлt•1111t• ш1м1111.ю
n.1nux ................. .
непрерывным для устройства) , но программирование
IOMMU
является
дополнительным шагом, который необходимо выполнить при настройке
DMA операций.
•
Конечно , адреса шин сильно зависят от архитектуры.
Логические адреса
-
составляют обычное адресное пространство ядра.
Такие адреса отображают какую-то часть основной памяти и часто рас
сматриваются как физические адреса. В большинстве архитектур логиче
ские адреса и связанные с ними физические адреса отличаются только на
постоянное смещение. Логические адреса обычно хранятся в перемен
ных типа
unsigned long
или
void *.
Память, возвращаемая
kmalloc,
имеет
логичеСКf!Й адрес ядра.
•
Виртуальные адреса
-
похожи на логические адреса тем, что они явля
ются отображением адреса пространства ядра на физический адрес. Сто
ит отметить, что виртуальные адреса ядра не всегда имеют линейную,
взаимно-однозначную связь с физическими адресами, характеризующую
логическое адресное пространство. Все логические адреса являются вир
туальными адресами ядра, но многие виртуал ьные адреса ядра не явля
ются логическими адресами. Так, например, память, выделенная
vmalloc,
имеет виртуальный адрес (но без прямого физического отображения).
Функция
kmap ( описываемая
далее в этой главе) также возвращает вир-
туальные адреса. Виртуальные адреса обычно хранятся в переменных
указателей.
На рис.
8.3 показаны типы адресов,
используемые в
Linux.
При этом не окра
шена область физической памяти , а стрелки показывают отображение стра
ницы .
В иртуальные
адреса
Верхняя
nамять
;
Процесс
Ниж няя
память
Логические
адреса
Процесс
Рис.
8.3.
Типы адресов в
Li11ux
,. ...-.. -... -... --.. --.... -................ --.. --..... -.......... -..... ·... --.. --.·tlll
.
....................... n..,пux
Ящю (,i1шх
8.2.
Методы управления подсистемой памяти
8.2.1.
Подкачка и невытесняемая память
Для работы с памятью в
Linux (как и в других UNIХ-подобных системах) ха
рактерно такое явление как "страничный обмен" (paging). Оно заключается в
том, что ядро выделяет процессам столько памяти, сколько им необходимо.
В том смысле , чтобы ее (памяти) всегда хватало. Это достигается за счет
расширения физической памяти за счет виртуальной, т. е. "подкачки". По
скольку выполнение процессов должно происходить в реальной физической
памяти, то ядро постоянно перемещает страницы памяти процессов между
физической и виртуальной памятью. Забегая вперед, следует отметить, что
в виртуальной памяти хранятся "неактивные" страницы, которые не задей
ствованы процессом в данный момент, но необходимые ему для полноцен
ной работы впоследствии.
С файловой памятью все просто: если данные в ней не менялись, то для ее
вытеснения делать особо ничего не нужно
-
просто перетираешь, а затем
всегда можно восстановить из файловой системы.
С анонимной памятью такой трюк не работает: ей не соответствует никакой
файл , поэтому чтобы данные не пропали безвозвратно., их нужно положить
куда-то еще. Для этого можно использовать так называемый "swар"-раздел
или файл. Можно, но на практике не нужно. Если
swap
выключен, то ано
нимная память становится невытесняемой, что делает время обращения к
ней предсказуемым.
Может показаться минусом выключенного
swap,
что, например, если у при
ложения утекает память, то оно будет гарантированно зря держать физиче
скую память (утекшая не сможет быть вытеснена). Но на подобные вещи
скорее стоит смотреть с той точки зрения, что это наоборот поможет раньше
обнаружить и устранить ошибку.
8.2.2.
Системный вызов
mlockO
По умолчанию вся файловая память является вытесняемой, но ядро
..
Linux
,
предоставляет возможность запрещать ее вытеснение с точностью не только
до файлов , но и до страниц внутри файла .
. ---- --- ----- -- -- --- ................ -.... --·· ... ---- ....... ···-. ------. -----. ___
1J 1aiш Х. У11равJ1с1tис 11а 1шп ыо
n.1nux .. ............ _·_..
Для этого используется системный вызов
памяти, полученной с помощью
mlock()
mmap . Если
на области виртуальной
спускаться до уровня систем
ных вызовов не хочется, рекомендую посмотреть в сторону консольной ути
литы
vmtouch,
которая делает ровно то же самое , но снаружи относительно
приложения.
Несколько примеров, когда это может быть целесообразно :
•
У приложения большой исполняемый файл с большим количеством вет
влений, некоторые из которых срабатывают редко, но регулярно. Такого
стоит избегать и по другим причинам , но если иначе никак , то, чтобы не
ждать лишнего на этих редких ветках кода, можно запретить им вытес
няться.
•
Индексы в базах данных часто физически представляют собой именно
файл, с которым работают через
mmap, а mlock нужен
чтобы минимизи
ровать задержки и число операций ввода-вывода на и без того нагружен
ном диске(-ах).
•
Приложение использует какой-то статический словарь, например, с соот
ветствием подсетей IР-адресов и стран, к которым они относятся. Вдвой
не актуально, если на одном сервере запущено несколько процессов , ра
ботающих с этим словарем.
8.2.3.
ООМ
killer
Перестаравшись с невытесняемой памятью , нетрудно загнать операцион
ную систему в ситуацию, когда физическая память кончилась , а вытеснять
нич;его нельзя. Безысходной она выглядит лишь на первый взгляд : вместо
вытеснения память можно освободить.
Происходит это достаточно радикальными методами: послуживший назва
нием данного раздела механизм выбирает по определенному алгоритму про
цесс, которым наиболее целесообразно в текущий момент пожертвовать
-
с
остановкой пр_оцесса -освобождается использовавшаяся им память, которую
можно перераспределить между выжившими. Основной критерий для выбо
ра: текущее потребление физической памяти и других ресурсов, плюс есть
возможность вмешаться и вручную пометить процессы как более или менее
ценные, а также вовсе исключить из рассмотрения. Если отключить ООМ
•
... . -- -- -- .. -- ...... -.... --- .... ........ ................ --... --...... --.. --- . -- -.. . . .
Я ! tро
l , i11ю:
·······················a.nux
killer полностью, то
системе, в случае полного де фицита, ничего не останет
ся, как перезагрузиться.
8.2.4. cgroups
По умолчанию все пользовательские процессы наравне претендуют на поч
ти всю физически доступную память в рамках одного сервера. Это поведе
ние редко является приемлемым. Даже если сервер условно-однозадачный,
например, т<_шько отдает статические файлы по НТТР с помощью
всегда есть какие-то служебные процессы вроде
syslog
nginx,
или какой-то вре
менной команды , запущенной человеком. Если же на сервере одновременно
работает несколько production -пpoцeccoв, например, популярный вариант
подсадить к веб-серверу
memcached,
-
крайне желательно чтобы они не могли
начать "воевать" друг с другом за память в случае ее дефицита.
Для изоляции важных процессов в современных ядрах существует механизм
cgroups,
с его помощью можно разделить проu;ессы на логические группы
и статически сконфигурировать для каждой из групп сколько физической
памяти может быть ей выделено. После чего для каждой группы создается
своя почти независимая подсистема памяти, со своим отслеживанием вы
теснения, ООМ
Механизм
killer и
cgroups
прочими радостями.
намного обширнее, чем просто контроль за потреблени
ем памяти. С его помощью можно распределять вычислительные ресурсы,
"прибивать" группы к ядрам процессора, ограничивать ввод-вывод и многое
другое . Сами группы могут быть организованы в иерархию и вообще на ос
нове
cgroups
работают многие системы "легкой" виртуализации и нынче
модные Dосkеr-контейнеры .
. Но,
на мой взгляд , именно контроль за потреблением памяти
-
самый
необходимый минимум, который определенно стоит настроить, осталь!iое
уже по желанию/необходимости.
8.2.5.NUMA
В многопроцессорных системах не вся память одинакова. Если на материн
ской плате предусмотрено
N
процессоров (например,
2
или
все слоты для оперативной памяти физически разделены на
4), то обычно
N групп так, что
•
............................................................... , ............ . .... . . .
1J 1ава
n.1nux ................. .
Х . Y11p:111лt•1111t• ш1м)111,ю
каждая из них располагается ближе к соответствующему ей процессору
такую схему называют
-
NUMA 4 .
Таким образом, каждый процессор может обращаться к определенной
1/N
части физической памяти быстрее (примерно раза в полтора), чем к остав
шимся
Ядро
(N-1 )/N.
Linux
самостоятельно умеет это все определять и по умолчанию
достаточно разумным образом учитывать при планировании выполнения
процессоров и выделении им памяти. Посмотреть, как это все выглядит и
подкорректировать можно с помощью утилиты
системных вызовов, в частности
8.3.
numactl и ряда
get_ mempolicy/set_mempolicy.
Механизм распределения
доступных
LRU
Ядро старается управлять памятью таким образом, чтобы недавно исполь
зуемые процессом страницы находились в физической памяти. И в свою
очередь , "неактивные" или редко использу,емые страницы перемещаются и
хранятся в виртуальной памяти в области "подкачки". Такой механизм рас
пределения памяти называется
LRU (least recently used) -
замещение
наиболее редко используемых страниц.
Вторым важнейшим аспектом в работе памяти является использование кэш
буфера страниц. Это вытекает из работы алгоритма
LRU,
который доволь
но сложен в своей реализации. Поскольку следить за всеми обращениями к
страницам
-
это в некоторых случаях, довольно ощутимые потери в про
изводительности системы. Использование же страничного кэш-буфера куда
проще в своей реализации при тех же самых результатах. К тому же данный
подход имеет огромный модернизационный потенциал (в отличие от
LRU) и
алгоритмы анализа содержимого кэш-буфера (для определения, какие стра
ницы должны рыть перемещены из виртуальной памяти) постоянно совер
шенствуются. Что заметно сказывается на производительности и эффектив
ности управления памятью.
Когда процессу не хватает памяти , то ядро начинает искать "занятые" стра
ницы, которые можно использовать для "голодающего" процесса. Обычно
такими страницами являются те, что давно не были использованы. Ядро
-
проверяет их на предмет модификации каким-либо процессом. Для этого
существуют определенные признаки, при последнем обращении и если из-
f
Non-Uniform Memory Access, неравн омерны й
д ост уп к памяти
........ -- ........... ---- --- ... -.................... -· ............ ... -... .... ·····
Я 1 tро
1-inux
....................... rl.inux
менения были , то такие страницы помечаются ядром как "грязные"
(dirty),
т. е . такие , которые еще нужны процессам. Для повторного использования
памяти такие страницы сначала обязательно переносятся в виртуальную па
мять. Все же остальные страницы являются "чистыми". И поэтому ядро их
использует для предоставления другим или "голодающим" процессам.
Когда происходит обращение к страницам памяти, которые некоторое или
долгое время не использовались , т. е. к "неактивным" страницам, ядро вы
полняет с ними несколько важных задач:
•
Возвращает ссылки на эти страницы в соответствующей таблице
страниц;
•
Сбрасывает в нулевое значение время "неиспользования" этих страниц;
•
Помечает эти страницы как "активные" .
Со страницами, находящимися в виртуальной памяти не все так однозначно.
Дело в том , что для того, чтобы "активизировать" такие страницы, они долж
ны быть предварительно прочитаны с диска.
Системное ядро комплектуется специализированными модулями, которые
содержат алгоритмы и даже целые технологии. Посредством данных тех
нологий система доволqно эффективно "предсказывает", сколько может по
требоваться памяти при разной степени активности и загруженности про
цессов . Данные алгоритмы имеют своей целью обеспечение процессов
свободной памятью с максимальной эффективностью, т.е. так, чтобы про
цессам как можно реже приходилось простаивать в "ожидании" выгрузки
очередной страницы в свободную память. Таким образом , наблюдая за
состоянием страничного обмена во время рабочей нагрузки системы, можно
делать выводы о том, нужна ли ей дополнительная память. Если страничный
обмен интенсивный
-
то однозначно следует установить дополнительные
модули ОЗУ.
Если же происходит так, что процессам не хватает ни реальной физической,
ни виртуальной памяти, т.е. когда память полностью исчерпана, система на
чинает завершать
(а
точнее уничтожать) целые процессы. Либо запрещает
создание новых . Конечно, в этом случае в первую очередь уничтожаются
наиболее "безболезненные" для системы процессы. Однако в таких случая:х:
даже "на глаз" и по собственным ощущениям видно, что она большую часть
времени тратит на управление памятью, а не на выполнение рабочих задач .
•
1D ................................................................................. .
1~ ,ава R.
n..inux _________________ _
В
Linux
У11равле11ие 11амs11 ыо
можно настроить параметр, который задает, насколько быстро ядро
должно "отбирать" страницы памяти у процессов, которым они менее нуж
ны
-
для процессов , которым они на данный момент необходимы . Этот па
раметр содержится в файле
60.
/proc/sys/vm/swappiness
и по умолчанию равен
Если задать его меньшим значением (например , О) , то ядро будет заби
рать страницы процесса в самую последнюю очередь, используя ~место это
го любые другие варианты. Если это значение в пределах между
60
и
100,
то страницы будут отбираться у процессов с более высокой вероятность~ .
Вариант с изменением данного параметра на с.амом деле говорит о том, что
необходимо либо снизить нагрузку на систему, адаптировав ее для других,
менее производительных задач, либо увеличить объем ОЗУ.
8.4. Дополнительные
памятью в Linux
Управление памятью в
Linux
сведения об управлении
представляет собой сложную систему, которая
развивалась с годами и включала все больше и больше функций для под
держки различных систем , от микроконтролл;еров без ММU до . суперком
пьютеров. Управление памятью для систем без ММU называется
nommu, и
оно определенно заслуживает отдельной книги, которая , надеемся , в конеч
ном итоге будет написана. Тем не менее, хотя некоторые концепции одинако
вы , здесь мы предполагаем, что
MMU доступен,
и
CPU может преобразовать
виртуальный адрес в физический адрес .
8.4.1.
Снова о виртуальной памяти
Физическая память является ограниченным ресурсом , и д аже для систем,
поддерживающих горячее подключение памяти, существует жесткое ограни
чение на объем устанавливаемой памяти . Физическая память не обязательно
непрерывна
-
она может быть доступна как набор отдельных диапазонов
адресов. Кроме того , разные архитектуры
CPU
и даже разные реализации
одной и той же архитектуры имеют разные представления о том, как опреде
ляются эти диапазоны адресов.
И 1 1ро l,i1111x
................... .... n.1nux
Все это делает непосредственную работу с физической памятью довольно
сложной, и чтобы избежать этой сложности, была разработана концепция
виртуальной памяти.
Виртуальная память абстрагирует детали физической памяти от приклад
ного программного обеспечения, позволяет хранить в физической памяти
только необходимую информацию (подкачка по запросу) и обеспечивает ме
ханизм защиты и контролируемого обмена данными между процессами.
С виртуальной памятью каждый доступ к памяти использует виртуальный
адрес. Когда
CPU
декодирует инструкцию, которая читает (или записывает)
из (или в) системную память , он транслирует виртуальный адрес, закоди
рованный в этой инструкции , в физический адрес, который может понять
контроллер памяти.
Физическая системная память разделена на страничные фреймы или страни
цы. Размер каждой страницы зависит от архитектуры . Некоторые архитек
туры позволяют выбирать размер страницы из нескольких поддерживаемых
значений
-
этот выбор выполняется во время сборки ядра путем установки
соответствующей опции конфигурации ядра.
Каждая страница физической памяти может отображаться как одна или
несколько виртуальных страниц. Эти сопоставления описываются табли
цами страниц, позволяющими выполнять преобразование виртуального
адреса, используемого программами , в адрес физической памяти. Таблицы
страниц организованы иерархически.
Таблицы на самом низком уровне иерархии содержат физические адреса
фактических страниц, используемых программным обеспечением. Табли
цы более высоких уровней содержат физические адреса страниц, принад
лежащих более низким уровням. Указатель на таблицу страниц верхнего
уровня находится в регистре. Когда процессор выполняет трансляцию
адресов, он использует этот регистр для доступа к таблице страниц верх
него уровня. Старшие биты виртуального адреса используются для ин
дексации записи в таблице страниц верхнего уровня . Эта запись затем ис
пользуется для доступа к следующему уровню в иерархии со следующими
битами виртуального адреса в качестве индекса к таблице страниц этого
уровня. Младшие биты виртуального адреса определяют смещение внутри
фактической страницы.
•
ID- ----. --------------. ---.. ---. ---. --. ---"-. -"--"-"-. --.. ----. -. --. --. --". ---------.
1J1a11a
n.1nux ................. .
8.4.2.
Х. У111э,11шс1111с ш1~н111,ю
Большие страницы
Преобразование адресов требует нескольких обращений к памяти , а обра
щения к памяти медленны относительно скорости проце ссора. Чтобы не
тратить драгоценные циклы процессора на преобразование адресов , про
цессоры поддерживают кэш таких преобразований , наз ывае м ый буфером
преобразования (или
Translation Lookaside Buffer, TLB) . Обычно TLB
явля
ется довольно дефицитным ресурсом , и приложения с больши м рабочим на
бором памяти будут испытывать снижение производительности из-за про
махов
TLB.
Многие современные архитектуры
CPU
позволяют отображать страницы
памяти непосредственно на более высокие уровн и в табли це страниц.
Например , на х86 можно отображать страницы р азмер ом 2М и даже
пользуя записи в таблицах страниц второго и третьего уровня . В
страницы называются большими
(huge pages).
TLB,
ниц значительно снижает нагрузку на
TLB
lG, ис
Linux такие
Использо вание больших стра
повыш ает частоту попаданий
и, таким образом, повышает общую произ водительн ость си стемы.
В ОС
Linux
есть два механизма, которые позвол яют сопо ставлять физи
ческую память с большими страницами. Первый
HugeTLB,
-
это файловая система
или hugetlЬfs. Это псевдо файловая система, которая использует
оперативную память в качестве резервного хранилища. Для файлов, создан
ных в этой файловой системе, данные находятся в памяти и отображаются с
использованием больших страниц.
Другой , более современный механизм, позволя ющий использовать боль
шие страницы , называется
Transparent HugePages
или ТНР. В отличие от
hugetlЬfs, который требует от пользователей и/или системных администра
торов настройки того , какие части системной п амяти должны и могут быть
отображены большими страницами, ТНР управляет такими сопоставления
ми прозрачно для пользователя и , следовател ьно , для имени .
8.4.3.
Зоны
Зачастую оборудование накладывает ограничения на доступ к различным
диапазонам физической памяти . В некоторых случаях устройства не могут
выполнять прямой доступ к памяти
•
(DMA, Direct Memory Access)
для всей
.. . . ... . ...... ... .. . . . . .. .. . . . .. .. . . . . . ... . . . . . . ........ ... . ...... ... . ..... .. ... . --
Ядро
Linux
........... . .......... n..inux
адресуемой памяти. В других случаях размер физической памяти превыша
ет максимальный адресуемый размер виртуальной памяти, и для доступа к
частям памяти требуются специальные действия.
ОС
Linux
группирует страницы памяти в зоны в соответствии с их возмож
ным использованием. Например,
ZONE_ DMA будет содержать память, кото
DMA, ZONE_HIGHMEM будет
рая может использоваться устройствами для
содержать память, которая не отображается постоянно в адресное простран
ство ядра, а ZONE_NORМAL будет содержать страницы с обычной адреса
цией.
Фактическое расположение зон памяти зависит от аппаратного обеспечения,
поскольку не все архитектуры определяют все зоны, а требования к прямому
доступу к памяти различаются для разных платформ.
8.4.4.
Узлы
Многие многопроцессорные машины являются системами
Uniform Memory Access).
NUMA (Non-
В таких системах память организована в банки, ко
торые имеют разную латентность доступа в зависимости от "удаленности"
от процессора. Каждый банк называется узлом, и для каждого узла
Linux
создает независимую подсистему управления памятью. У узла есть свой на
бор зон, списки свободных и используемых страниц и различные счетчики
статистики .
8.4.5.
Кэш страницы
Физическая память энергозависима, и обычным случаем получения данных
в память является их чтение из файлов. Всякий раз , когда файл читается,
данные помещаются в кэш страниц во избежание "дорогостоящего" (по фак
ту
-
длительного) доступа к диску при последующих чтениях. Точно так же,
как когда кто-то записывает в файл, данные помещаются в кэш страниц и,
в конечном итоге , попадают на резервно е запоминающее устройство. Запи
санные страницы помечаются как грязные, и когда ядро
решает
Linux
повторно использовать их для других целей, оно обязательно синхронизиру
ет содержимое файла на устройстве с обновленными данными .
. . . . .. --
. .
--.. ---- --. --- -- --- ---- -- -- -.
. . .
. .
.
.
. .
. .
. . . . . . . . . .
. . . . . . . . .
-
. . .
·
. ·
.
. .
.
•
-. . . .
1 1:tll:t
t.\.1nux ................. .
8.4.6.
Х
Y11Jlallclt' Jlllt' ШIMil 11,Ю
Анонимная память
Анонимная память или анонимные сопоставления представляют собой па
мять, которая не поддерживается файловой системой. Такие отображения
создаются неявно для стека и программ или явными вызовами системного
вызова
mmap().
Обычно анонимные сопоставления определяют только обла
сти виртуальной памяти , к которым программе разрешен доступ . Доступ для
чтения приведет к созданию записи в таблице страниц , которая ссылается на
специальную физическую страницу, заполненную нулями. Когда программа
выполняет ·запись , для хранения записанных данных выделяется обычная
физическая страница. Страница будет помечена как грязная , и если ядро ре
шит перепрофилировать ее , грязная страница будет заменена.
8.4.7.
Освобождение
На протяжении всего жизненного цикла системы физическая страница мо
жет использоваться для хранения различных типов данных . Это могут быть
внутренние структуры данных ядра, буферы с поддержкой
DMA для исполь
зования драйверами устройств, данные, считанные из файловой системы,
память, выделенная процессами пользовательского пространства и т. д.
В зависимости от использования страницы управление памятью
Linux
об
рабатывает ее по-разному. Страницы, которые могут быть освобождены в
любое время либо. потому, что они кэшируют данные, доступные в другом
месте, например, на жестком диске, либо потому, что их можно выгрузить,
опять же, на жесткий диск, называются восстанавливаемыми. Наиболее за
метными категориями восстанавливаемых страниц являются кэш страниц и
анонимная память.
В большинстве случаев страницы, содержащие внутренние данные ядра и
используемые в качестве буферов DМА, не могут быть переназначены , и
они остаются закрепленными до тех пор, пока их не освободит пользова
тель. Такие страницы называются невосстановимыми . Однако при опреде
ленных обстоятельствах могут быть освобождены даже страницы, занятые
структурами данных ядра. Например, кэши метаданных файловой системы
в памяти могут быть повторно прочитаны с устройства хранения и, следо
-
вательно , их можно удалить из основной памяти, когда система испытывает
,
нехватку памяти.
_
..................... ....... " " ...
_
"
". -
.. ..
"
""
...
" "
..
". ". ""
......
". "
.............
и ,, .,ю l ,illll\
...................... n.1nux
Процесс освобождения восстанавливаемых страниц физической памяти и
их перепрофилирования называется освобождением
ОС
Linux
(reclaim).
может освобождать страницы либо асинхронно, либо синхрон
но, в зависимости от состояния системы. Когда система не загружена,
большая часть памяти свободна, и запросы на выделение будут немед
ленно удовлетворены за счет наличия свободных страниц. По мере уве
личения нагрузки количество свободных страниц уменьшается, и когда
оно достигает определенного порога (нижний водяной знак), запрос на
выделение пробуждает демон
kswapd.
Он будет асинхронно сканировать
страницы памяти и либо просто освобождать их, если данные, которые
они содержат, доступны в другом месте, либо вытеснять их на резервное
устройство хранения (помните эти грязные страницы?). По мере того,
как использование памяти увеличивается еще больше и достигает дру
гого порога
-
минимального водяного знака
-
выделение инициирует
прямое восстановление. В этом случае выделение останавливается до тех
пор, пока не будет высвобождено достаточное количество страниц памя
ти для удовлетворения запроса.
8.4.8.
Уплотнение (сжатие)
По мере работы системы, задачи выделяют и освобождают память, и она
становится фрагментированной. Хотя с помощью виртуальной памяти мож
но представить разрозненные физические страницы как виртуально непре
рывный диапазон, иногда необходимо выделить большие, физически непре
рывные области памяти. Такая необходимость может возникнуть, например,
когда драйверу устройства требуется большой буфер для
DMA,
или когда
ТНР выделяет большую страницу. Сжатие памяти решает проблему фраг
ментации. Этот механизм перемещает занятые страницы из нижней части
зоны памяти в свободные страницы в верхней части зоны. По завершении
сканирования с уплотнением свободные страницы группируются вместе в
начале зоны, и становится возможным выделение больших физически смеж
ных областей.
Как и операция
kcompactd или
•
reclaim,
сжатие может происходить асинхронно в демоне
синхронно в результате запроса на выделение памяти.
•
············ ······· ·······························································
1 т111а Х . Yщ)a11J1t·1111t• ш1мs111.ю
n.1nux .. ..... .......... .
8.5.
Большие страницы . Бол ее подробн о
8.5.1.
Общая информация
Как уже отмечалось ранее, ядро
(hugetlb ).
Linux
поддерживает большие страницы
Эта поддержка построена на основе поддержки нескольких раз
меров страницы , которая обеспечивается большинством современных архи
тектур. Например, процессоры х86 обычно поддерживают размеры страниц
4К и 2М
(lG,
если поддерживается архитектурой), архитектура
держивает несколько размеров страниц: 4К, 8К, 64К, 256К,
256М, а ррс64 поддерживает 4К и
TLB -
lM,
ia64
под
4М, 16М,
1бМ.
это кэш преобразований виртуального в физическое. Как правило,
на подобные преобразования тратится достаточно ресурсов процессора,
поэтому кэш просто необходим. Операционные системы пытаются наилуч
шим образом использовать ограниченное количество ресурсов
TLB.
Данная
оптимизация становится все более важной сейчас, поскольку все больше и
больше физической памяти становится все более доступнее.
Пользователи могут использовать поддержку больших страниц в ядре
mmap или
SYSV (shmget, shmat).
используя системный вызов
общей памятью
Linux,
стандартные системные вызовы с
Сначала необходимо собрать ядро
Linux с параметрами конфигурации
CONFIG_HUGETLBFS (находится в разделе "File systems") и CONFIG
HUGETLB_PAGE (выбирается автоматически при выборе CONFIG
HUGETLBFS).
Файл
/proc/meminfo
постоянных страниц
предоставляет информацию об общем количестве
hugetlb в
пуле больших страниц ядра. Он также отобра
жает размер большой страницы по умолчанию и информацию о количестве
свободных , зарез ервированных и избыточных больших страниц в пуле боль
ших страниц размера по умолчанию. Указание размера большой страницы
необходимо дл я создания правильного выравнивания и размера аргументов
для системных вызовов, которые отображают области больших страниц.
Вывод
cat /proc/meminfo
будет примерно следующим :
HugePages_Tot a l : uuu
HugePages_Free : vvv
. ugePages_Rsvd : www
..................... . .... . .... -.................... -- -.................. -.......
--
Ищ111
l ,i1111x
...................... t't1nux
HugePages_Surp :
Hugepagesize :
Hugetlb :
ххх
kB
zzz kB
ууу
Где:
•
HugePages_Total -
это размер пула больших страниц.
это количество больших страниц в пуле, которые еще
• HugePages_Free не выделены .
• HugePage·s_Rsvd - является сокращением от "зарезервировано" и пред
ставляет собой количество больших страниц, для которых было принято
обязательство о выделении из пула, но еще не бьшо выделено. Зарезерви
рованные большие страницы гарантируют, что приложение сможет вы
делить большую страницу из пула больших страниц в случае сбоя.
• HugePages_ Surp -
является сокращением от "избыточный" и представля
ет собой количество больших страниц в пуле, превышающее значение в
/proc/sys/vm/nr_ hugepages.
Максимальное количество избыточных боль
ших страниц контролируется /proc/sys/vm/nr_ overcommit_hugepages. Если
включена функция освобождения неиспользуемых страниц vmemmap,
связанных с каждой страницей
hugetlb, количество
избыточных больших
страниц может временно превышать максимальное количество избыточ
ных больших страниц, когда система испытывает нехватку памяти.
• Hugepagesize -
это размер большой страницы по умолчанию (в килобай
тах).
• Hugetlb- общий
объем памяти (в килобайтах), потребляемый большими
страницами всех размеров. Если используются большие страницы разно
го размера, это число превысит
HugePages_Total * Hugepagesize. Чтобы
/sys/kemeUmm/
получить более подробную информацию, обратитесь к
hugepages.
Файл
/proc/filesystems
также должен показывать файловую систему тиnа
"huget\Ьfs", сконфигурированную в ядре.
Файл
/proc/sys/vm/nr_hugepages
указы вает текущее количество "постоян
ных" больших страниц в пуле больших страниц ядра. "Постоянные" боль
шие страницы будут возвращены в пул страниц при задаче освобождения
памяти. Пользователь с привилегиями
root
может динамически выделять
•
. .... -- ........................................ ... ········ -·. ---- .. ····-···- ····-·· ·
1 · 1а11а
n..inux ................. .
:,,;_ Y11paB.lt'llllt' 11:1\J)J I J,IO
больше или освобождать некоторые постоянные большие страницы, увели
чивая или уменьшая значение
nr_hugepages.
Страницы, которые используются как большие
(huge ), зарезервировавы вну
три ядра и не могут использоваться для других целей . Большие страницы не
могут быть выгружены из-за нехватки памяти.
Как только несколько больших страниц были предварительно выделены в
пул больших страниц ядра, пользователь с соответствующими правами мо
жет использовать либо системный вызов mmap(), либо системные вызовы с
общей памятью для использования больших страниц .
Администратор может выделить постоянные hugе-страницы, используя
параметр ядра
"hugepages=N",
где
"N" =
количество запрошенных hugе
страниц. Это самый надежный метод выделения больших страниц, так как
память еще не стала фрагментированной .
•
Некоторые платформы поддерживают несколько больших размеров страниц.
Чтобы выделить большие страницы определенного размера, перед параме
трами команды загрузки больших страниц необходимо указать параметр вы
бора размера большой страницы "hugepagesz=<paзмep>". <размер> должен
быть указан в байтах с необязательным суффиксом масштаба [kКmМgG].
Размер hugе-страницы по умолчанию можно выбрать с помощью параметра
ядра
"default_hugepagesz=<paзмep>" .
Семантика параметра командной строки загрузки
Hugetlb:
• hugepagesz
Указывает размер hugе-страницы . Используется в сочетании с параметром
hugepages
для предварительного выделения ряда болъшliх страниц указан
ного размера. Следовательно , параметры ядра
hugepagesz и hugepage указы
ваются парами:
hugepages z=2 M hugepages=512
Параметр
hugepagesz можно указать только один раз в командной строке. До
пустимый размер таких страниц зависит от архитектуры.
·················································································· -
Я .' tро
l,inux
........... __ ·_........ n.inux
• hugepages
Укажите количество больших страниц для предварительного выделения.
Обычно он указывается после параметра
hugepagesz или default_hugepagesz.
hugepages является первым или единственным параметром ко
строки hugetlb, он неявно указывает количество больших страниц с
Однако если
мандной
размером по умолчанию, которые будут выделены.
Если количество страниц размера по умолчанию указано неявно, оно не мо
жет быть перезаписано парой параметров
hugepagesz,hugepages для размера
по умолчанию.
• default_ hugepagesz•
Задает размер по умолчанию для больших страниц. Данный параметр мож
но указать только один раз в командной строке. За
дополнительно следовать параметр
hugepages,
default_hugepagesz может
чтобы предварительно вы
делить определенное количество больших страниц размера по умолчанию.
Количество больших страниц размера по умолчанию для предварительного
выделения также может быть неявно указано, как указано в разделе о боль
ших страницах ранее . Следовательно , на архитектуре с размером большой
страницы в
2 Мб
конфигурация:
hugepages= 256 default_hugepagesz=2M hugepages=256
hugepages=256 default hugepagesz=2M
приведет к выделению
256
больших страниц по 2М. Допустимый размер
большой страницы по умолчанию зависит от архитектуры.
• hugetlbJree _ vmemmap
Когда
опция
ядра
CONFIG HUGETLB PAGE
OPТIMIZE
VMEMMAP
установлена (она устанавливается при компиляции ядра), это включает оп
тимизацию
HugeTLB Vmemmap (HVO).
•
I D---.--------------------.---.. -... ----.--------.---.. ---.. -.. --.. ----------------.
l ".11ана Х. У11рав. н.• 111н• 1ш,1я 11,ю
t\.inux ................. .
Когда поддерживаются несколько больших страниц, фа.йл
hugepages указывает текущее количество предварительно
/proc/sys/vm/nr_
выделенных бо1;1ь
ших страниц размера по умолчанию . Таким образом, можно использовать
следующую команду для динамического выделения/освобождения постоян
ных больших страниц по умолчанию:
ech o 2 0 > / pr o c / sys / vm / nr hugepages
Эта команда попытается установить количество больших страниц с разме
ром по умолчанию в пуле страниц до 20, выделяя или освобождая большие
страницы по мере необходимости.
На платформе
NUMA ядро
попытается распределить пул больших страниц
по всему набору разрешенных узлов, указанному в политике памяти
задачи, изменяющей
nr_ hugepages .
NUMA
Разрешенные узлы с недостаточной
доступной непрерывной памятью для большой страницы будут автомати-.
чески пропущены при выделении постоянных больших страниц.
Успех выделения больших страниц зависит от объема физически непрерыв
ной памяти, которая присутствует в системе во время попытки выделения.
Если ядро не может выделить большие страницы для некоторых узлов в
системе
NUMA,
оно попытается компенсировать разницу, выделив допол
нительные страницы на других узлах с достаточным количеством доступной
непрерывной памяти , если таковая имеется.
Системные администраторы могут захотеть поместить эту команду в один
из локальных файлов инициализации
rc. Это
позволит ядру выделять боль
шие страницы в начале процесса загрузки, когда вероятность получения фи
зических смежных страниц все еще очень высока. Администраторы могут
проверить количество фактически выделенных больших страниц, проверив
файл
sysctl
или
meminfo. Чтобы проверить распределение больших страниц
NUMA, используйте:
по узлам в системе
c at / sys / devices / syst e m/ node / node* / memin f o I f g rep Huge
Файл
/proc/sys/vm/nr_ overcommit_hugepages
указывает, насколько большим
может стать пул больших страниц, если приложения запрашивают больше
страниц, чем
/proc/sys/vm/nr_ hugepages.
Запись любого ненулевого значения
в этот файл указывает на то, что подсистеме
•
hugetlb
разрешено пытаться
.-----------.---\. -------. ----.---.. -------. -------------.--... -.----------... -----tD
•
Я , tро l,i1111x
...................... t81..1nux
получить это количество "избыточных" больших страниц из обычного пула
страниц ядра, если постоянный пул больших страниц исчерпан. Когда эти
лишние большие страницы становятся неиспользуемыми, они возвращают
ся в обычный пул страниц ядра,
При увеличении размера пула больших страниц с помощью
nr_hugepages
любые существующие избыточные страницы сначала будут преобразованы
в постоянные большие страницы , Затем, если это необходимо и возможно,
будут выделены дополнительные большие страницы, чтобы заполнить но
вый постоянный размер пула больших страниц,
Администратор может уменьшить пул постоянных больших страниц. уста
новив
sysctl nr_ hugepages
в меньшее значение , Ядро попытается сбаланси
ровать освобождение больших страниц на всех узлах в политике памяти за
дачи, изм~няющей
nr_hugepages,
Любые свободные большие страницы на
выбранных узлах будут возвращены в обычный пул страниц ядра,
Внимание! Сокращение постоянного пула больших страниц с по
мощью
nr_hugepages так,
что он станет меньше, чем количество
используемых больших страниц, приведет к преобразованию
баланса используемых больших страниц в избыточные большие
страницы. Это произойдет, даже если количество избыточных
страниц превыс'ит значение overcommit. Пока выполняется это
условие, то есть пока nr_hugepages+nr_overcommit_hugepages
не будет увеличено в достаточной степени или лишние большие
страницы не выйдут из использования и не будут освобождены,
система больше не разрешит выделять дополнительные боль
шие страницы ,
Благодаря поддержке нескольких пулов больших страниц во время выпол
нения большая часть интерфейса пользовательского пространства больших
страниц в
сы
/proc
/proc/sys/vm дублируется в sysfs,
Обсуждавшиеся выше интерфей
были сохранены для обратной совместимости, Корневой каталог
управления большими страницами в
sysfs:
/sys/ kern el/mm/hugepages
Для каждого размера большой страницы, поддерживаемого работающим
ядром, будет существовать подкаталог в форме:
-
•
···· -· ............ ----- ----- --- .... -· .. ·-·-. - . ---· ·- -··-·-·. --- . -- -...... .. .. .. .. .
•
1
t\.1nux ........... ...... .
1а11а Х . Yщt,111.1t•1111t• ШI\HI 11,ю
hugepages-${size }kB
Внутри каждого из этих каталогов будет существовать набор файлов, содер
жащихся в
/proc.
Кроме того, могут существовать два дополнительных ин
терфейса для понижения уровня больших страниц:
demote
demote size
n r_hugepages
n r hugepa~es_mempolicy
n r_overcommit_hugepages
free hugepages
resv_hugepages
surp lu s _hugepages
Интерфейсы понижения уровня предоставляют возможность разбить боль
шую страницу на более мелкие большие страницы. Например, архитектура
х86 поддерживает большие страницы размером
ницу размером
1 ГБ
можно разделить на
512
1 ГБ
и
2 МБ.
Большую стра
больших страниц по
2 МБ.
По
нижение интерфейсов недоступно для самых маленьких больших страниц.
Интерфейсы понижения приведены ниже:
• demote_size -
размер пониженных страниц. Когда уровень страницы бу
дет понижен, будет создано соответствующее количество больших стра
ниц
demote_size.
По умолчанию для параметра
demote_size
установлен
следующий меньший размер большой страницы. Если существует
несколько меньших больших размеров страниц, для параметра
size
demote_
можно установить любой из этих меньших размеров. Допускаются
только те размеры больших страниц, которые меньше текущего рцзмера
больших страниц.
• demote -
используется для понижения ряда больших страниц. Пользо
ватель с привилегиями
root
может писать в этот файл . Возможно, будет
невозможно понизить запрошенное количество больших страниц. Чтобы
определить, сколько страниц было фактически понижено , сравните зна
чение
фейс
•
nr_ hugepages до и после записи в интерфейс
demote поддерживает только запись .
понижения. Интер
·--·--···-·····--------·-···········-·················-··--···--··--··--···--···-· -
}1
11ю
l .i1111,
8.5.2.
....................... f't.1nux
Взаимодействие политики памяти задач с выделением/
освобождением больших страниц
Независимо от того, выделяются и освобождаются ли больших страницы
через интерфейс /proc или интерфейс /sysfs с использованием атрибута
nr_ hugepages_ mempolicy, узлы NUМA, из которых выделяются или осво
бождаются большие страницы , контролируются политикой памяти NUMA
задачи, которая изменяет sysctl или атрибут nr_ hugepages _ mempolicy. Когда
используется атрибут nr_ hugepages, mempolicy игнорируется .
Рекомендуемый метод для выделения или освобождения больших страниц
в/из пула больших страниц ядра, используя приведенный выше пример
nr_hugepages:
numactl -- interleave
<список
узлов> echo 20 \
>/proc/sys/vm/nr_hugepages_mempolicy
или , более кратко:
numactl - m
<список - узлов>
echo 20 >/proc / sys /vm/ nr_hugepages_mempolicy
Это выделит или освободит
abs(20 - nr_hugepages)
для узлов , указанных в
<список-узлов >, или из них , в зависимости от того, изначально ли количе
ство постоянных больших страниц меньше или больше
20
соответственно.
Большие страницы не будут выделены или освобождены ни на одном узле,
не включенном в указанный <список-узл ов>.
При настройке постоянного кол ичества больших страниц с помощью
nr_hug_epages_mempolicy можно использовать л юбой режим политики
- привязку, предпочтительный, л ок альный или черед ование .
памя
ти
8.5.3.
Атрибуты больших страниц для каждого узла
Подмножество
страницами в
содержимого
sysfs,
корневого
каталога
управления
большими
описанного выше , будет репл ицировано под каждым
системным устройством каждого узл а
NUMA с
памятью в:
•
. . ....................... ............................................................
•
1 1 1а11а
n.1nux ................. .
Х
Ущ1а11.' 1t•11ш• 11а~ш 11.111
/sys/devices/system/node/node[0 - 9]*/hugepages/
В этом каталоге подкаталог для каждого поддерживаемого большого разме
ра стра!:Jицы содержит следующие файлы атрибутов:
nr_hugepages
free_hugepages
surplus hugepages
Файлы атрибутов
free _ *
и
surplus_ *
доступны только для чтения. Они воз
вращают количество свободных и избыточных больших страниц соответ
ственно на родительском узле.
Атрибут
nr_ hugepages
возвращает общее количество больших страниц на
указанном узле. Когда этот атрибут записан, количество постоянных боль
ших страниц на родительском узле будет скорректировано до указанного
значения если существует до статочно ресурсов, независимо от ограничений
памяти задачи или набора процессоров.
Обратите внимание, что количество избыточных и резервных страниц оста
ется глобальными величинами, поскольку мы не знаем до момента сбоя, ког
да применяется мемполитика сбойной задачи, с какого. узла будет предпри-
нята попытка выделения большой страницы .
8.5.4.
'
Использование больших страниц
Если пользовательские приложения будут запрашивать большие страницы с
помощью системного вызова
mmap(), то
нужно, чтобы системный админи
стратор смонтировал файловую систему типа
hugetlbfs:
mount - t hugetlbfs \
- о uid=<val ue> , gid=<value>, mode=<value> , pagesize=<value> , size=<value>, \
min_size=<value> , nr_inodes=<value> none /mnt/huge
•
·----------------------------··-·····-··--···----------·-·--·----··----- ---------- -
И , 11ю
lai1111,
...................... rl.1nux
Эта команда монтирует (псевдо) файловую систему типа
/mnt/huge.
Любой файл, созданный в
/mnt/huge,
hugetlbfs в каталог
использует большие страни
цы.
Параметры
uid
и
gid
задают владельца и группу корня файловой системы .
По умолчанию берутся
Опция mode
&01777. Это
uid и gid текущего
процесса.
устанавливает режим корня файловой системы на значение
значение задается в восьмеричном формате. По умолчанию
выбрано значение
0755.
Если платформа поддерживает несколько размеров больших страниц, па
раметр
pagesize
можно использовать для указания размера большой стра
ницы и связанного пула. Данный параметр указывается в байтах. Если раз
мер страницы не указан, будет использоваться размер большой страницы по
умолчанию и соответствующий пул.
Параметр
size
устанавливает максимальное значение памяти, разрешенное
для этой файловой системы
(/mnt/huge ).
Размер памяти может быть указан в
байтах или в процентах от указанного пула больших страниц
Размер округляется до границы
Параметр
(nr_hugepages).
HPAGE_ SIZE.
min_size устанавливает
минимальное значение памяти, разрешен
ное для файловой системы. Параметр
min_size
можно указать так же, как
и размер: либо в байтах, либо в процентах от пула больших страниц. Во
время монтирования количество больших страниц, указанное в параметре
min _size,
зарезервировано для использования файловой системой. Если сво
бодных больших страниц недостаточно, монтирование не удастся. Когда
большие страницы выделяются в файловой системе и освобождаются, счет
чик резервов корректируется так, чтобы сумма выделенных и зарезервиро
ванных больших страниц всегда была не меньше
Опция
nr_inodes
устанавливает максимальное количество инодов, которые
может использовать
Если параметры
min_size.
/mnt/huge.
size, min_size или nr_inodes
не указаны в командной строке,
ограничения не устанавливаются.
Для параметров
pagesize, size, min _size и nr_inodes вы можете использовать
[Glg]/[Mlm]/[Klk] для представления гига/мега/кило. Например, size=2K
имеет то же значение, что и size=2048.
В то время как системные вызовы чтения поддерживаются для файлов, на
ходящихся в файловых системах
hugetlb,
системные вызовы записи
-
нет.
•
I D - ··················································································
1!lава
n..1nux ................. .
Обычные команды
chown, chgrp и chmod (с
Х . Ущнш.1t·1111t• Н:1\НI 11.ю
соответствующими разрешения-
'
ми) можно использовать
для изменения атрибутов файла на hugetlbfs.
Кроме того, важно отметить, что такая команда монтирования не требует
ся, если приложения будут использовать только системные вызовы
shmget или mmap с МАР_HUGETLB.
mmap с МАР_НUGETLB, посмотрите
shmat/
Для примера того, как использовать
на
map_ hugetlb ниже.
Пользователи, которые хотят использовать память
hugetlb через
сегмент об
щей памяти, должны быть членами дополнительной группы, а системный
администратор должен настроить этот gid в
/proc/sys/vm/hugetlb_shm_group.
Для одних ·и тех же или разных приложений можно использовать любую
комбинацию вызовов
mmaps
и
shm*,
хотя для использования вызовов
mmap
без МАР_HUGETLB потребуется монтирование файловой системы.
Системные вызовы, работающие с памятью, поддерживаемой страницами
hugetlb, имеют только длину,
соответс:гвующую собственному размеру стра
ницы процессора; они обычно не будут работать, если для
значение
errno установлено
EINVAL или будут исключены из страницы hugetlb, выходящие за
пределы длины, если они не выровнены по большой странице. Например,
munmap() завершится ошибкой , если память поддерживается
hugetlb, а ее длина меньше, чем размер hugepage.
8.6.
Практикум администратора
8.6.1.
Полезные команды оболочки
Файл
Файл
страницей
/proc/meminfo
/proc/meminfо
содержит всю щ-1формацию, связанную с памятью. Для
просмо1_-ра данного файла используйте команду
cat:
$ c at / pr oc/ meminf o
•
... .. .. ... ...... ... ........ ..... .... ..... .. .... .. . .... .. .. . .. .... ........... .... ·· -
И , IJНI J ,illll\.
....................... n.1nux
Рис.
8.4.
Вывод команды (частично)
cat lproc/meminfo
Данная команда выводит множество параметров, связанных с памятью. Что
бы получить информацию о физической памяти из файла
/proc/meminfo, ис
пользуйте :
$ grep MemTotal /proc/meminfo
MemTotal:
41185488 kB
Чтобы получить информацию о виртуальной памяти из файла /proc/meminfo,
используйте:
$ grep VmallocTotal /proc/meminfo
VmallocTotal:
34359738367 kB
Команда
Команда
top
и ее улучшенный вариант
htop
top позволяет отслеживать процессы и использование системных
ресурсов в
Linux
в режиме реального времени. Когда вы запустите команду,
• •
-
--------------···········--···-···--··--···--··--···--···-···-···--···-··--···-···
n..1пux ................. .
) Jlalla Х . У11р:111.11t·111н· 11:l~HI 11,Ю
то заметите, что значения в выходных данных продолжают изменяться с не
которым небольшим интервалом (рис.
8.5).
о
top
Т,1
1,
".(р11(
У.1В
f
11 ',' U0 up
}1'\ tnl 11,
)
]8 2 u ,
41185488 total,
•>1~m
1А
,,11р
3805992 frf"e,
20804600 tot,11, 20797564 free,
(J.Jta
20
",1184 •,>11,w·dat.J
20
20
с,;ч;<,
',7182
':>031
57185
57183
57366
12733
8
57678
1
2
3
\,r,,,,.,,1
data
my5ql
1<11·.-w·data
www-data
www-data
wi....w··data
root
den;s
root
root
.,,,мw
root
4 root
6 root
7 root
9
10
11
12.
13
14
root
root
root
root
root
root
lS
root
16
18
19
20
21
11 d.iy•, 16 • 1,
1 11~1!'•,
ln,1d ;iv+ r,1gr'
6 r1н>1111g, 142 •lt>ep111~,
0
\op1<.,I
0
-;' 3
\.,
0 0 nl, 79 4 111,
0 0 ,,,,1,
0 0 111
root
,0
20
20
20
20
20
20
20
20
20
0
0
20
20
0 -i54600 145S28
0
50'>176 196500
0 493760 183S32
0 :'3.302g 0.016t
0 515S12 205512
442032 133752
556824 240244
53.2.88 11816
0
42948
4112
225492
9000
0
0
·20
·20
0
19019640
7036
21888 S
Ч.8
4q.
4i' ',
0.4
43.'41.7
32.9 0.5
22912 R
12 .0
0. 3
21400 R
10.0
0.6
56S6 S
0 I
0.0
R
1.3
0. 3
0.3
6420 S
0 S
0.0
0.0
0 I
0 I
0 I
0.0
0.0
0.0
0
0
0
0
0
0
0
0
0
0
0
0
0
0 0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
ЗЗS2
0
0
ct
20
0 ·20
,.
root
ct
root
0
Рис.
На рис.
8.6
5
I
S
S
S
5
':,
S
S
I
S
S
5
8.5.
0
0
1
,
И
0
1
0: s-1 :я pr,:-, tr-n;•.:
l ... t, ·,\ :,t,p fр'Т!/ .'
1: ~4 10 phV fµtn7 .'
4">01 i0 ,r,y,;qld
1: 38. 72 php-fpm7 _2
1:37.78 php-fpm7.2
0 59.89 php-fpm7.2
37 05.91 nginx
19 14. 34 rcu_c;ched
0 -1
~
':,
0.0
0.0
0.0
0 00.04 top
3 04.56 systemd
0 00.1~ kthreadd
0 35.68 kworker/0 0
0 00.00 k,~or~er:0:€\H
0 00.00 mrn_percpv __ wq
0 ..18. 73 i.so+-tirq,Ji0
0 00.00 ,·cu_Ьh
0 00.34 migro1,tion.·0
0 01 9б ,~atchdc,~/0
0 00.00 ~p;;hpi0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0
0
0
0
0
0
00.00
е: 1-:.
00. 76
28, 1"1
cpuhpil
1,at:ch(1og: 1
n,igi·ation/1
kso-ftirad 1
00.е0 ~1-юr·ker
1 :0Н
00.00 cpuhp.-:
0 0: .19 ,~at::chdog/ 2
0 00. 76 migration.':;'
Команда
top
приводится более продвцнутый ее вариант
мимо всей информации, выводимой
top,
х
f}l
18359856 h<Jft r,н~н,
]1649348 , нl .,,,,,.
.224 ~6 <.,
10
root
r·oot
Pd.
21196 ':.
17440S
22260 R
r'"t
ct
20
ц
tJ't't:
'
("!НII•
-
команда
htop.
По
данная команда выводит загрузку
процессора по ядрам, а также выводит график используемой памяти.
о
1
]
1
J
[
""[
]
'.
1
]
I
'
[
1 11
118 1l• 3
[
1
J
I
]
]
[
Рис.
8. 6.
]
1
н.l
]
'\ 16 ,
• ,.
•
]
J
R•>
1
ja,-,:;.
Комапда
i
1
1
[
1
х
,
.'4
16 59
с:,
1
htop
..--.. ----.. -.------.--.--.----.. ---.--------.---.. ----.--.----.-... --... ------.. -ID
Sl. 1p11 J,i1111x
...................... n.lnLix
Во всем эта программа лучше , но ее нужно установить отдельно (например,
командой
sudo apt install htop
в DеЬiаn-подобных системах).
Команда free
Информация об используемой памяти выводится командами
top
и
htop
по
мимо всего прочего. Но если вам нужно вывести информацию только об
использовании памяти , тогда используйте команду free. По умолчанию зна
чения для ка~ого поля указана в килобайтах, чтобы не пересчитывать в уме
в мегабайты, используйте ключ
Рис.
На рис.
8.7
-h
8. 7.
для более удобного формата вывода.
Команда free
показано, что всего установлено
-h
39
Гб физической памяти (у
нас виртуальный сервер, поэтому объем памяти не является степенью
как обычно) , из них
17
используется
(used),
еще
17 Гб
2,
отведено под буферы
и кэш (эту память также можно считать свободной, поскольку в случае
необходимости система будет выделять память из этой области) и
полностью свободна. Также есть область подкачки
из них используется
...
6.9 Мб,
(Swap)
размером
поэтому можно считать, что все
3.6 Гб
19 Гб,
19 Гб подкачки
свободно .
•
. . . -----------.. ----------------------. ---. --. --------------------------.. --.... -.
•
n.iпux .. ..... .. ........ .
I '.: 1ава Х. У11раи.1е1111r ШI\IЯ 11,ю
Для сброса области буферов и кэша можно использовать команду:
sudo echo 1 > / proc / sys /vm/ dr op cac hes
Результат выполнения этой команды показан на рис.
было свободно
(free) 3.4 Гб,
нения указанной команды для кэша используется
уже
lO
Гб.
Рис.
8.8.
Сброс буферов и кэша в действии
Команда
Команда
Linux,
8.8. Если до этого у нас
17 Гб, то после выпол
всего 846 Мб , а свободно
а для кэша было отведено
vmstat -
vmstat
это инструмент мониторинга производительности в
который предоставляет полезную информацию о процессах, памяти ,
операциях ввода-вывода, подкачке , диске и планировании процессора, а так
же приводит статистику виртуальной памяти вашей системы.
$ vmstat
•
··- ........ -.......... ··- -·-- .............. -...... -·- ---. -- -- .. -· ........ -·· ...... . .
Ядро
Linux
.................... ... n.inux
8.6.2.
Интерфейс СМА
Интерфейс отладки СМА полезен для извлечения базовой информации из
различных областей СМА и для проверки выделения/освобождения в каж
дой из областей.
Каждая область СМА представляет каталог в
<debugfs>/cma/,
представлен
ный своим именем СМА, как показано ниже:
<de b ugfs>/cma/<cma name>
Структура файлов, созданных в этом каталоге, выглядит следующим обра
зом:
• [RO] base_pfn:
• [RO] count:
базовый
PFN
(номер страницы кадра) зоны.
объем памяти в области СМА.
• [RO]
order_per_Ьit: порядок страниц, представленный одним битом .
• [RO]
Ьitmap: битмап состояний страниц в зоне.
• [WO] alloc:
выделить
N
страниц из этой области СМА. Например, ко
манда:
e cho 5 > <debugf s>/ c ma /< cma_name >/ all o c
попытается выделить
•
[WO] free:
5 страниц
бесплатные
N
из области ста_ пате.
страниц из этой области СМА, как описано
выше.
Примечание.
WO
означает "только для записи",
RO -
только
для чтения.
8.6.3.
Добавление файла подкачки
Как правило, раздел подкачки создается при установке системы и не всегда
•
удобно менять структуру разделов уже после того, как система установле-
1D ....... -.. --... -.................... -------.. --.......... -.. --.--.---.--.... ---.-.
•
1J 1ава
t\.inux ----------···-····
Х. У11равJ 1с1шс 1щмя I ыо
на. Однако , если вам понадобилось дополнительное пространство подкачки,
выход есть
- можно создать файл подкачки . Его производительность будет
чуть ниже , чем у раздела подкачки , но как временный вариант (пока не уве
личите размер ОЗУ) такая мера вполне сойдет.
Первым дел о м. нужно создать собственно сам файл подкачки (в данном при
мере мы создаем его размером
2
Гб , вы можете добавить больше подкачки ,
если есть свободное место на диске):
$ sudo dd if=/dev/zero of=/swap - file count=2 bs=lGiB
Затем установим права доступа и настроим область подкачки (команда
mkswap):
$ sudo chmod - v 0600 /swap - file
$ sudo chown - v root : root /swap - file
$ sudo mkswap /swap - file
Осталось только активироват ь файл подкачки :
$ sudo swap on /swap - file
Чтобы уб~диться , что новый файл подкачки используется, введите команду:
$ swapon -summary
Осталось только добавить информаци ю о нем в файл
/etc/fstab , чтобы систе
ма не "потеряла " его после перезагрузки. Откройте файл /etc/fstab в любом
текстовом редактор е и доб авьте строку (редактор нужно запускать через
команду
sudo , н апример , sudo joe /etc/fstab -
мало ли, вдруг вы об этом за
были):
. /swap - file swap s~ap defaults
О
О
•...--.. ·--.. -... --· .. -· .. -· .. -...... -.-----·. -.-· ··--.·--· .. -·. -..................1D
Глава
9.
Файловая система и ядро
Ядро
9.1.
Linux
•
_______________ : __ _____ n.iпux
Виртуальная файловая система
Linux
Поскольку эта книга посвящена ядру, то в главе, посвященной файловой
системе , мы рассмотрим как все устроено изнутри вместо рассмотрения ко
манд для работы с файловой системой.
Виртуальная файловая система
(VFS, Virtual File System) -
это программ
ный уровень в ядре, который обеспечивает интерфейс файловой системы
для программ пользоват ель ского пространства.
Он также обеспечивает абстракцию внутри ядра, которая позволяет сосу
ществовать различным реализациям файловой системы. Другими словами,
ядро поддерживает множество самых разных фай.т,ювых систем
- ext2, ехtЗ ,
ext4, XFS , ZFS и т.д. Чтобы пользователь мог использовать одни и те же ко
манды (ер , mv, cat и т.д. ), а программист одни и те же системные вызовы для
работы со всеми файл овыми системами , как раз и нужна виртуальная фай
ловая система . В противном случае пришлось бы реализовывать отдельные
команды для работы с каждой файловой системой , например, для работы с
XFS коман да копирования
ния - xfs mv.
могла бы называться
xfs_cp,
а команда перемеще
•
n.iпux ................. .
1. ,ака 9,
Ф:iii.IOJШSI CIIC I t'\Ja 11 Sl , IJНI
Системные вызовы
зываются из
VFS open(2), stat(2), read(2), write(2), chmod(2) и т. д. вы
контекста процесса . Это также благодаря VFS, иначе пришлось
бы создавать разные методы для работы с файлами, в зависимости от фай
ловой системы . Настоящее бы веселье начал ось , когда нужно было скопи
ровать файл из раздел а , отформатированного как
ext4
в ХFS-раздел, то есть
когда файловые системы на разделах не совпадают. Какую тогда команду
использовать
ext4_cp
или
xfs_cp?
В общем , чтобы всех этих сложностей не
было, как раз и был добавлен уровень абстракции , называемый виртуальн.ой
файл овой сист емой .
VFS
реализует
open(2), stat(2), chmod(2)
и аналогичные системные вызовы.
Передаваемый им аргумент pathname используется VFS для поиска в кэше
записей каталога (также известном как кэш
dentry
или
dcache).
Он обеспе
чивает очень быстрый м еханизм поиска для преобразования имени пути
(имени файла) в определ енный
dentry.
Кэ ш "живет" в оперативной памяти и
никогда не сохраняется на диск : он существуют только для повышения про
изводительнос ти .
Кэш
dentry
предназначен для просмотра всего вашего файлового простран
ства. Поскольку большинство компьютеров не могут одновременно разме
стить все записи кэ ша в ОЗУ, некоторые биты кэша отсутствуют. Чтобы пре
образовать ваше имя пути в
созданию
dentry по
dentry, VFS ,
возможно , придется прибегнуть к
пути, а затем загрузить
inode. Это делается путем поиска
inode.
Отдельный
dent1y обычно имеет указатель на ин.дексный дескриптор (инод,
inode) . Иноды -это объекты файловой системы, такие как обычные файлы,
каталоги , FIFO и др . Они размещаются л ибо на диске (для файловых систем
блочных . устройств) , л ибо в памяти (для псевдофайлов111х систем). Индекс
ные дескрипторы , находящиеся на диске , при необходимости копируются в
память , а изменения в индекс н ых дескрипторах записываются обратно на
диск. На один индексны й дес криптор могут указывать несколько
dentry
(например , это делают жесткие ссыл ки) .
Для поиска индекса нужно , чтобы
VFS
вызвала метод
lookup() индекса роди
тельского каталога. Данный метод устанавливается конкретной реализацией
файловой системы , в которой находится индексный дескриптор.
Как только у
VFS
есть требуемый
dentry
(и , следовательно, индексный
дескриптор), мы можем делать все эти скучные вещи, такие как
open(2)
или
stat(2) .
•
.............................................................................. ..... .
Я : tро
l,inux
Операция
stat(2)
_______________________ t'tinux
довольно проста: как только
сматривает данные
VFS
получает
dentry, она про
и передает часть их обратно в пространство поль
inode
зователя.
Для открытия файла требуется еще одна операция: выделение файловой
структуры (это реализация файловых дескрипторов на стороне ядра). Только
•
что выделенная файловая структура инициализируется указателем на
и набором функций-членов файловой операции. Они взяты
Затем вызывается файловый метод
open(),
dentry
из данных inode.
чтобы конкретная реализация
файловой системы могла выполнять свою работу. Вы можете видеть, что это
еще одно переключение, выполняемое
VFS.
Файловая структура помещает
ся в таблицу файловых дескрипторов процесса.
Чтение, запись и закрытие файлов (и друтие операции
VFS)
выполняются
с использованием файлового дескриптора пользовательщюго пространства
для захвата соответствующей файловой структуры , а затем вызова требуе
мого метода файловой структуры для выполнения всего, что требуется. Пока
файл открыт, он использует dentry, что, в свою очередь, означает, что индекс
ный дескриптор
9.2.
VFS
все еще используется.
Регистрация и монтирование файловой
системы
Следующие системные вызовы используются для регистрации и отмены ре
гистрации файловой системы:
#include <linux/fs.h >
extern int register_filesystem (struct file_system_type *) ;
extern int unregister_filesystem (struct file system_type *) ;
Переданная структура .file_system _ type описывает вашу файловую систему.
Когда делается запрос на монтирование файловой системы в каталог в ва
шем пространстве имен ,
вызывает соответствующий метод
VFS
конкретной файловой системы. Новый
возвращаемое вызовом
vfsmount,
mount() для
ссылающийся на дерево,
->mount(), будет присоединен к точке монтирования,
•
так что при обращении к точке монтирования она будет указывать на ко-
ID--------· .. --.. --·---...... --...... -·. ·---.. ·---··· ... --·. --.. -···---·· -· ......... .
•
•
1Jlalla 9 . Фaiim111as1
t.'l.1nux ... ............... .
рень этого
vfsmount.
Все то же самое, как при монтировании через команд
ную строку. Например, вы монтируете к
устройство
CIICll.'Ma 11 SЦJJO
/dev/sda2.
/mnt/sda2
(это точка монтирования)
После монтирования каталог
/mnt/sda2 будет предо
/dev/sda2.
ставлять доступ к корню файловой системы, размещенной на
Файл
/proc/filesystems
содержит все файловые системы, поддерживаемые
ядром.
Cтpyктypafile_system_type описывает файловую систему. В ней определены
следующие члены:
struct file system_type {
const char *name ;
int fs_flags;
struct dentry * (*mount )
(struc~ fйе system_type *
const char * , void *);
void (*kill sb) (struct super_Ыock *) ;
struct module *owner ;
struct file system_type * next ;
struct list_head fs_supers ;
struct lock_class_key s lock_key ;
struct lock_class key s umount_key ;
int ,
};
Описание членов структуры приведено в табл .
Таблица
9.1.
Описание членов cmpyкmypыfile_system_type
Член структуры
пате
fs_Jl.ags
mount
kill- sb
•
9.1.
Описание
Имя типа файловой системы , например,
"iso9660", "xfs"
"xt4",
и т. д.
Различные флаги вроде
FS_REQUIRES_DEV, FS_
NO_DCACHE и т.д
Метод, вызываемый при монтировании нового эк-
земпляра этой файловой системы
Метод, вызываемый при закрытии экземпляра файловой системы
..-. -- --.--------------------------------------------------------------------------1111
И J \IIO
l .i1111x
....................... n.1n ux
Для внутреннего использования
owner
VFS:
в большинстве
случаев вы д ол жны инициализировать его значением
THIS- MODULE
Для внутреннего использования
next
VFS : вы должны
NULL
инициализировать это значен!fе
fs_supers
Для внутреннего использования
s_lock_key
Зависит от блокировки
s_ umount_ key
Зависит от блокировки
Аргументы метода
Табл ица
9.2.
mount()
приведены в табл .
Аргумен ты метода
9.2.
mount()
Описание
Аргумент
structfile_system_type *fs_type
Структура типа
(см.
Флаги монтирования
intflags
const char *dev-
file_system_type
9.1)
табл.
Имя монтированного устройства
пате
Произвольные параметры монтирования, обычно представляют собой стро -
void *data
ку
Метод
mount()
ASCII
должен возвращать корневую структуру дерева, запрошен
ную вызы вающей стороной. Активная ссылка на его суперблок должна быть
получена , а суперблок должен быть заблокирован. В случае ошибки он дол
жен вернуть
ERR_ PTR.
Аргум енты совпадают с аргументами
mount(2),
.
и их интерпретация зави
сит от типа файловой системы. Например , для блочных файловых систем
пате интерпретируется как имя блочного устройства, это устройство
dev
-
•
. . . . . . -- .... . ---. ---.. ---. - . --. - ·... ---.... --...... -. -... -.. -.. -. ---. -. -. ---. - .. -. -- ,
n..1nux .................. .
открывается , и если оно содержит подходящий образ файловой системы, ме
тод соответственно создает и инициализирует структуру
возвращая его корневой
Метод
мы
-
dentry
struct super_Ыосk,
вызывающей стороне.
может вернуть поддерево существующей файловой систе
->mount()
ему не нужно создавать новое . Основной результат с точки зрения вы
зывающей стороны
-
ссылка на
dentry
в корне дерева для присоединения;
создание нового суперблока является обычным побочным эффектом.
Наиболее интересным элементом структуры суперблока, который заполня
ет метод mount(), является поле "s_op". Это
operations'!, которая описывает следующий
указатель на "структуру
super_
уровень реализации файловой
системы.
Обычно файловая система использует одну из общих реализаций
mount()
и
вместо этого предоставляет обратный вызов fill_super() .
Общие варианты :
• mount_ bdev -
смонтировать файловую систему, находящуюся на блочном
устройстве.
• mount_nodev -
смонтировать файловую систему, которая не поддержива
ется устройством.
• mount_single -
смонтировать файловую систему, которая разделяет экзем
пляр между всеми монтируемыми.
Реализация обратного вызова
• struct super_Ыосk *sb -
fill_super()
имеет следующие аргументы:
структура суперблока. Обратньхй вызов должен
инициализировать ее надлежащим образом.
• void *data -
произвольные параметры монтирования, обычно представля
ют собой строку
• int silent- нужно
9.3.
ASCII
ли "молчать" об ошибке
(1)
или нет (О)
Объект суперблока
Объект суперблока представляет смонтированную файловую систему.
'. --.. --.. -.-.. --.. ---.. -.... -.. ---.. --.. -.-.. --.. --.. ---................-... --.·1111
И , 1ро
l ,i1111x
..... .. ... .. ........... ft1nux
9.3.1. Структура struct super_operations
Описывает, как именно
VFS
может манипулировать ' суперблоком в вашей
файловой системе. В ней определены следующие члены:
struct super_operations {
struct inode * (*all oc inode) (struct super_Ьlock *sb );
void (*destr oy_i node ) (struct inode *) ;
vo id (*dirty_inode) (struct inode * , int flags);
int (* write_inode ) (stru c t inode * , int) ; _
void (* drop_inode) (struct inode *) ;
void (*delete_inode ) (struct inode *);
void (*put super) (struct super_Ьlock *) ;
int (* sync_fs ) (stru ct super_Ьlock *sb , int wait );
int (*freeze fs) (struct super_Ьlock *) ;
int (*unfreeze f s ) (st ru ct supe r _Ьlock *) ;
int (*statf s ) (struct dentry * , struct kstatfs * );
int (*remou nt fs) (struct super_Ьlock * , int * , char *) ;
void (* c lear inode) (str uct inode *) ;
void (*umount_begin) (struct super Ыосk *) ;
int
(*sho w o ptions) (struct seq_file * , struct dentry * );
ssize t
(*quota_read ) (struct
super_Ьlock
* , int , char *, s i ze_t ,-
• loff_t) ;
ssize t (*quota_write) (struct super_Ыock * , int , const char * ,
size_t , loff_t ) ;
int (*nr_ca c hed_o bje c ts) (s tru c t super _Ьlock *) ;
void ( *free_cached_objects) (struct supe r _Ыock * , int) ;
};
Все методы вызываются без каких-либо блокировок, если не указано иное .
Это означает, что большинство методов можно безопасно блокировать. Все
методы вызываются только из контекста процесса (т.е. не из обработчика
прерывания или его нижней половины). Методы объекта суперблока при
ведены в табл.
Таблица
9.3.
9.3.
Методы объекта суперблока
•
. . ...................... ............................................................
) " 1ава 9. Фаiiлои:Ш CIICICJ\1:1 11 Sl,' \()O
n.1nux ...... .. . . ....... .
Оп ис ан ие
Метод
Данный метод вызы1:шется
alloc_inode() для выде
inode и ее инициализа
ления памяти для структуры
alloc inode
ции . Если эта функцl:Я не определена, выделяется
простой
"struct inode" . Обычно alloc_inode
использу
ется для выделения более крупной структуры , кото
рая содержит встроенный в нее
"struct inode"
Данный метод вызьiвается
вобождения ресурсов,
destroy_inode
destroy_inode() для ос
выделенных для struct inode.
Это нужно только в том случае, если была определе
на функция
->alloc_inode,
и она просто отменяет все
действия, сделанные функцией
->alloc _inode
Данный метод вы;3ывается виртуальной файловой
системой, когда индексный дескриптор помечен как
грязный. Обратите внимание: как грязный помеча
ется сам инод, а не его данные. Если обновление
dirty_inode
должно быть сохранено с помощью
.
fdatasync() , тог
да
1_DIRTY_ DATASYNC будет установлен в аргу
менте флагов. 1_DIRTY_ ТIМЕ будет установлено во
флагах в случае, если включено отложенное время,
и
struct inode
имеет время обновления с момента по
следнего вызова
Метод вызывается, когда
write inode
->dirty_inode
VFS
необходимо записать
индексный дескриптор на диск . Второй параметр
указывает, должна ли запись быть синхронной или
нет, не все файловые системы проверяют этот флаг
Вызывается, когда последний доступ к индекс
ному узлу отбрасывается с удерживаемой спин
блокировкой
drop_inode
inode->i_lock. Этот метод должен
быть либо NULL (нормальная семантика файловой
системы UNIX), либо "generic_delete_inode" (для
файловых систем, которые не хотят кэшировать
индексные дескрипторы, что приводит к тому, что
"delete_inode"
всегда вызывается независимо от зна
чения
i_ nlink)
•-~ -----------------------. ---------.-------------. --. -.--.-.· -----. -----------------1111
И , 11111
l.i1111,
delete- inode
....................... ftlnux
Вызывается , когда
Вызывается , когда
put_super
VFS
VFS
хочет удалить индекс
хочет освободить суперблок
(т,е. размонтировать). Обычно вызывается при удер-
живаемой блокировке суперблока
Вызывается , когда
sync.Js
VFS
записывает все грязные
данные, связанные с суперблоком . Второй параметр
указывает, должен ли метод ожидать завершения за~
писи. Необязательный метод
Вызывается , когда
freeze.Js
VFS
блокирует файловую систе-
му и переводит ее в согласованное состояние. Этот
метод в настоящее время используется диспетчером
логических томов
unfreeze.Js
statfs
Вызывается , когда
VFS
(LVM)
разблокирует файловую си-
стему и снова делает ее доступной для записи
Вызывается , когда
VFS
необходимо получить стати-
стику файловой системы
Вызывается при перемонтировании файловой систе-
remount.Js
мы. Метод вызывается с удерживаемой блокировкой
ядра
clear- inode
umount_ begin
show_ options
quota read
Если вызывается , то
VFS
очищает индексный
дескриптор. Необязательный метод
Вызывается , когда
VFS
размонтирует файловую
систему
Вызывается
VFS
для отображения параметров мои-
тирования для
Вызывается
VFS
/proc/<pid>/mounts
для чтения из файла квоты файло вой системы
11!1- - ---------------------~-------·--···---·--··---··-········-·--------·--·--···--- '
) Jl:111:1
n..1nux .................. .
Вызывается
quota_ write
VFS
9 . Фаiiло11:ш CIJClt.'M:I 11 SЩl)CI
для з аписи в файл квоты файло во й
системы
Вызывается функцией сокр ащения кэша
sb для
фай-
ла вой системы , чтобы вернуть количество содер-
nr_cached_objects
жащихся в ней свободных кэшированных объектов .
Необязательный метод
Вызывается функцией сокращения кэша
sb для
файловой системы , чтобы сканировать указанное
количество объектов , чтобы попытаться их освобо -
дить. Необязательно , но любая файловая система,
реализую щая этот метод, должна также реализ ов ать
->nr_ cached _ objects, чтобы
он вызывался правильно.
Мы ничего не можем сделать с ошибками, с которыми может столrшуться файловая система, отсюда и
free _ cache_ objects
возвращаемый тип
void.
Реализации должны включать условные вызовы
повторного планирования внутри любого выпал няемого цикла сканирования. Это позволяет
VFS
определять подходящие размеры пакето"в сканирова-
ния , не беспокоясь о том, не вызовут ли реализации
проблемы задержки из-за больших размеров пакетов
сканир ования
9.3.2.
Структура
struct xattr_handlers
В файл овых системах , поддерживающих расш иренные атрибуты
поле суперблока
s_xattr
указывает на массив обработчиков
ющийся нулем . Расширенные атрибуты
•
пат е
-
-
(xattrs ),
xatt,-, оканчива
это пары имя:значение :
указывает, что обработчик сопоставл я ет атрибуты с указанным
именем (например , "system.posix_acl_access"); поле префикса должно
быть
•
NULL.
.---.----.. --.-.------...-.. ---.---.-.------.-.-.... ---.---.----... -.-... ---.-----Cil
•
Я , 1р11 l.iJHI\
....................... f.l1nux
• prefix - указывает, что обработчик сопоставляет все атрибуты с указанным
префиксом имени (например, "user"); поле имени должно быть NULL.
• list - определяет, должны ли атрибуты, соответствующие этому обработ
чику xattr, быть перечислены для определенного dentry. Используется не
которыми реализациями listxattr, такими как generic _listxattr.
• get -
вызывается
VFS
для получения значения определенного расширен
ного атрибута . Этот метод вызывается системным вызовом
• set -
вызывается
VFS
getxattr(2).
для установки значения определенного расширен
ного атрибута. ~огда новое значение равно
NULL,
вызывается для уда
ления определенного .расширенного атрибута. Этот метод вызывается
системными вызовами
9.4.
setxattr(2)
и
removexattr(2).
Объект инода
Объект инода представляет собой объект внутри файловой системы. Струк
тура
struct inode_operations
описывает, как именно
VFS
может манипулиро
вать инодами в файловой системе . Структура описана так:
struct inode_operations {
int (*create) (struct user_namespace *, struct inode *, struct dentry
*, umode_t , bool) ;
struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned
int) ;
int (*link) (struct dentry *,struct inode *, struct dentry *) ;
int (*unlink) (struct inode * , st r uct dentry *);
int (*symlink) (struct user_namespace *, struct inode *, struct dentry
*, const char *) ;
int (*mkdir) (struct user_namespace *, struct inode *, struct dentry
*, umode_t) ;
int (*rmdir) (stru.c t inode * , struct dentry *);
int (*mknod) (struct user_namespace *, struct inode *, struct dentry
*, umode_t , dev_t) ;
int (*rename) (struct user_namespace *, struct inode *, struct dentry
*,
struct inode *, struct dentry * , unsigned int);
int (*read lin k) (struct dentry * , char _user * , in t);
const char * ( *get link) (struct dentry * , struct inode * ,
struct delayed_call *);
int ( *permission) (s truct user_ namespace *, struct inode *, int) ;
struct posix_acl * (*get inode acl) (struct inode * , int, bool);
int (*setattr) (struct user_namespace * , struct dentry *, struct
iattr *) ;
1111- :·-------------------------···:··------------------ ----------- ---- -- --- ---------'
n.1пux .................. .
1 . rава
9.
(l):1ii.юн:н1 Cll{'ll'M:t II щ1ро
int (*getattr) (struct user_namespace * , const struct path *, struct
kstat *, u32 , unsigned int) ;
ssize_t (*listxattr) (struct dentry * , char * , size_t);
void (*update time) (struct inode * , struct timespec * , int);
int (*atomic_open) (struct inode *, struct dentry * , struct file * ,
unsigned open_flag , umode t create_mode);
int (*tmpfile) (struct user_namespace * , struct inode * , struct file
* , umode_t) ;
struct posix_acl * (*get_acl) (struct user_namespace *, struct dentry
*, int) ;
int (*set_ acl) (struct user_namespace * , struct dentry * , stru c t
posix_acl * , int) ;
int (*fileattr_set) (struct user_ namespace *mnt_userns ,
struct dentry *dentry, struct fileattr *fa);
int (*fileattr_get) (struct dentry *dentry , struct fileattr *fa) ;
};
Нужно отметить, что все методы (табл.
9.4)
могут вызываться без каких
либо блокировок.
Таблица
9.4.
Методы объекта инодов
Метод
Описание
Вызывается системными вызовами
open(2) и creat(2). Требует-
ся только в том случае, если вы хотите поддерживать обычные
create
файлы. Записи
dentry,
которые вы получаете, не должны иметь
индекса (то есть это должен быть отрицательный
вы , вероятно, вызовете
dentry) . Здесь
d_instantiate() с dentry и только
что соз•
данным индексным дескриптором
Вызывается, когда
VFS
необходимо найти индексный дескрип-
тор в родительском каталоге. Имя, которое нужно искать , на•
ходится в
dentry.
lookup
d_add(), чтобы
"i_count" в структуре
Этот метод должен вызвать
вставить найденный
inode в dentry.
Поле
inode должно быть увеличено. Если указанный inode не существует, в dentry следует вставить NULL inode (это называется
отрицательным dentry). Возврат ко.1;1а ошибки из этой подпрограммы должен выполняться только при реальной ошибке ,
иначе создание
как
inode с
помощью системных вызовов , таких
create(2), mknod(2), rnkdir(2)
хотите перегрузить методы
и т. д., не удастся. Если вы
dentry,
вам следует инициали-
"d_dop" в dentry; это указатель на структуру
"dentry_operations". Этот метод вызывается с удерживаемым
зировать поле
~,
семафором индексного дескриптора каталога
.. ... . .... .. ... . .. .. .... .... . ..... -···- ·· . ... . ...... -- .... ...... . ····--· ....... --- -
Я . 1ро (,iш1,
................. .-.....
Вызывается системным вызовом
link
Вам , вероятно, потребуется вызвать
d_instantiate()
create()
Вызывается системным вызовом
в
так же, как в
unlink(2) . Требуется только
в
том случае, если вы хотите поддерживать удаление инодов
Вызывается системным вызовом
symlink
link(2). Требуется только
том случае, если вы хотите поддерживать жесткие ссылки .
методе
unlink
t\.iпux
symlink(2).
Требуется только
в том с лучае, если вы хотите поддерживать символические
·ссылки . Вам, вероятно , потребуется вызвать
d_instantiate() так
же, как в методе create()
Вызывается системным вызовом
mkdir
rnkdir(2).
гов. Вам, вероятно, потребуется вызвать
d_instantiate()
create()
как в методе
rmdir
Вызывается системным вызовом
rmdir(2).
так же ,
Требуется только в
том случае, если вы хотите поддерживать удаление подкаталогов
Вызывается системным вызовом
устройства
mknod
Требуется только в
том случае, если вы хотите поддерживать создание подкатало
(char,
mknod(2)
для создания
Ыосk) , именованного канала
'·
(FIFO)
inode
или со-
кета . Требуется только в том случае, если вы хотите поддерживать создание этих типов инодов . Вам , вероятно , потребуется
вызвать
d_instantiate()
так же , как в методе
Вызывается системным вызовом
create()
rename(2) для переименова
ния объекта , чтобы родитель и имя были заданы вторым индексным узлом и
dentry.
Файловая система должна возвращать
-EINVAL для
любых не
поддерживаемых или неизвестных флагов . В настоящее время
реализованы следующие флаги:(!)
RENAME_NOREPLACE:
этот флаг указывает, что если цель переименования существу -
rename
ет, переименование должно завершаться с ошибкой
-EEXIST
вместо замены цели. VFS уже проверяет существование, по
этому для локальных файловых систем реализация
RENAME_
NOREPLACE эквивалентна простому переименованию. (2)
RENAME_EXCHANGE: обмен источником и целью . Оба
должны существовать; это проверяется VFS. В отличие от про
стого переименования , источник и цель могут быть разных
ти пов
.,
. ...................................................................................
Глава
n..inux __ ____ __ ___ ___ __ ___
Вызывается
get_link
VFS
9. Файловая
сисrема и ядро
для перехода по символической ссылке к
индексному узлу, на который он указывает. Требуется только в
том случае, если вы хотите поддерживать символические ссылки
Теперь это просто переопред еление для использования
readlink
readlink(2) в случаях, когда ->get_link использует ndjump_
link() или объект на самом деле не является символической
ссылкой. Обычно файловые системы должны реализовы вать
->get_link только
для символических ссылок, и
readlink(2)
бу-
дет использовать это автоматически
Вызывается
permission
VFS
для проверки прав досту па к
рую
rcu-walk
не может обработать , верните
снова будет вызван в режиме
setattr
getattr
listxattr
POSIX-
подобной файловой системе. Если возникает ситуация, кото-
-ECHILD,
ref-walk
и он
Вызывается
зывается
VFS для установки атрибутов файла. Этот метод выchmod(2) и соответствующими системными вызовами
Вызывается
вызывается
Вызывается
VFS для получения атрибутов файла. Этот метод
stat(2) и соответствующими системными вызовами
VFS для отображения всех расширенных атрибутов данlistxattr(2)
ного файла. Этот метод вызывается системным вызовом
Вызывается
update_time
VFS для обновления определенного времени или
i_version индексного дескриптора. Если это не определено,
VFS сама обновит индекс и вызовет mark_inode_dirty_sync
Вызыв ается последний открытый компонент. Используя этот
необязательный метод, файловая система может искать, возможно, создавать и открывать файл за одну атомарную операцию. Если он хочет оставить фактическое открытие для
вызывающей стороны (например, если файл оказался символической ссылкой, устройством или просто чем-то, для чего
файловая система не будет выполнять атомарное открытие), он
atomic_ ореп
может сигнализировать об этом, возвращая
dentry).
finish _ no_ open(file,
Этот метод вызывается только в том случае, если по-
следний компонент отрицателен или нуждается в поиске.
Кэшированные пол ожительные записи
dentry по-прежнему
f_op->open(). Если файл был создан, флаг
FMODE_CREATED должен быть установлен в файл->f_mоdе.
В случае О_EXCL метод должен быть успешным только в том
случае, если файл не существует, и, следовательно, FMODE_
CREATED всегда долже н быть установлен в случае успеха
обрабатываются
.,.... --... -.. ---.--.----.-.-----.-.·-------.. -.-.. --.--------.--.. -..... --.. --.----1111
Я J tpo (,iщ1х
: .............. _....... t\.inux
Вызывается в конце О
TMPFILE open(). Необяза:гельно, эквивалентно атомарному ~озданию, открытию и удалению файла
в ·заданном каталоге. В случае успеха необходимо вернуться с
tmp.file
уже открытым файлом; это можно сделать, вызвав finish_open_
simple()
прямо в конце
Вызывается в ioctl(FS_IOC_GETFLAGS) и ioctl(FS_IOC_
FSGETXATTR) для получения различных флагов и атрибутов
.fileattr_get
файлов. Также вызывается перед соответствующей операцией
SET,
чтобы проверить, что изменяется (в данном случае с за-
блокированным эксклюзивным
вернитесь к
Вызывается в
.fileattr_ set
FSSETXATTR)
i_rwsem). Если
f_op->ioctl()
ioctl(FS_IOC_SETFLAGS)
ioctl(FS_IOC_
для изменения флагов и атрибутов различных
файлов. Вызывающие удерживают эксклюзивный
Если не установлено, вернитесь к
9.5.
и
не установлено,
i_rwsem.
f_op->ioctl()
Объект адресного пространства
9.5.1.
Общая информация
Объект адресного пространства используется для группировки и управле
ния страницами в кэше страниц. Его можно использовать для отслеживания
страниц в файле (или чего-либо еще) , а также для отслеживания отображе
ния разделов файла в адресные пространства процесса.
Существует ряд различных, но связанных между собой услуг, которые мо
жет предоставлять адресное пространство. К ним относятся сообщение о
нехватке памяти, поиск страниц по адресу и отслеживание страниц, поме
ченных как "грязные"
(dirty)
или "обратная запись"
(writeback).
Первый можно использовать независимо от остальных. ВМ может попы
таться либо записать грязные страницы, чтобы очистить их, либо выпустить
чистые страницы, чтобы использовать их повторно. Для этого он может вы
зывать метод
фолиантов
-
->writepage для грязных страниц и ->release_folio для чистых
(folios) с установленным флагом private. Чистые страницы без
PagePrivate и без внешних ссылок будут выпущены без уведомления в адрес
ном пространстве .
--.. ----------------. --------. ---. -------------. ---. ---- . ---. ------------------_,
J 1,111,1 1) (J):lli . 11111:HI Cllt' 1 t'\1:1 11 11 IIIO
n.1nux .................. .
Примечание. Фолианты
(folios) памяти Linux предназначены
для того, чтобы файловые системы и кэш страниц могли управ•
лять памятью фрагментами, превышающими размер страницы
по умолчанию.
Для достижения этой функциональности страницы должны быть помещены
в
LRU
с
lru_cache_add,
а
mark_page_active
должен вызываться всякий раз,
когда страница используется.
Страницы обычно хранятся в индексе системы счисления с помощью
->index. Это дерево поддерживает информацию о статусе PG_Dirty и
PG_ Writeback каждой страницы, так что страницы с любым из этих флагов
можно быстро найти.
•
Тег
Dirty в основном используется mppage_ writepages - методом по умол
-->.writepages. Он использует тег для поиска грязных страниц для
вызова ->writepage. Если mpage_writepages() не используется (т. е. адрес
предоставляет свой собственный -->writepages), тег PAGECACHE_TAG_
DIRTY практически не используется. write_inode_now и sync_inode ис
пользуют его (через _sync_single_inode), чтобы проверить , удалось ли
->writepages записать все адресное пространство address_space.
чанию
Тег обратной записи используется функциями
через
filemap Jdatawait_range
filemap*wait*
и
sync_page*
для ожидания завершения всей обратной за
писи.
Обработчик адресного пространства может прикреплять к странице до
полнительную информацию, обычно используя поле
"private"
на "странице
структуры". Если такая информация прикреплена, должен быть установлен
флаг
PG_Private. Это заставит различные подпрограммы виртуальной маши
address_space для обработ
ны делать дополнительные вызовы обработчику
ки этих данных .
Адресное пространство действует как промежуточное звено между храни
лищем и приложением . Данные считываются в адресное пространство по
целой странице за раз и предоставляются приложению либо путем копиро
вания страницы, либо путем отображения страницы в памяти. Данные за
писываются в адресное пространство приложением, а затем записываются
обратно в хранилище , как правило , целыми страницами , однако адресное
пространство
писи
•
address_space имеет более точный
контроль над размерами за
.
·-------------------------- ------- ---------------------------- -------------------- 8 : D
Я , tро l , i1111,
....................... rlinux
Процесс чтения по существу требует только
"read_ folio", Процесс записи бо
лее сложен и использует write_ begin/write_ end или dirty Jolio для записи дан
ных в адресное пространство address_space, а также writepage и writepages
для обратной записи данных в хранилище.
Добавление и удаление страниц в/из адресного пространства защищено
mutex индексного
i_
дескриптора .
Когда данные записываются на страницу, должен быть установлен флаг
PG_Dirty.
Обычно он остается установленным до тех пор, пока
writepage
установить PG_
не попросит его записать. Это должно очистить PG_ Dirty и
Writeback. На самом деле его можно записать в любой момент после очистки
PG_Dirty. Как только становится известно, что он безопасен, PG_Writeback
очищается.
Обратная запись использует структуру
операциями . Это дает операциям
writeback_contro/ для управления
writepage и writepages некоторую инфор
мацию о характере и причине запроса обратной записи , а также об ограни
чениях, при которых они выполняются.
9.5.2.
Большинство
Обработка ошибок во время обратной записи
приложений,
выполняющих
буферизованный
периодически используют вызов синхронизации файлов
ввод-вывод,
(fsync, fdatasync,
msync или sync_file _range ), чтобы убедиться , что записанные данные попали
в резервное хранилище. Когда возникает ошибка во время обратной записи,
они ожидают, что об этой ошибке будет сообщено при выполнении запроса
.на синхронизацию
файлов. После получения сообщения об ошибке в одном
запросе последующие запросы к тому же файловому дескриптору должны
возвращать О, если только после предыдущей синхронизации файлов не воз
никло новых ошибок обратной записи.
В идеале ядро будет сообщать об ошибках только в тех описаниях файлов,
в которых были выполнены записи, которые впоследствии не удалось
записать обратно. Однако универсальная инфраструктура кэша страниц
не отслеживает описания файлов, которые загрязнили каждую отдельную
страницу, поэтому определить, какие файловые дескрипторы должны воз
вращать ошибку, невозможно.
•
at-· ................................................................................
1 1,111а !) (J);1ii.1111нн1 t·11t·н·,ш 11,111ю
n.inux .................. .
Вместо этого универсальная инфраструктура отслеживания ошибок с обрат
ной записью в ядре разрешает сообщать об ошибках в
fsync
для всех опи
саний файлов , которые были открыты во время возникновения ошибки. В
ситуации с несколькими модулями записи все они вернут ошибку при после
дующей
fsync,
даже если все записи, выполненные через этот конкретный
файловый дескриптор, завершились успешно (или даже если записи в этот
файловый дескриптор вообще не производились).
Файловые системы , которые хотят использовать эту инфраструктуру, долж
ны вызывать функцию тар _set_error для записи ошибки в адресном про
странстве , когда она возникает. Затем , после обратной записи данных из
кэш а страниц в операции
advance_wb_err, чтобы
file->fsync,
они должны вызвать .fi[f:_ check_and_
убедиться , что курсор ошибки файла структуры пе
реместился в правильную точку в потоке ошибок, выдаваемых поддержива
ющим устройством (устройствами).
9 .5.3.
Структура
sutruct address_ space_ operations
Данная структура описывает, как
VFS может манипулировать сопоставлени
ем файла с кэшем страниц в вашей файловой системе. Содержит следующие
члены:
struct address space_ operati o ns {
int (*writepage) (struct page *page, struct writebac k_cont r ol *wb c );
int (*read_folio) (struct file * , struct folio * ) ;
int (*writepages) (struct address_space *, struct writeback_ control
*) ;
,
boo l (*dirty_foli o ) (struct add r ess_space * , struct fol i o * ) ;
void (*readahead ) (struct readahead_control *) ;
int (*write_begin) (struct fi l e * , struct address _ space *mapp ing ,
loff_ t pos , unsigned len ,
struct page **pagep , void **fsdata) ;
int (*write end) (struct file * , st r uct address_space *mapp ing ,
loff_t pos , uns i gned len , unsigned copied ,
stru c t p a ge *page , void *fsdata) ;
sect o r_t (*bmap) (struct address_space * , sector_t );
void (*invalidate_ f o lio) (struct folio *, size_ t start , size t l en ) ;
b oo l (*release f o lio) (struct folio * , gfp t );
vo id (*free foli o ) (struc t f o lio *) ;
ssize t (*direct IO) (struct kiocb * , struct iov ite r *ite r ) ;
int ( ~migrate_folio) (struct mapping * , struct folio *dst ,
struct f o lio *src , enum migrate_mode) ;
........................................ . .................................... .. .. .
И , 11ю l ,i1111,
............... . . ___ ... t\.1nux
int (*launder_folio)
(struct folio *) ;
bool (*is_partially_uptodate)
(struct folio * , size_t f r om ,
size_t count) ;
void (*is_dirty_writeback) (struct folio * , bool * , bool *) ;
int (*error_remove_page) (struct mapping *mapping , struct page
*page );
int (*swap_activate ) (struct swap_info_struct *sis , struct file *f ,
sector_t *span)
int (*swap_deactivate) (struct file *) ;
i n t (*swap_rw ) (struct kiocb *iocb , s t ruct iov i ter *iter );
};
Таблица
9.5.
Члены структуры
address_space_operations
Член структуры
Описание
Вызывается виртуальной машиной для записи грязной
страницы в резервное хранилище, Это может произойти
из соображений целостности данных (например, "синхронизации") или для освобождения памяти (сброс), Раз-
ницу можно увидеть в
wbc->sync_mode. Флаг PG_Dirty
PageLocked равно true. writepage должен
должен установить PG_Writeback и убе-
снят, а значение
начать запись,
диться , что страница разблокирована , либо синхронно ,
writepage
либо асинхроюю, когда операция записи завершится.
Если wbc->sync_mode равен WB_SYNC_NONE,
->writepage не нужно слишком стараться , если есть
проблемы , и может выбрать запись других страниц из
сопоставления , если это проще (например , из-за внутренних зависимостей) . Если он решит не начинать за-
пись, он должен вернуть АОР _ WR1TEPAGE_ACTIVATE,
чтобы виртуальная машина не продолжала вызывать
->writepage на этой странице
•
I D - ---------------------------------·-·····-----------··:···------------------------·
1.1,ша 9. Фаii . ~овая с11с1е,ш II s1.1po
n.inux _________________ _
Вызывается кэшем страниц для чтения фолианта из ре
зервного хранилища. Аргумент "файл" предоставляет
информацию для аутентификации в сетевых файловых
системах и обычно не используется блочными файловы
ми системами. Он может быть равен
NULL,
если у вызы
вающей стороны нет открытого файла (например , если
ядро выполняет чтение для себя, а не от имени процесса
пользовательского пространства с открытым файлом).
Если сопоставление не поддерживает большие фолиан
ты, фолиант будет содержать одну страницу. Фолиант
будет заблокирован при вызове
read_folio.
Если чтение
завершается успешно, фолио должно быть помечено как
актуальное. Файловая система должна разблокировать
фолио после завершения чтения, независимо от того,
было ли оно успешным или нет. Файловой системе не
_нужно
изменять счетчик ссылок на фолио; кэш страницы
содержит счетчик ссылок, и он не будет выпущен, пока
фолио не будет разблокировано .
readJolio
Ф айловые системы могут реализовывать
->read_ folio()
синхронно . При нормальной работе фолианты читаются
с помощью метода
->readahead().
Только в случае не-
удачи или если вызывающей стороне нужно дождаться
завершения чтения, кэш страницы вызовет
->read_folio().
Файловые системы не должны пытаться выполнить соб
ственное упреждающее чтение в операции
->read_folio().
Если файловая система не может выполнить чтение в
данный момент, она может разблокировать фолиант,
выполнить любое действие, необходимое для обеспе
чения успешного чтения в будущем, и вернуть АОР _
TRUNCATED_PAGE. В
этом случае вызывающая сто
рона должна найти фолиант, заблокировать его и снова
вызвать
->read folio.
Вызывающие могут вызывать метод
мую, но использование
->read_fo lio() напря
read_mapping_folio() позаботится
о блокировке, ожидании завершения чтения и обработке
таких случаев, как АОР _ TRUNCATED_PAGE
•
.-------------------------------------------- -------------------.. --.---------.---tв
И . 1р11
l.i1111,
....................... n..inux
Вызывается виртуальной машиной для записи страниц,
связанных с объектом address _ space. Если wbc·>sync _
mode равен WB_SYNC_ALL, то writeback_control укажет
диапазон страниц, которые должны быть записаны . Если
writepages
это
WB_SYNC_NONE,
то дается
nr_to_write
и , по воз-
можности, должно быть записано столько страниц . Если
параметр
•>writepages не указан, вместо него используmpage_writepages. Он выберет страницы из адресного пространства, помеченные как DIRTY, и передаст
их •>writepage
ется
Вызывается виртуальной машиной, чтобы пометить
фолиант как грязный . Это особенно необходимо, если
адресное пространство связывает личные данные с фо•
dirtyJolio
лио, и эти данные необходимо обновлять, когда фолиант
"загрязняется". Он вызывается, например, при измене-
нии отображаемой страницы памяти. Если он определен,
он должен установить флаг
ка
dirty фолианта и метку
PAGECACHE_TAG_DIRTY в i_pages
поис•
Вызывается виртуальной машиной для чтения страниц,
связанных с объектом
address_ space.
Страницы
расположены последовательно в кэше страниц и
заблокированы. Реализация должна уменьшать
счетчик ссылок на страницу после запуска ввода-
вывода на каждой странице . Обычно страница будет
разблокирована обработчиком завершения вводавывода. Набор страниц делится на несколько страниц
синхронизации, за которыми следуют нескол ько
асинхронных страниц, член
readahead
rac->ra->async_ size
дает количество асинхронных страниц . Файловая
система должна попытаться прочитать все страницы
синхронизации , но может решить остановиться , как
только достигнет асинхронных страниц . Если будет
решено прекратить попытки ввода-вывода, можно
просто выполнить
retum. Вызывающий удалит
оставшиеся страницы из адресного пространства,
разблокирует их и уменьшит счетчик ссылок
(refcount)
PageUptodate, если ввод •вывод
Установка PageError на л юбой
на страницы . Установите
завершился успешно.
странице будет проигнорирована; просто разблокируйте
страницу, если произойдет ошибка ввода•вывода
4
'
ID- .. --. -----. ------------------------------.---. --------------. -------------------.
1 1ава !) (J).til. IOll,HI CIH' 1 t'\J.I 11 SI IIНI
rtinux ............. _____ _
Вызывается общим кодом буферизованной записи, чтобы
попросить файл овую систему подготовиться к записи
длинных байтов по заданному смещению в файле.
dress _space должен
Ad-
проверять возможность завершения
записи , выделяя пространство, если это необходимо ,
и выполняя любые другие внутренние операции. Если
запись будет обновлять части любых базовых блоков в
хранилище , то эти блоки должны быть предварительно
write_ begin
прочитаны (если они еще не были прочитаны) , чтобы
обновленные блоки можно было правильно записать.
Файловая система должна возвращать заблокированную
страницу кэша страниц для указанного смещения в
*pagep, чтобы
вызывающая сторона могла выполнять
запись .
Возвращает О в случае успеха; < О в случае сбоя (это код
ошибки) , и в этом случае
write_end не
вызьIВается
После успешного выполнения
write_begin и копирования
write_end. len - это исходв write_ begin, а copied - это раз-
данных необходимо вызвать
ная длина, переданная
мер, который удалось скопировать.
write end
Файловая система должна позаботиться о разблокировке
страницы и освобождении ее
лении
Возвращает
<О
refcount,
- Size.
а также об обнов-
1
в случае ошибки, в противном случае
количество байтов
(<=
"скопировано") , которые удалось
скопировать в кэш страниц
Вызывается виртуальной файловой системой для сопоставл ения смещения логического блока внутри объекта
с номером физического блока. Этот метод используется
ioctl
Ьтар
FIВMAP и для работы с swар-файлами. Чтобы мож-
но был о переключиться на файл, файл должен иметь стабильное сопоставление с блочным устройством. Система
подкачки не проходит через файловую систему, а вместо
этого использует
bmap, чтобы узнать,
где находятся бло-
ки в файле , и напрямую испол ьзует эти адреса
•
·················································································· - I D
Я . tро l.iпux
____________ ........... t'1..inux
Если фолиант содержит приватные данные, тогда будет
вызываться
invalidate_folio,
когда часть или весь фолиант
должен быть удален из адресного пространства . Обычно
это соответствует усечению, перфорации или полному
аннулированию адресного пространства (в последнем
случае "смещение" всегда будет равно О , а "длина"
invalidateJolio
folio_size()) . Любые личные данные,
-
связанные с фоли-
антам , должны быть обновлены, чтобы отразить это усечение . Если смещение равно О, а длина равна
fo\io_size(),
то личные данные должны быть освобождены, потому
что фолиант должен быть полностью отброшен . Это
можно сделать, вызвав функцию _ ->rеlеаsе_fоliо, но в
этом случае выпуск ДОЛЖЕН завершиться успешно
Вызывается для фолианта с закрытыми данными, чтобы
сообщить файловой системе, что фолиант будет освобожден. Метод
->release_fo\io должен
удалить все лич-
ные данные из фолианта и снять флажок "приватный" .
Если функция
release_folio()
должна возвращать значение
завершается ошибкой, она
false. release_folio()
исполь-
зуется в двух разных, но связанных случаях . Во-первых,
когда виртуальная машина хочет освободить чистый
releaseJolio
фолиант без активных пользователей. В случае успеха
->release_folio
фолиант будет удален из
address_space
и
освобожден.
Второй случай
-
когда был сделан запрос на аннули-
рование некоторых или всех фолиантов в
address_ space.
Если файловая система делает такой В1'IЗОВ , она должна
быть уверена, что все фолианты признаны недействительными
Вызываетс:я , когда фолиант больше не отображается в
freeJolio
кэше страниц , чтобы разрешить очистку любых личных
данных
Вызывается общими процедурами чтения/записи для
выполнения
direct- !О
direct_IO -
то есть запросов ввода-вывода,
которые обходят кэ ш страниц и передают данные неттосредственно между хранилищем и адресным простран-
ством приложения
•
8 1 8 · · · · ·-····-·······································································
I . ,ана
n.inux _________________ _
9.
Фаii.1овая
c11cIr\la II sI.1po
Используется для сокращения использования физиче
ской памяти. Если виртуальная машина хочет переме
стить фолиант (возможно, с запоминающего устройства,
migrateJolio
сигнализирующего о неизбежном сбое), она передаст
этой функции новый фолиант и старый фолиант. Метод
migrate_fo\io
должен передавать любые личные данные и
обновлять все имеющиеся у него ссылки на .фолиант
Вызывается перед освобождением фолианта
launderJolio
-
для oб-
ратноif записи "грязного" фолианта. Фолиант остается
заблокированный на протяжении всей операции
Вызывается виртуальной машиной при чтении файла из
кэша страниц, когда базовый размер блока меньше paз-
is_partially_uptodate
мера фолианта . Если требуемый блок актуален, то чтение может завершиться без необходимости ввода-вывода
для обновления всей страницы
Вызывается виртуальной машиной при попытке вос
становить фолиант. Виртуальная машина использует
"грязную" информацию и информацию обратной записи,
чтобы определить, нужно ли ей останавливаться, чтобы
дать очистителям шанс завершить некоторые операции
ввода-вывода. Обычно она может использовать
is_ dirty_ writeback
test_dirty
и
folio _ test_ writeback,
folio_
но некоторые файловые
системы имеют более сложное состояние (нестабильные
фолианты в
NFS
предотвращают восстановление) или
не устанавливают эти флаги из-за проблем с блокиров
кой. Этот обратный вызов позволяет файловой системе
указать виртуальной машине, следует ли рассматривать
фолиант как грязный или с обратной записью в целях
приостановки
Обычно устанавливается в geпeric _ error_remove_
error_remove_page
page,
если усечение допустимо для этого адресного
пространства. Используется для обработки сбоев памяти
•
.------------------.. ---- ----.---------- -------------.. --.. ------------.. --.. ------&1
•
}t , чт l.itlll\
...................... . r.l1nux
Вызывается для подготовки данного файла к обмену. Он
должен выполнять любую проверку и подготовку, необходимые для обеспечения того, чтобы запись могла вы-
полняться с минимальным выделением памяти. Он должен вызывать
swap_activate
функцию
add_ swap_ extent() или вспомогательную
iomap_swapfile_activate() и возвращать коли-
чество добавленных экстентов . Если ввод-вывод должен
быть отправлен через
->swap_rw(), он должен устаноSWP _FS _ OPS, иначе ввод-вывод будет отправлен
непосредственно на блочное устройство sis->bdev
вить
Вызывается во время
swapoff для файлов ,
activate был успешным
swap_deactivate
Объект
swap _
Вызывается для чтения ици записи страниц подкачки ,
swap_rw
9.6.
где
когда установлен
SWP_FS_OPS
File
Файловый объект представляет собой файл, открытый процессом. Cтpyктy
pafile_ operations описывает,
как
VFS
может манипулировать открытым фай
лом. Содержимое структуры:
struct file_operations
struct module *owner;
loff_t (*llseek) (struct file * , loff_t, int);
ssize t (*read) (struct file *, char
user * , size t , loff_t *) ;
ssize t (*write) (struct file * , const char _user * , size_t , loff_t
*);
ssize t (*read_iter) (struct kiocb * , struct iov_iter *);
ssize_t (*write_iter) (struct kiocb *, struct iov_iter *) ;
int (*iopoll) (struct kiocb *kiocb , bool spin) ;
int (*iterate) (struct· file * , struct dir context *);
int (*iterate_shared) (struct file * , struct dir_context *);
_ poll t (*poll) (struct file * , struct poll_taЫe_struct *) ;
long (*unlocked_ioctl) (struct file * , unsigned int , unsigned long) ;
long (*compat ioctl) (struct file * , unsigned int , unsigned long) ;
int (*mmap) (struct file *, struct vm_ area struct *) ;
int (*open) (struct inode *, struct file *) ;
int (*flush) (struct file * , fl_owner_ t id) ;
int (*release) (struct inode * , struct file *) ;
. ... -- -- -- --- -- -- --
. . . . . . .
-- .. ----. ---
. . . . .
--- ....... ---
. . . . . . . . .
--- ... ----
. . . . . .
_
,
1 J1ава ') Фа~i . юв:ш t·11c1t·,i:111 s1 . 11ю
rlinux _________ __. ______ _
int (*fs ync) (str uct file * , loff_t , loff_t , int datasync) ;
int (*fasync) (int , struct file * , int) ;
int (*lock) (struct file *, int , struct file lock *);
ssize t (*sendpage) (struct fi le * , struct page * , int , size t ,
loff t *, int) ;
unsigned long (* get_unmapped area) (struct file * , unsigned long ,
unsigned long , unsigned long , uns i gned long) ;
int (*check_flags) (int);
int (*flock ) (str uct file * , int , struct file lock *);
ssize_t (*splice_write) (struct pipe_inode info * , struct file * ,
loff_t * , size_t , unsigned int);
ssize_t (*splice_read) (struct file * , loff_t * , struct pipe_inode_info * ,
size_t , unsigned int) ;
int· (*setlease) (struc t file *, long , struct file_lock ** , vo id **) ;
long (*fallocate) (struct file *file , int mode , loff_t offset ,
loff_t len) ;
void ( * show fdinf о) ( struct seq_file *m , struct file * f) ;
#ifndef CONFIG ММU
unsigned (* mmap capaЬilities ) (struct file *);
#endif
ssize t (*copy_f!le_range) (struct file * , loff_ t , struct file * ,
loff_t , size_t , unsigned int) ;
loff t (* remap_f!le range) (st r uct file *file_ in , loff_t pos_in ,
struct file *file_out , l off_t pos_out ,
loff_t len , unsigned int remap_flags) ;
int (*fadvise) ( struct file * , loff_t , loff_t , int) ;
);
Описание членов структуры приведено в табл.
9.6.
Все методы могут быть
вызваны без блокировок .
Таблица
9.6.
Члены cmpyкmypыfi/e_operations
Описание
Метод
llseek
read
read- iter
•
Вызывается , когда
VFS
необходимо переместить
индекс позиции файла
Вызывается
read(2) и
связанными системными вызовами
Осуществляет асинхронное чтение с
iov _iter в
каче-
стве назначения
·-·-·--·--·-·-·-----·--- · ----·---··----··-······ -------·-·--·---··-------··--·---- -IZ!ZI
Я . tро Liпux
write
write- iter
iopoll
iterate
.......................
Вызывается
write(2)
1
Используется для асинхронной записи с
aio нужно опросить
iocbs HIPRI
iov_iter
завершение
на
Вызывается, когда
VFS
необходимо прочитать со-
держимое каталога
Вызывается , когда
iterate- shared
и связанными системными вызовами
Вызывается , когда
n.iпux
VFS
необходимо прочитать со-
держимое каталога, когда файловая система поддерживает параллельные итераторы каталогов
Вызывается
VFS,
когда процесс хочет проверить,
есть ли активность в этом файле, и (необязательно)
poll
перейти в спящий режим, пока не будет активно-
сти. Вызывается системными вызовами
select(2)
и
poll(2)
Вызывается системным вызовом
compat_ioёt/
ioctl(2),
когда
32-битные системные вызовы используется на
64-битных ядрах
ттар
Вызывается системным вызовом
Вызывается
VFS,
mmap(2)
когда индексный дескриптор
должен быть открыт. Когда
VFS
открывает файл,
он создает новый "файл структуры" . Затем он вызывает метод ореп для вновь выделенной файловой
структурь1. Вы можете подумать, что метод ореп
ореп
действительно относится к
tions,
struct inode_opera-
и вы можете быть правы . Я думаю, что это
сделано так, потому что это упрощает реализацию
файловых систем. Метод
open() -: хорошее место
private_ data в файловой
для инициализации члена
структуре, если вы хотите указать на структуру
устройства
.,
.....................................................................................
n.1пux ................. .
jl.ush
release
fsync
1 1а11а 9. Фаii.ю11:н1 t·11e1t·ш111 s1 . 11ю
Вызывается системным вызовом
close(2) для
Вызывается , когда закрывается последняя ссылка
на открытый файл
Вызывается системным вызовом
Вызывается системным вызовом
fasync
очист-
ки файла
fsync(2)
fcntl(2),
когда для
файла включен асинхронный (неблокирующий)
режим
lock
get_ unmapped_ area
check_fiags
jl.ock
Вызывается системным вызовом
fcntl(2) для
F_ GETLK, F_ SETLK и F_ SETLKW
Вызывается системным вызовом
Вызывается системным вызовом
команд
mmap(2)
fcntl(2)
для коман-
дыF_SETFL
Вызывается системным вызовом
flock(2)
!
Вызывается
splice_ write
VFS
для объединения данных из кана-
ла в файл. Этот метод используется системным вы-
зовом
Вызывается
splice_read
VFS
для объединения данных из файла
в канал. Этот метод используется системным вы-
зовом
.
setlease
splice(2)
Вызывается
VFS
splice(2)
для установки или освобождения
аренды блокировки файла. Реализации
должны вызывать
setlease
generic_setlease для записи или
inode после ее установки
удаления аренды в
fallocate
•
Вызывается
VFS
для предварительного выделения
блоков или пробивания отверстий
... .. ..... -- -. ----- .... -- -- ......... ···- --- -- --- --- --- ---- -............... -- -..... . . .
_____ . _________________ n.iпux
И 1ро J,i1111,
сору__file _range
Вызывается системным вызовом сору_file _range(2)
Вызывается системным вызовом
и
FICLONERANGE, FICLONE
ioctl(2) для команд
FIDEDUPERANGE
для переназначения диапазонов файлов. Реализация
должна переназначить байты
len в pos_in исходноpos_out. Реализации
вызовы, передающие len ==
го файла в файл назначения в
должны обрабатывать
О; это означает "переназначить в конец исходно-
го файла" . Возвращаемое значение должно быть
числом переназначенных байтов или обычным
отрицательным кодом ошибки, если ошибки про-
remap__file_range
изошли до того , как какие-либо байты были переназначены. Параметр
remap_fiags принимает флаги
REMAP _FILE_ *. Если REMAP_FILE_DEDUP установлен, то реализация должна переназначать только
в том случае, если запрошенные диапазоны файлов
имеют идентичное содержимое . Если
FILE_ CAN_ SHORTEN установлен ,
REMAP_
вызывающая
сторона не возражает против того , 'Побы реализация сокращала длину запроса для удовлетворения
требований выравнивания или
EOF
(или по любой
другой причине)
fadvise
Вызывается системным вызовом
fadvise64()
Обратите внимание, что файловые операции реализуются конкретной фай
ловой системой , в которой находится индексный дескриптор. При открытии
узла устройства
(специального
символьного или блочного) большинство
файловых систем вызывают специальные процедуры поддержки в
VFS, ко
торые находят необходимую информацию о драйвере устройства. Эти под
программы поддержки заменяют файловые операции файловой системы
операциями для драйвера устройства, а затем продолжают вызывать новый
метод
open()
для файла . Именно так открытие файла устройства в файловой
системе в конечном итоге приводит к вызову метода
ства.
open() драйвера устрой
•
. ... -- . - -- ............... ··- ... --- - - - . - - .. -- .......... -- . -- ........... -- .. - ........ ,
•
1
n.inux .................. .
9.7.
Кэш записей каталога
9.7.1.
Структура
Структура
dentry_ operations
VFS
(dcache)
dentry_operations
описывает, как файловая система может пере
грузить стандартные операции
ся областью
1 , 1ва () Фаii . 111вю1 с11t·н·,1а 11 я , 11ю
dentry.
Записи
Dentries
и
dcache
являют
и отдельных реализаций файловой системы. Драйверы
устройств здесь ни причем. Этим методам может быть присвоено значение
NULL,
так как они либо являются необязательными , либо
значение по умолчанию, Начиная с ядра
2.6.22
VFS
использует
(по текущую версию ядра),
определены следующие члены:
struct dentry_operations {
int (*d_revalidate) (struct dentry, * , unsigned int) ;
int (*d_weak_revalidate) (strµct dentry * , unsigned int) ;
int (*d_hash) (const struct dentry * , struct qstr *) ;
int (*d_compare) (const struct dentry * ,
unsigned int , const char *, const struct qstr *);
int (*d_delete) (const struct dentry *) ;
int (*d_init) (struct dentry *) ;
void (*d_release) (struct dentry *);
void (*d_iput) (struct dentry * , struct in ode *);
char * (*d_dname) (struct dentry * , ch ar * , int) ;
struct vfsmount * (* d automount ) (struct path *);
int (*d_manage) (const struc t path * , bool) ;
struct dentry * (*d real ) (stru c t d e ntry * , const struct
inode *);
};
Описание членов структуры приводится в табл.
•
9.7 .
······························--···-··········-··················· · · · ······ -· · ·- · ·IZiil
И , 1р11 l.itlll\
Таблица
9. 7.
....................... n.1nux
Описание членов структуры
dentry_operations
Описание
Метод
Вызывается, когда
dentry.
необходимо перепроверить
VFS
Это вызывается всякий раз, когда поиск имени
находит
dentry
в
Большинство локальных фай-
dcache.
ловых систем оставляют это значение равным
потому что все их
d- revalidate
dentries
в
NULL,
dcache действительны.
Сетевые файловые системы отличаются тем, что чтото может измениться на сервере без ведома клиента.
Эта функция должна возвращать положительное
значение, если
dentry
все еще действительна, и ноль
(если недействительна) или отрицательный код ошибки, если это не так
Вызывается, когда
VFS
необходимо повторно прове-
рить "перепрыгнувший"
обход пути
dentry. Это вызывается, когда
заканчивается на dentry, который не был
получен путем поиска в родительском каталоге. Это
включает в себя"/","." и" .. ", а также символические
ссылки в стиле
-
weak- revalidate
procfs
и обход точки монтирования.
В этом случае нас заботит не столько правильность
dentry,
сколько то, что индекс по-прежнему действи-
телен. Как и в случае с
d_revalidate,
большинство
локальных файловых систем установит его в
поскольку их записи в
dcache
NULL,
всегда действительны.
Эта функция имеет ту же семантику кода возврата,
что и
d- revalidate
Вызывается, когда
таблицу. Первый
d- hash
VFS добавляет dentry в хешdentry, переданный в d_hash, являет-
ся родительским каталогом, в который должно быть
хешировано имя. Те же правила блокировки и синхронизации, что и в
d_compare,
в отношении того, что
безопасно для разыменования и т.д.
•
. . . . --------------.-------------~ -------------- ------ -------------------------------.
1 1 ,1 11а
n.1nux ................. .
' ) Фаii . 11111.ш r11rн• ,ia 11 i1, 1po
Вызывается для сравнения имени
dentry с заданным
dentry является родителем сравниdentry, второй-дочерним dentry. Параме-
именем. Первый
ваемого
тры !еп и пате являются свойствами сравниваемого
это имя, с которым его нужно сравнить.
dentry. qstr d_compare
Должен быть постоянным и идемпотентным, не
должен по возможности блокироваться и не должен
сохраняться в
dentry.
Не следует без особой осторож-
ности разыменовывать указатели за пределами
(например, не следует использовать
dentry
d_parent, d_inode,
d_name)
Вызывается, когда последняя ссылка на
d- delete
брасывается, и
Возвращает
dcache решает,
1 для
немедленного удаления или О для
кэширования
d- init
d- release
dentry от-
кэшировать ее или нет.
dentry
Вызывается при выделении
dentry
Вызывается, когда dentry действительно освобожда~
ется
Вызывается , когда
dentry теряет свой inode
(непосред-
ственно перед его освобождением) . По умолчанию ,
d_iput
когда это значение равно
NULL, VFS
вызывает
iput().
Если вы определяете этот метод, вы должны сами вы-
звать
•
iput()
.• --- --•-- --- ----- ----- ---- --- ---- -- -. --- --- -- -- --- --- -- ----- -------- -- ---- ---- ---- -
Я11pol,inux
....................... n..inux
Вызы вается, когда должно быть сгенерировано имя
пути к
dentry. Полезно для некоторых псевдо файло
(sockfs, pipefs, ... ) для задержки создания
вых систем
пути.
Реальные файловые системы, вероятно, не хотят его
использовать, потому что их dentries присутствуют
в глобальном хэше
dcache, поэтому
их хэш должен
быть инвариантом. Поскольку блокировка не удержи
вается, функция
d_dname() не должна пытаться моди
фицировать сам dentry, если только не используется
соответствующая безопасность SMP. ВНИМАНИЕ:
логика d_path() довольно сложна. Правильный способ вернуть , например, "Hello" - поместить его в
d dnam e
конец буфера и вернуть указатель на первый символ.
Для этого предусмотрена вспомогательная функция
dynamic _ dname().
Пример:
static char *pipefs_dname (stru ct dentry *dent ,
char *buffer , int buflen )
{
return dynamic_dnarre (dentry, buffer, buflen, "pipe : [%lu] ",
dentry- >d_inode- >i_ino ) ;
Вызы вается , когда необходимо пройти через автомон
тирование
dent,y
(необязательно) . Это должно создать
новую запись монтирования
VFS
и вернуть запись
вызывающей стороне. Вызывающий объект получает
параметр пути, задающий каталог автомонтирования
для описания цели автомонтирования и родительскую
d automount
запись монтирования
VFS
для обеспечения наследуе
мых параметров монтирования. Значение
NULL воз
вращается , если кому-то другому удалось выполнить
автомонтирование первым. Если создание
vfsmount
не удалось, должен быть возвращен код ошибки. Если
возвращается
-EISDIR,
то каталог будет рассматри
ваться, как обычный каталог и возвращен в
для продолжения обхода
pathwa\k
I J 1aнa
t'.l1nux .................. .
9. Файтшаs,
с11сн· 1ш111 sщро
Вызывается, чтобы позволить файловой системе
управлять переходом от
позволяет
dentry (необязательно). Это
autofs, например, задерживать клиентов,
позволяя демону автомонтирования пройти мимо и
построить там поддерево. Значение О возвращается,
чтобы продолжить вызывающий процесс . Значение
d_manage
-EISDIR возвращается,
чтобы сказать
pathwalk ис-
пользовать этот каталог как обычный каталог и игнорировать все, что смонтировано в нем, и не проверять
флаг автомонтирования . Любой другой код ошибки
полностью прервет путь
Файловые системы типа
метод для возврата
d- real
overlay/union реализуют этот
одного из базовых dentry, скрытых
оверлеем
Помните , что каждый
dentry
также хеш-список дочерних
имеет указатель на его родительский
dentry.
dentry,
а
Дочерние записи в основном похожи на
файлы в каталоге.
9.7.2. API
кэша записей каталогов
Определен ряд функций, которые позволяют файловой системе манипули
ровать
dentries:
• dget -
позволяет открыть новый дескриптор для существующего
dentry
(увеличивает счетчик использования).
• dput -
закрывает дескриптор для
вания, член
i_ count).
dentry
(уменьшает счетчик использо
Если счетчик использования падает до О, а
все еще находится в хэше своего родителя , вызывается метод
dentry
"d_delete",
чтобы проверить , следует ли его кэшировать. Если его не нужно кэши
ровать или если
dentry
не хешируется , он удаляется. В противном случае
кэшированные dentгy помещаются в список
•
LRU для восстановления при
нехватке памяти.
•
··················································································8
1
Я ; tро 1,iщах
...... . ................ n.1nux
• d_drop - удаляет dentry из списка хэшей его родителей. Последующий
вызов dput() освободит dentry, если счетчик использования упадет до О .
• d_delete - удаляет dentry. Если нет других открытых ссылок на dentry, то
dentry превращается в отрицательную dentry (вызывается метод d_iput()).
Если есть другие ссылки, то вызывается d_drop().
• d_add вызвать
позволяет добавить
dentry
в список хэшей его родителей, а затем
d_instantiate().
dentry в список хэшей псевдонимов для
"d_inode". Член "i_count" в
структуре inode должен быть установлен/увеличен. Если указатель inode
равен NULL, dentry называется "отрицателыюй dentry". Данная функ
• d_instantiate -
позволяет добавить
индексного дескриптора и обновить элемент
ция обычно вызывается, когда создается индексный дескриптор для су
ществующей отрицательной
• d_lookup -
dentry.
поиск dentry по данным его родителя и компонента имени пути.
Он ищет дочерний элемент с заданным именем из хеш-таблицы
dcache.
Если он найден, счетчик ссылок увеличивается и возвращается dentry.
Вызывающий должен использовать dput() для освобождения dentry после
завершения его использования .
....................................................................................
Глава
10.
Псевдофайловые системы
Я , 1ро
l,inux
10.1.
. ...................... t')_lnux
Назначение
Псевдофайловые системы sysfs (каталог /sys) и proc (каталог /proc) исполь
зуются для настройки системы и получения различной информации о
системе и процессах. Свое название псевдофайловые системы получили из
за того, что они работают на уровне виртуалыюй файловой системы. В ито
ге оба эти средства (назовем их так) для конечных пользователей выглядят
как обычная файловая система
каталог
/proc.
-
вы можете зайти как в каталог
/sys,
так и в
В обоих этих каталогах будут файлы, вы можете просмотреть
эти файлы и даже изменить их содержимое.
Содержимое многих файлов псевдофайловой системы
/proc
формируется
"на лету". Обратите внимание на размер любого файла в каталоге
/proc -
он
равен нулю, но если открыть файл, то информация в нем будет. Например, в
· файле /proc/version
находится информация о версии
Монтирование файловых систем
sysfs
ях инициализации системы, или через
Linux.
и
proc осуществляется или в сценари
/etc/fstab. В последнем случае записи
монтирования псевдофайловых систем выглядят так:
•
at·." .... "". --· ............................---· .. -·· ...... -................ "... "... .
.
n.iпux __________________ _
/ s ys
/ pr oc
sysfs
proc
10.2.
sysfs
proc
1 1 1ава
I О.
Пссвдофаii J 1овыс с11с I смы
defaults
defaults
Псевд о файловая система
о
о
о
о
sysjs
Файловая система
sysfs (каталог /sys) предоставляет пользователю инфор
Linux, об имеющихся в системе устройсп~ах и драйверах этих
На рис . 10.1 представлено содержание катал ога /sys. В нем вы
мацию о ядре
устройств.
найдете сл~дующие подкаталоги :
•
Ыосk
-
содержит каталоги для всех блочных устройств , которые есть в
вашей системе в настоящее время. Здесь под устройством подразумевает
ся наличие физического устройства и его драйвера . Если вы подключите
внешний жесткий диск, то в каталоге
/sys/devices
появится новое устрой
ство, но в каталоге /sys/Ыock оно появится только , если в системе есть
драйвер для работы с этим устройством или же драйвер (модуль) встроен
в само ядро.
• bus -
здесь находится список шин, которые поддерживает ваше ядро.
Заглянув в этот каталог, вы обнаружите подкаталоги
pci, pci_ express, scsi
devices и drivers. В
и т. д. В каждом из этих каталогов будут подкаталоги
первом находится информация об устройствах , подключенных к данной
шине, во втором
• class -
-
информация о драйверах устройств.
позволяет понять , как устройства формируются в классы . Для каж
дого класса есть отдельный подкаталог в каталоге
class.
содержит дерево устройств ядра, точнее структуру файлов и ка
• devices -
талогов, которая полностью соответствует внутреннему дереву устройств
ядра.
• firmware -
содержит интерфейсы, предназначенные для просмотра и ма-
нипулирования finnwаrе-специфичными объектами и их параметрами .
• fs -
информация о файловых системах, которые поддерживает ваше ядро .
• kernel -
общая информация о ядре.
• module -
здесь вы найдете подкаталоги для каждого загруженного мо
дуля ядра. Имя подкаталога соответствует имени модуля. В каждом из
подкаталогов модулей вы найдете подкаталог
parameters,
содержащий
специфичные для модуля параметры.
, _--------.--.-----.-.---.. ---.-.----.... --.-.----..... ---.. -.... --.--... --_._----fJII
Ядро
,
Linux
• power -
А .
....................... t_J,.1nux
позволяет управлять параметрами питания, а также переводить
систему из одного состояния питания в другое. Далее будет показано
несколько примеров .
hlock
bus
class
d-
devices
firmware
fs
kernel
module
power
Рис.
10.1.
Содержание катш~ога
/sys
Довольно интересен с практической точки зрения каталог
файле
state
/sys/power.
В
находится состояние питания. Изменив должным образом со
держимое этого файла, можно изменить состояние питания. Например, вот
как можно перевести систему в ~остояние
"Suspend to RAM",
когда питание
процессора отключается, но питание на память подается, благодаря чему ее
содержимое не уничтожается:
$ sudo echo - n mem > /sys/power/state
•При желании можно отправить систему в
состояние
"Suspend to Disk",
когда
содержимое памяти будет записано на жесткий диск, пос_ле чего питание
будет отключено:
$
sudo echo - n disk > /sys/power/state
10.3.
Псевдофайловая система proc
Файловая система
proc позволяет отправлять информацию ядру, модулям и
процессам. Вы можете не только получать информацию о процессах, но из-
•
....................................................................................
[ ~ 1ана
r.linux ______ ___________ _
IО .
Пссв, 10файловые с11с Iемы
менять параметры ядра и системы "на лету" . Эта файловая система интерес
на тем, что позволяет изменять такие параметры ядра, которые невозможно
изменить другим способом, к тому же вносимые изменения вступают в силу
сразу же.
Некоторые файлы в
/proc
доступны только для чтения
вы можете только
-
просмотреть их. А некоторые вы можете изменять , и эти изменения сразу
же отразятся на работе системы. Просмотреть файлы из
/proc
можно любой
программой для просмотра файлов, проще всего в консоли использовать ко
манду
ca t
cat:
/рrос/< н аз в ание
ф айла>
Записать информацию в файл можно с помощью команды
echo,
как уже
было показано выше :
sudo echo
В каталоге
" и нф орм ац ия "
/proc
>
/рrос/< н азва н ие
файла>
очень много файлов и рассмотреть их все мы не сможем.
Прежде, чем мы приступим к самым интересным с моей точки зрения фай
лам, нужно понять, что означают каталоги с числами. Эти каталоги содержат
информацию о запущеннь1х процессах.
Итак, самые полезные информационные файлы:
• /proc/cmdline -
содержит параметры, переданные ядру при з агрузке.
• /proc/cpuinfo -
содержит информацию о процессоре , откройте этот файл ,
думаю , вам будет интересно . Кроме общей информации о процессоре
вроде модели и частоты , здесь выводится точная
частота , размер кэша
и псевдорейтинг производительности , выраженный в
ние
BogoMIPS
BogoMIPS.
Значе
показывает "сколько миллионов р а'з в секунду компьютер
может абсолютно ничего не делать" . Способ измерения производител ь
ности пусть и не самый удачный , но от него до сих пор не отказались , а
"на дворе" уже 3-я версия ядра.
• /proc/devices -
список устройств .
• /proc/filesystems вых систем .
•
полный список поддерживаемых вашим ядром файло
.------------..... -... -.... -.... -... - - .. --- .. -... - -. -- -... --.. --... -... --... -... -. . . .
Ядро
___________________ __ __n.iпux
l.inux
• /proc/interrupts -
информация по прерываниям.
информация о портах ввода/вывода .
• /proc/ioports -
• /proc/meminfo -
полная информация об использовании оперативной па~
мяти. Как по мне , вывод этого файла более понятен и удобен, чем вывод
командыfrее.
• /proc/mounts • /proc/modules • /proc/swaps -
/proc
список загруженных модулей и их параметры.
содержит список активных разделов и файлов подкачки.
• /proc/version -
Используя
содержит список подмонтированных файловых систем.
здесь находится версия ядра.
можно не только получить информацию о системе, но и 'из
менить ее. Например, в файлах
domainname
и
/proc/sys/kemel/hostname
/proc/sys/kemel/
содержится информация об имени компьютера и домена. Вы
MOfI<eтe не только просмотреть, но и изменить содержимое этих файлов, из
менив , соответственно , имя узла и имя домена. Хотя практика изменения
доменных имен через
/proc/sys
практикуется не часто , никто не мешает вам
это сделать :
sudo echo " server " > / proc / sys / kernel/ho stname
sudo echo " example . com " > / proc / sys / kernel / domainn a me
Файл
/proc/sys/kemel/ctrl-alt-del
позволяет регулировать тип перезагрузки
системы при нажатии комбинации клавиш
Ctrl+Alt+Del.
По умолчанию в
этом файле содержится значение О, что означает так называемую "мягкую
перезагрузку"
при нажатии
Reset
(soft reboot). Если же вы внесете в этот файл значение 1, то
Ctrl+Alt+Del эффект будет такой же , как при нажатии кнопки
на корпусе компьютера:
sudo e cho " l " > / proc / sys / kernel /c trl - alt - del
Файл
/proc/sys/kemel/printk
позволяет задать, какие сообщения ядра будут
выведены на консоль , а какие
-
попадут в журнал демона
нию в этом файле содержатся значения
4 4 1 7.
syslog.
По умолча
Сообщения с приоритетом
ниже (первая четверка) будут выводиться на консоль. Вторая четверка
-
4и
это
•
1111-----... -.. -.-.-.---.--... -.-.--.---.----------.-.----.. ----.-.------.---.----..... '
•
r.linux _____ _____ _____ ____
\ 'лава I О .
flсевдофайловые системы
уровень приоритета по умолчанию. Если для сообщения не задан уровень
приоритета, то считается, что его приоритет будет равен
4.
Третье значение определяет номер самого максимального приоритета.
Последнее значение
-
э то уровень приоритета по умолч анию для пер вого
значения.
В большинстве случаев изменяют только пер вое значение , позволяющее
определить, будет ли сообщения с указанным уровнем приоритета выво
диться на консоль или нет. Остальные параметры оставляют без изменения.
В файле
/proc/sys/net/core/netdev_ max_ backlog
содержится максимал ьное
число пакетов в очереди. Значение по умолчанию
Ф айл
/proc/sys/fs/file-max
- 1000.
позволяет изменить максимальное количество за
головков файло в , которое может быть одновременно открыто . Другими сло
вами, этот файл задает, сколько одновременно может быть открыто файлов.
Значение по умолчанию для ядра 3.16 и файловой системы Ьtrfs - 73054.
Чтобы сохранить внесенные "на лету" изменения , и чтобы их не пришлось
снова вводить при следующей перезагрузке сервера, нужно отредактировать
файл
/etc/sysctl.conf. Представим, что вы изменили значение из файла /proc/
sys/fs/file -max. Тогда в файл /etc/sysctl.conf нужно добавить строку:
fs . file - max
16 384
Принцип прост:
/proc/sys/
отбрасывается совсем , а в оставш ейся строке все
слеши заменяются точкам и . Само же з начен ие указывается че ре з знак
равенства. Если нужно указать несколько з начен ий, то они указываются че
рез пробел .
•
.-- ---- . ---- ... --- ---- . -- . -- -- ---- . --- . -- . --- -. -- ---. --- -. -- . -- ---. ---- -.. -- . - . . . . . . .
Глава
..
11.
.
Пользователи и группы
Ядро
[,inux
....................... n..inux
11.1. Введени е
в учетные з аписи
Для того, чтобы эффективнее работать с ядром
Linux
Linux,
нужно хорошо раз
бираться в особенностях учетных записей и группах пользователей
Linux.
I
Операционная система
Linux
поддерживает регистрацию и одновременную
работу множества пользователей. Обратите внимание: именно одновремен
ную работу. Раньше, еще во времена
UNIX,
были компьютеры, к которым
подключалось несколько мониторов и клавиатур. Каждый комплект
монитор
+
клавиатура назывался терминалом и представлял собой от
дельное рабочее место пользователя. Пользователь входил в систему, а его
рабочее место в системе отображалось как
ttyN,
где
N-
номер рабочего
места.
Сегодня такие компьютеры уже более не востребованы, их вытеснили персо
нальные компьютеры, которые и стали называться персональными, посколь
ку предполагают подключение только одного рабочего места. Мониторов
можно подключить несколько, а устройство ввода
-
клавиатура будет одна.
Но даже на таких компьютерах возможна одновременная работа несколь
ких пользователей. Например , вы можете войти в систему как обычно
-
посредством графического интерфейса. Другие пользователи смогут войти
через
ssh
..
или
FTP.
И все вы будете работать с системой одновременно. SSН
пользователи смогут выполнять команды и получать результат их выполне
ния, FТР-пользователи
-
обмениваться с вашим компьютером файлами .
•
. . . -... -........ -... •. -.. -... --.... -....... -.... -........ -... -................. -.. .
I J ia в a
n.inux _________________ _
11 . Пользователи
и гру1111ы
Все учетные записи можно разделить на три вида: учетные записи обычных
пользователей , учетные записи системных служб и учетная запись
учетными записями обычных пользователей все ясно
-
root.
С
они имеют право
входить в систему разными способами (если тот или иной способ не запре
щен настройками системы), для них определен домашний каталог (обычно
/hоmе/<имя_пользователя>), пароль и командная оболочка (как правило, в
последнее время используется /Ьin/Ьash).
Права обычных учетных записей:
•
Право на вход в систему
по умолчанию обычный пользователь мо
-
жет войти в систему самыми разными способами , если это не ограничено
настройками системы (например, модулями РАМ) . Пользователь может
войти локально
-
через консоль или в графическом режиме через
дисплей-менеджер вроде
gdm.
Также никто не запрещает (опять-таки
по умолчанию) удаленный вход, например, по
SSH
или
если на
FTP,
компьютере , в который осуществляется вход, установлены соответству
ющие службы.
•
Право на запуск программ, не требующих для своего выполнения
прав
root -
как правило, такие программы находятся в каталогах /Ьin и
usr/Ьin. А вот из каталога
/sbin
/
запустить программу может только супер
пользователь. Программы , действие которых распространяется на всю
систему,
например
программы
изменения сетевых интерфейсов ,
программы разметки диска, находятся в каталоге
/sbin (super-bin).
Что
бы запустить эти программы , пользователю нужно получить полномочия
root.
•
О том, как это сделать, будет сказано в следующем разделе .
Обычный пользователь может создавать, удалять, читать, изменять,
запускать, устанавливать права и выполнять другие операции над фай
лами, которые находятся в его домашнем каталоге. Как правило , это ка
талог /hоmе/<имя _ пользователя> . Хотя администратор может назначить
пользователю любой другой каталог, хоть /users/Ьagira, как правило, этого
никто не делает. Каталог
/home
может находиться физически на одном
разделе, что и корневая файловая система, а может находиться и на дру
гом разделе и даже на другом диске. На крупных серверах, как правило ,
под
•
/home
отводят целый диск или даже создают RАID-массивы дисков.
Право на чтение файлов
-
обычный пользователь может читать боль
шую часть файлов за пределами домашнего каталога. Исключения раз
ве что составляют домашние каталоги ' других пользователей (если эти
'--
другие пользователи явно не разрешили этому пользователю читать их
-. -
· - .
· · -
. .
· -
...
· - ·
. . . . . .
--·
. . . . . . . . . . . . . . .
-- ·---.
. .
- - · · · ·
- ·
. . . . . . . . . . .
- ·
. .
-
. .
--
И . 11111 l ,illll\
...................... t.\.1nux
файлы) и некоторые файлы/каталоги в
могут читать все пользователи, а вот
•
/etc. Например,
файл /etc/shadow -
файл
/etc/passwd
только root.
Пользователь не имеет право вносить изменения в конфигурацию
всей_ системы , то есть устанавливать программы, изменять глобальные
настройки устройств, параметры ядра, параметры загрузчика и т.д.
•
Пользователь имеет право изменить свои пользовательские параме
тры, например, обои рабочего стола, некоторые переменные окружения ,
которые будут влиять только на его работу и т.д.
•
Право на изм~нение своего пароля, но обычный пользователь не имеет
право изменять пароль других пользователей.
Учетные записи системных служб не имеют право входить в систему. Для
них не задан ни пароль, ни домашний каталог, а в качестве оболочки исполь
зуется /Ьin/true или /Ьin/false
-
чтобы пользователь , используя учетную за
пись службы, не мог войти в систему через консоль. От имени таких учетных
записей выполняются различные службы, например, от имени пользователя
www-data выполняется
Display Manager и т.д.
Пользователь
root -
веб-сервер,
gdm -
учетная запись для
GNOME
пользователь с максимальными правами, он может
делать все:
•
Право на изменение любого файла
root
-
может читать, записывать,
удалять любые файлы, в том числе и файлы в домашних каталогах других
пользователей.
•
Право на изменение конфигурации системы
-
пользователь
root мо
жет изменять конфигурацию системы посредством редактирования фай
лов в каталоге
•
/etc, /proc,
запуска конфигураторов системы .
Право на запуск любых программ
-
root
может запустить любую
программу, в каком бы каталоге она ни находилась.
•
Право на создание, удаление, изменение (в том числе изменение паро
ля) других учетных записей.
•
Право на установку и удаление программ.
•
. . ................ . ........ .. . . . ...... .. .. .. .. .... ............ . ........ .. ..... . . . . . ..
11 , 111.1 11.110.11,юкан-. 111111р~1111ы
r.l1nux . ................ .
Власть пользователя
неограниченна. Так было до определенного мо
root
мента, пока не появились системы принудительного контроля доступа вроде
SELinux, LIDS, Tomoyo, которые могут ограничить даже самого root. Вот
SELinux, LIDS, Tomoyo и другие подобные с~стемы
только беда в том, что
по умолчанию неактивны или даже не установлены, поэтому пока их не ак
тивировать, пользователь
root будет все равно
самым главным.
Примечание. Напомним, что когда у вас привилегии пользова
теля
лом
11.2.
root,
#,
приглашение командной строки заканчивается симво
а когда вы работаете как обычный пользователь
Получение полномочий
Самый простой способ получить права
- $.
root
root -
это войти как
при входе в систему вы указываете имя пользователя
root
root.
То есть
и пароль , указан
ный при установке. Проблема в том, что не во всех дистрибутивах этот трюк
сработает. Учитывая всю опасность, которую несет использование учетной
записи
root, во многих дистрибутивах учетная запись root отключена, а вход
root ограничен самыми разными способами. Включать учетную запись
root не . рекомендуется - ведь злоумышленник знает, что учетка root есть
как
везде и ему не придется угадывать имя пользователя, останется только по
добрать пароль
root.
root.
А так вы исключаете даже саму возможность входа как
Тем более права
root
можно получить другим образом, о котором мы
nоговорим далее. А пока рассмотрим способы блокировки входа (кроме
отключения учетной записи)
Часто вход как
root.
root ограничен на уровне менеджера дисплея.
В дистрибути
вах, где используется графическая среда КDЕ и менеджер экрана КDМ (К
Display Manager), нужно отредактировать файл /etc/alternatives/kdm4-config.
В нем нужно найти директиву AllowRootLogin и присвоить ей значение true,
чем вы разрешите вход как root в графическом режиме.
При использовании
GDM (Gnome Display Manager) вход как root ограничен
GDM, а столько РАМ-модулями. Нужно
открыть /etc/pam.d/gdm-password и найти строку, отвечающую за запрет вхо
да как root. Она может выглядеть, например, так:
не столько конфигурацией самого
auth required pam_succeed_if.so user ! = root quiet
•
·· ····· ··· ········································································ -
Я ; {ро
IJnux
....................... n..inux
Некоторые дистрибутивы разрешают заходить как гооt даже в графическом
режиме. Просто они отображают предупреждение о том, что работать как
root небезопасно .
В
Linux
Пример такого дистрибути ва
используется оболочка
нятся в каталоге
/etc/fly.
Fly,
-
CentOS.
конфигурационные файлы которой хра
Это собственная разработка, которую не встретить
в других дистрибутивах. За графический вход в систему отвечает
fly-dm
(Fly Display Manager), конфигурационные файлы которого находятся в ката
/etc/Xl 1/fly-dm. Основной файл конфигурации - fly-dmrc . Самое ин
тересное, что вход как root в Linux по умолчанию разрешен параметр
Allow RootLogin у~тановлен в true (рис. 11.1 ). Поэтому если вам очень силь
логе
но хочется войти как гооt в графический режим , вы можете это сделать , но
сначала вам нужно изменить пароль самого пользователя
root -
как это сде
лать, будет показано далее. Пока нужно отметить, что вход как
графическом , что в настольном режиме
-
root
что в
очень опасная штука. Поэтому
если вы за безопасность, выключите данный параметр (значение/а/sе), а для
временного получения полномочий
root
используйте команду
sudo
(будет
показано далее) .
Рис.
11.1.
Файл коиф11гурац1111ftу-dтrс
•
. .. ... . . ..... .. . ... .. .. . ........ .. . . . .. . . . . ... . . . .. . . . ....... .. . . . . ... . . . .. . . . . . . . . .
1 1 1ав а
ft.inux ................. .
11 .
ПОJ1ыова, еJ Ш и
I ру1111ы
Настоятельно рекомендуется работать в системе как обычный пользователь,
а максимальные права получать только тогда, когда они вам действительно
нужны. Например, когда понадобится запустить какую-то программу, требу
ющую права
root.
При этом вам особо ничего не придется делать, кроме как
ввести пароль.
Рассмотрим пример. Вы установили, например
создали учетную запись
mark
Astra Linux, и при установке
и задали пароль. По умолчанию инсталлятор
создает первую учетную запись так, что она вносится в группу
sudo root. Други
является root,
членам этой группы можно выполнять команды с привилегиями
ми словами, созд~нный во время установки пользователь уже
только с некоторыми оговорками.
Настройки , позволяющие группе
хранятся в файле
/etc/sudoers.
sudo
выполнять команды от имени
root,
В этом файле указываются все учетные
записи, имеющие право выполнять административные задачи. Когда вы по
пытаетесь выполнить одну из таких задач, например, добавить нового поль
зователя, графический интерфейс автоматически запросит у вас ваш пароль.
Аналогично, когда вы будете пытаться запустить командную оболочку (ко
манда
root. Это будет не пароль root, а ваш пароль, то
есть пароль пользователя mark (рис. 11.2). Ему разрешено выполнять адми
нистративные задачи, просто система пытается убедиться, что вы - это вы,
sudo bash)
с правами
а не некто, кто оказался за вашим компьютером во время вашего отсутствия.
Рис.
•
11.2.
Запуск командной оболочки с правами
но ввести пароль пользователя
root- ко.манда sudo bash.
mark, а не root!
Нуж
.---- ----- -- ---- ................... -................. --........................... . . .
•
я , .ро (,iпux
....................... n..inux
Когда же вам нужна командная строка с правами
root,
не обязательно даже
переключаться в консоль. Достаточно открыть терминал и ввести команду
su.
Она попросит вас ввести пароль
терминал с правами
root.
вводить после ввода команды
няться с правами
После ввода пароля вы получаете
root.
Это означает, что все команды, которые вы будете
su
и успешной аутентификации, будут, выпол
root.
Примечание. Если учетная запись
жете использовать команду
парол~
Когда вы
-
root,
sudo,
то вы не смо
а вы его не знаете.
единственный администратор, команда
ант. Но когда администраторов несколько,
ку пароль
root отключена,
так как она предполагает ввод
root
su - идеальный вари
команда su - не выход, посколь
нужно будет сообщить всем остальным администраторам.
Если потом возникнет нестандартная ситуация, выяснить, кто виноват, будет
сложнее.
На этот случай у пользователя
root могут
быть доверенные лица. Это может
быть помощник администратора, его заместитель
называйте, как хотите.
Есть лица, которым разрешено получать права
Такие лица вносятся в
файл
/etc/sudoers ( если вам не
sudo (так правильнее).
root.
лень прописывать каждого отдельно) либо в
группу
...
Рис.
-
11.3.
--
Редактирование файла
--
/etc/sudoers
•
----- ---- -.. ---- ---- -------------------- .
. . . . . . ·- ....... ... ---. ----- -- .. -----
l . 1ава 11 .
t\.inux. _............... .
Редактировать файл
По. 1ыо~щ1е. 111 и I р~ 1111ы
можно только через команду
/etc/sudoers
visudo
(рис.
11.3):
expo rt EDITOR=nan o
sudo visudo
Первая команда устанавливает переменную окружения EDIТOR, задающую
удобный текстовый редактор, который будет использован для /etc/sudoers.
Вторая команда вызывает утилиту для редактирования файла
/etc/sudoers.
Представим, чт.о у нас есть пользователь
делать все, что можно пользователю
sudoers
bagira, которому нужно разрешить
root. Для этого нужно добавить в /etc/
запись вида:
bagira ALL=(ALL:ALL) ALL
Можно также добавить запись :
%s udo
ALL= (ALL: ALL) ALL
Она означает, что членам группы
пользователю
вить в группу
root. Тогда
sudo (далее
sudo
можно делать все , что можно делать
всех администраторов-помощников нужно доба
будет показано, как это сделать).
Сохраните файл и выйдите из редактора. Войдите как пользователь, которо
му вы предоставили право
sudo. В
нашем случае-это пользователь
Далее введите команду, которая требует прав
sudo
root через
bagira.
команду sudo:
< к о манда >
Например:
sudo bash
,
Обратите внимание: система запрашивает пароль пользователя, а не
пароль
,
root.
Пользователь указывает свой пароль, а система знает, что ему
разрешено получать права
root.
В итоге наши помощники не знают пароль
-............ ---. ------· -. --. ----. -----------.. ---·- ---------------.. ----. ------
_
Я J tpo
root
[,inux
•••••••••••••••••••••••
и смогут выполнять определенные действия с пр авами
root
rtiпux
под своим
именем.
Как правило, вам не нужно вообще редактировать файл
денная информация о его формате
-
/etc/sudoers.
только для общего развития. На прак
тике вам нужно просто добавить пользователя в группу
появилась возможность получать права
sudo usermod
-а
Приве
sudo,
чтобы у него
root:
- G sudo bagira
Данная команда изменяет группу для пользователя
список групп пользователя группу
Контролировать получение прав
bagira ,
добавляя (-а) в
(-G) sudo.
sudo
можно командой 1 :
# tail /var/log/auth . log I grep sudo
Посмотрите на рис .
mark
11.4. Для
примера ,
6 июля 2022 года в 7.16 пользователь
sudo для выполнения команды bash. То
только попытки использования sudo, но и
пытался выполнить коман ду
есть в журнале отображаются не
журналируются даже вводимые польз овател ями команды.
Рис.
1
11.4.
Журнал аутентификации
aut/1.log
В некото ры х дист р ибут ивах журн ал аутентификации называется
secure,
а не
auth.log.
•
. . ..-- --- --- ----- ------- --- -- -- ---- --- -- -- --------- -- ------ --- ---- -. -. --- --- . ------ -.
•
1нава 11 .
r.linux -·················
llш11,т1ш 11.'J Ш 11 1 ру1111м
Если вам нужно получить некоторый аналог команды
su,
чтобы вы могли
вводить сразу неограниченное количество команд с максимальными права
ми без приставки
sudo,
используйте следующий трюк
мальными правами оболочку
bash. Все
-
запустите с макси
команды , вводимые в этой оболочке,
будут выполнены с максимальными правами:
sudo bash
Закрыть такой сеанс можно командой
exit . .
Прежде чем перейти к следующему разде!Jу, разберемся, как сменить пароль
пользователя
root.
Для этого нужно просто задать пароль:
su d o passwd r oo t
Сначала нужно ввести ваш пароль, затем новый пароль для
-
root,
после этого
подтвердить пароль. После этого вы сможете войти в систему как
root
в
консоли. Для входа в графическом режиме нужно редактировать файл, отно
сящийся к РАМ, как было сказано ранее. Отметим, что активация пользова
теля
правильнее использовать коман
ду
root - занятие небезопасное, гораздо
sudo. На личном компьютере еще такое
сервере такое делать воспрещено.
мероприятие допускается, но на
11.3.
Уп равление учетными записями
пользователей
11.3.1.
Создание учетной записи пользователя
Создать новую учетную запись пользователя можно командой
adduser.
Пример:
sudo adduser evg
•
.-- . ---------- -------- --. ------ ------------------------------------------. ------ -.. . .
Ядро
Linux
_______ _____ ___ ___ __ __ _n..inux
В большинстве случаев
adduser
просто добавляет в файл
учетную запись поль зо вателя . Но в
Linux
/etc/passwd
данная коман да запрашивает не
только имя пользователя (которое передается команде в качестве пер в ого
параметра), но и пароль пользовател я. Также есть во зм ожность ввести
дополнительную информацию о пользователе, если есть такая необхо
димость (см. рис .
11.5).
Рис.
11.5.
Создание нового пол ьзователя в
Linux
Если при создании парол ь задан неверно (вы задали слишком простой или
слишком сложный пароль и хотите его изменить), можно сменить пароль с
помощью команд ы
passwd:
su d o p ass wd
п ользователя
имя
Напомню, что для добавления учец-юй записи пользователя нужны права
root,
который пq_льзо вател ь может получить через
сен в
/etc/sudoers
В
Linux
su
или
sudo,
если он вне
и ему разрешена операция добавления пользователя .
есть также графический конфигуратор и создать пользо вателя мож
но не только с помощью команды
adduser.
Чтоб ы открыть графический кон
фигуратор и создать пользователя, выполните следующие действия :
•
1!!1- ------------------------------------ ---------- ----------------------------------- ·
1j 1 ава 11 .
n..inux ................. .
flш1ыова I с. 111 11 1 ру1111ы
1.
Откройте Панель управления.
2.
Перейдите в раздел Безопасность и запустите Управление политикой
безопасности.
Перейдите в раздел пользоват~ля и нажмите кнопку+ на панели инстру
3.
ментов .
Заполните информацию о пользователе и нажмите зеленую галку на па
4.
нели инструментов для сохранения пользователя (рис .
11.6).
Eil PIOOч,oA(TM
• ~ otюP)'A,Qtl.OИ"""
Груnпw
Рис.
ll.6.
:Swнtonlaunch
1,s
:J_,,deo
и;
5.,.... $
1()0
д..
д,,
S}p1u9~
•6
.:i•
д.:~
Создание пользователя, графический метод
11.3.2.
Файлы
/etc/passwd
и
/etc/shadow
При добавлении учетной записи происходят следующие действия (вкратце):
Добавляется запись в файл
•
/etc/passwd -
это небольшая база данных о
пользователях в текстовом формате . Этот файл могут просмотреть все
пользователи .
Если при создании учетной записи утилита запрашивает пароль, то он
•
будет внесен в файл
/etc/shadow. Пароли в этом файле хранятся в зашиф
root. Команда p asswd < имя > , из
пользователя, вносит изменения как раз в этот файл .
рованном виде , а доступ имеет только
.
•
меняющая пароль
······-·---··--·----·---·-----·------------·---·----·-------·----·---·---··---·--- -
И , 11т
•
l .i1111x
....................... t\.1nux
Создается домашний каталог /hоmе/<имя>, и в него копируется содержи
мое каталога
/etc/skel.
•
Создается почтовый ящик пользователя в каталоге
•
Владельцем каталога /hоmе/<имя> и всех файлов и каталогов в нем
/var/spool/mail.
назначается создаваемый пользователь .
Рассмотрим формат файла
/etc/passwd:
имя_пользователя:пароль : UID : GID : полное _имя:домашний_каталог:оболочка
Вот фрагмент этого файла:
evg:x : 1000 : 1000 : evg : /home/evg : /bin/bash
mark:x : 1001 : 1001 : : /home/mark : /bin/bash
Формат файла
/etc/passwd
Таблица
Формат файла
11.1.
Номер
поля
1
приведен в таблице
11.1.
/etc/passwd
Описание
Название
Имя пользователя
Имя , использующееся при входе в
систему
Поскольку пароль пользователя хра-
2
Пароль
нится в файле
etc/passwd
/etc/shadow, то
в файле /
вместо пароля просто ука-
зывается символ 'х'
3
UID
Идентификатор пользователя
4
GID
Идентификатор группы пользователя
•
& 1 - - -----------------·-----------------------·---··-·················-············-··
1JJa вa 11 .
n..inux ................. .
1111. 11 . 1111шн·.1111111 р~1111ы
Устанавливается администратором и
ни на что не влияет. В крупных организациях имя пол ьзователя помогает
Полное имя поль-
5
зователя
устано вить контакт с пользователем.
Это поле может также содержать
номер телефона, номер_ комнаты и
прочую информацию, которую запрашивает
adduser при
создании пользо -
вател"я
6
Домашний ката-
Обычно это /hоше/<имя - пользовате -
лог пользователя
ля>
Программа, которая будет запущена
при входе польз9вателя в систему из
Оболочка
7
консоли (для графического режима
это поле не имеет значения). Список
доступных оболочек хранится в файле
/etc/shells
В файле
/etc/shadow
passwd, поля
полей больше , чем в
/etc/passwd.
Как и в случае с
/etc/
разделяются двоеточиями:
1.
Имя пользователя. Совпадает с именем пользователя в файле
2.
Зашифрованный пароль. Позже мы поговорим о том, как распознать алго
/etc/passwd.
ритм шифрования , которым был зашифрован пароль .
3.
Количество дней (с
l
января
1970
года) , когда пароль был сменен в
последний раз.
4.
Число дней до смены пароля. Если в этом поле О , то пароль может быть
сменен в любой момент.
5.
Количество дней, после которых пароль должен быть сменен. Обычно
здесь з начени е
999999,
которое показывает, что пол ьзователь может ни
когда не менять свой пароль .
•
..- ................................................... ·.···· ............. . .. . ..... . - -
Я , 1ро
6.
l ,i 1111 х
....................... n.1nux
Число дней, в течение которых пользователь получает предупреждение о
необходимости изменить пароль. Обычно такие предупреждения пользо
ватель получает за неделю
7.
(7
дней) до часа "Х".
Число дней после окончания действия пароля, когда еще пользователь
может работать со старым паролем. Если после этого срока пользователь
не сменит пароль, учетная запись будет заблокирована.
8.
Число дней, начиная с
1 января 1970,
после которых пароль будет забло
кирован .
9.
Не используется.
Обычно последние три поля не используются. По зашифрованному паролю
можно понять, какой алгоритм шифрования использует система. Посмотри
те на начало зашифрованного пароля:
• $1$ - MD5. Ранее часто использовался, сейчас чаще используется SHA512, поскольку в MD5 обнаружились математические уязвимости.
• $2$, $2а$ Linux.
Blowfish.
Чаще используется в FreeBSD/OpenВSD, чем в
• $5$ -
SHA-256.
• $6$ -
SHA-512. Используется
Форматы файлов
в современных дистрибутивах.
/etc/passwd и /etc/shadow были приведены
"для общего раз
вития", чтобы вы понимали, что происходит. Модифицировать учетную за
пись пользователя правильнее с помощью команды
редактирования файла
/etc/passwd.
usermod, а не с помощью
Конечно, можно внести небольшие изме
нения, например, изменить полное имя пользователя. А вот для изменения
остальных параметров, например, домашнего каталога, правильнее исполь
зовать
usermod,
чтобы потом не делать много ручной работы.
11.3.3. Изменение
и удаление учетных записей
Как было отмечено, ранее для модификации учетной записи пользователя
нужно использовать команду
usermod,
но прежде поговорим об изменении
•
ВI- ······································· ···········································
n.iпux _________________ _
l . 1a11a 11 .
1111.11,ншан·. 11111 1 р~11111,1
пароля , так как изменение пароля ~ это тоже, по сути, изменение учетной
записи.
Для установки и изменения пароля пользователя используется команда
passwd:
# pass wd
<имя>
Если пользователь хочет изменить собственный пароль, то указывать имя не
нужно:
$ passwd
А вот теперь можно приступить к рассмотрению команды
usermod.
Формат
вызова этой команды следующий:
# usermod
[параметры]
Параметры команды
Таблица
11.2.
учетная
запись
usermod описаны
Параметры команды
в таблице
usermod
Параметр
-а,
-с,
-append
--comment
комментарий
11 .2.
Описание
Добавляет пользо вателя
в
дополнител ьную
группу. Используется только с параметром
Добавляет комментарий для учетной
-G
записи
пользователя
Задает новый домашний каталог пользователя . Если указать параметр -т , то текущий до-
-d, --home
каталог
машний каталог пользователя будет перенесен в новый домашний каталог, который будет
создан , если не существует
".--- -- ---- -- ------ ---- ---- --- -- -------- ---.---- -- --- ------- -- ---- -.----. ---.-- ----1!11
Я , tро
l,inux
....................... n.inux
Указывает дату устаревания учетной записи
пользователя. По достижении этой даты учет-
- е,
--expiredate
дата
ная запись пользователя будет заблокирована.
Дата указывается в формате ГГГГ-ММ-ДД.
Если дату не указывать, то устаревание учет-
ной записи будет отключено
После указанного числа дней, которые пройдут после устаревания пароля, учетная запись
-f, --inactive дни
будет заблокирована. Значение
означает,
-1
что эта возможность не используется, а О
запись будет заблокирована сразу
же
-
после
устаревания пароля
Указывает имя или
пользователя
-g, --gid группа
первичной группы
GID
Группа
с
таким
именем/GID
должна существовать. Все файлы в домашнем
.
каталоге пользователя, которые принадлежа-
ли бывшей первичной группе, теперь будут
принадлежать новой группе
Список
-G, --groups группа][,
группа2, ... , группаN}
дополнительных
групп,
рых находится пользователь.
групп
осуществляется
дополнительных
через
пробелов.
в
кота-
Перечисление
запятую
Например ,
без
-G
group 1,group2
-!, --login
новое_ имя
-L, --lock
-т,
--move-home
-о,
--non-unique
Изменяет имя пользователя на новое
Блокирует
учетную
запись
- имя.
пользователя.
Нельзя использовать этот параметр с -р или
-1
Перемещает домашний каталог. Используется
вместе с параметром
-d
При использовании с -и позволяет указать не
уникальный
ля)
UID
(идентификатор пользовате-
•
111-········································································,··········
lтша
n..inux ................. .
11 .
r1ш11,юва1сли 111ру1111ы
Шифрованное значение пароля, которое возвращает
-р, --passwoгd пароль
параметр
функция
не
crypt.
Использовать
рекомендуется ,
поскольку
ЭТОТ
дру-
гие пользователи увидят незашифрованный
пароль в списке процессов
Выполняет изменения в каталоге
-R, -гооt chгoot
chroot
и ис-
пользует файлы конфигурации из этого каталога
Задает оболочку для пользователя. Если обо -
-s, --shell оболочка
лочка не указана, то будет использована обо лочка по умолчанию
-и,
--uid UID
-И,
-Z,
--unlock
--selinux-useг
SEUSER
Задает новый
UID
пользователя, который дол-
жен быть уникальным
Разблокирует учетную запись пользователя
Новый пользователь
SELinux
для пользова-
тельского входа
Рассмотрим несколько примеров:
# usermod - d /home/new home - m mar k ·
# usermod - 1 mark
# usermod - G admins , sudo mark
Первая команда задает новый каталог для пользователя тагk. Теперь он бу
дет называться
/home/new_home.
Старые файлы (из каталога
/home/ubuntu)
будут перемещены в новый домашний каталог.
Вторая команда блокирует учетную запись пользователя тагk. Третья ко
манда вносит пользователя тагk в группы
admins
Теперь рассмотрим команду useгdel ( см. табл .
# userdel
•
[параметры]
и
sudo .
11.3):
пользователь
.. . ... . . . .. .. . . . . . . . . . . .... .. ... . . . . . . . .... .. . ... . .. ... . .. . . . . . . .... ... .. . . . . .. . . . . . .
Я . tро lj1111x
Таблица
11.3.
....................... t')_lnux
Параметры команды
userdel
Описание
Параметр
Удаляет учетную запись, даже если пользователь
работает в системе. Также будет удален домашний
каталог и почтовый ящик, даже если другой пользаватель использует тот же домашний каталог. Если в
-f, --force
файле
/etc/login.defs
параметр USERGROUPS_ENAВ
равенуеs, то будет удалена и первичная группа пальзователя, даже если она является первичной и для
другого пользователя. Довольно опасный параметр,
который может привести систему в нерабочее состояние
Удаляет домашний каталог пользователя и почто-
-r, --remove
вый ящик. Файлы этого пользователя, созданные на
других файловых системах, нужно искать и удалять
вручную
-R, --root chroot
Выполняет изменения в каталоге
chroot и
использует
файлы конфигурации из этого каталога
Удаляет все пользовательские сопоставления
-Z, --selinux-user
SELinux для
Пример удаления учетной записи
учетной записи пользователя
ubuntu,
домашний каталог и почтовый
ящик также будут удалены:
# userde l - r ubuntu
11.3.4.
..
Группы пользователей
Для более простого управления пользователями их можно объединять в
группы. Например, можно задать ограничения ресурсов для группы польза•
.. .... . . . . . . . . .. . . . . . . . ... ....... ..... . .... .... . ... ......... . .... ........ .... .....
1 1а11а 11
t\.1nux __ . _________ ..... .
ll11.11,юв.11t'.lll lt 1р~1111ы
вателей. Тогда они будут распространяться на всех пользователей, входящих
в группу, и вам не придется их устанавливать для каждого пользователя от
дельно.
Но, прежде чем устанавливать права для группы , нужно эту группу создать .
Добавить группу можно командой
groupadd,
чится, если вы просто отредактируете файл
однако ничего плохого не слу
/etc/group
(не
groups,
а именно
group!) и добавите группу вручную. При добавлении группы следите, чтобы
ID группы был уникальным. Если же вы не хотите ни за чем следить, тогда
просто введите команду groupadd:
# groupadd
[параметры]
С параметрами команды
ме
-
имя
группы
groupadd можно
ознакомиться в справочной систе
man groupadd.
11.4. Модули
РАМ
Подключаемые модули аутентификации РАМ (PluggaЫe
Modules)
тверждения подлинности пользователя. Модули РАМ
мире
Authentication
предоставляют администраторам дополнительные методы под
Linux.
-
это не новинка в
Они были разработаны очень давно, но до сих пор есть даже в
самых современных дистрибутивах
Linux,
поскольку заменить их, по сути,
нечем.
Модули РАМ позволяют использовать несколько схем аутентификации.
Большинство приложений, которые нуждаются в проверке подлинности
пользователя, используют РАМ. Модули РАМ позволяют реализовать аль
тернативную аутентификацию, например, по отпечаткам пальцев или по сет
чатке глаз, но для этого необходимо дополнительное оборудование, напри
мер, сканер отпечатков. В этой книге мы рассмотрим традиционный вариант
использования РАМ- когда аутентификация происходит посредством вво
да пароля с клавиатуры.
Основной файл конфигурации называется
pam.d/ находится
/etc/pam.conf.
В каталоге
/etc/
конфигурация для разных сервисов , которые поддержива
ют РАМ, например, в
•
для
/etc/pam.d/sshd находится конфигурация РАМ-модулей
SSH, в /etc/pam.d/fly-dm - конфигурация пароля для менеджера дисплея
.. ---.. --.. --.. ---.. --------.. ---------... --.--.. --............ -... -............ --tzll
•
Ядро
Linux
... . .. .. . ... . .... . .. ... t\..inux
Fly Display Manager и т.д.
В каталоге
/etc/security также есть файлы конфигу
рации, относящиеся к РАМ , например, файл ассеss.соnfуправляет доступом
в систему.
Безопасность вашей системы зависит от используемых вами модулей.
Модули хранятся в каталоге /liЬ/security или
/lib64/security
(для 64 - битных
систем), однако некоторые дистрибутивы не следуют этому стандарту. К
примеру, в некоторых системах модули можно найти в каталоге /usr/liЫ
security.
При желании можно написать и собственные модули, но для начала
следует разобраться с уже имеющимися. Ниже приведен список наиболее
часто используемь!х модулей. Больше информации по каждому из них мож
но получить, набрав
man
модуль, к примеру, тап рат _ywcheck. Обратите
внимание , что нет "стандартного списка" модулей . Их состав варьируется от
дистрибутива к дистрибутиву.
разрешает или запрещает доступ, в зависимости от IР
• pam_access -
адреса, имени пользователя, имени хоста или доменного имени и т.п. По
умолчанию правила доступа определены в файле /etc/secшity/access.conf.
Когда пользователь входит, проверяются правила доступа до первого
совпадения , и
принимается решение , разрешить или запретить д оступ.
та·кже смотрите модуль pam_time -там другие ограничения.
• pam _ cracklib
и
pam_pwcheck -
предоставляют функции проверки
прочности пароля (проверки на легкость угадывания или повторяемость).
У пользователя спрашивают пароль , и если он проходит предустановлен
ные правила и считается прочным , тогда нужно ввести его еще раз дл я
проверки правильности ввода.
• pam_deny -
безусловно зап рещает доступ. Этот модуль можно исполь
зовать для блокирования пользователей как политику по умолчанию (см.
также
pam_permit).
• pam_echo - выводит предустановленное текстовое
же pam_ inotd.
• pam_env -
поз воляет присвоение значений переменным окружения.
Правила по умолчанию берутся из файла
• pam _ ехес • pam_lastlog -
сообщение. См. так
/etc/security/pam_env.conf.
вызывает внешнюю программу.
выводит дату и время последнего входа в систему.
•
. ...................................................................................
1 :нана
t\.inux ................. .
• pam_limits -
11 .
lloJ IЫOH.IH'J III II IJ))lllll,I
устанавливает ограничения на системные ресурсы, ис
пользуемые пользователем. Ограничения по умолчанию берутся из фай
ла
/etc/security/limits.conf.
• pam_listfile -
разрешает или запрещает сервис в зависимости от значе
ний в файле. К примеру, если вы хотите открыть FТР-доступ лишь для не
которых пользователей, перечень которых указан в файле
/etc/ftpusers_ok,
auth required pam_lisifile.so item=user sense=allow
file=/etc/ftpusers_ok onerr=fail в файл /etc/pam.d/ftpd (см. также модуль
pam_nologin) .
нужно добавить строку
сообщает пользователю о наличии свежей электронной
• pam _ mail почты.
• pam_ mkhomedir -
создает домашний каталог пользователя, если он не
существует на локальной машине. Таким образом, можно использовать
централизованную авторизацию (к примеру, в
NIS или LDAP) и создавать
домашние каталоги лишь при необходимости.
выводит "сообщение дня" . См. также модуль
• pam_motd • pam_nologin • pam_permit также модуль
• pam _ rootok -
запрещает доступ, когда существует файл
безусловно разрешает доступ
-
/etc/nologin. •
очень небезопасно! (см .
pam_deny).
разрешает доступ для пользователя
ных проверок . Обычно этот модуль используется
пользователь
pam_echo.
root
root без дополнитель
в /etc/pam.d/su, чтобы
мог войти под любым другим пользователем даже без
ввода пароля . Файл должен содержать следующие строки (обратите вни
мание на вторущ строку, см . модуль
auth
auth
auth
• pam_succeed_if -
sufficient
required
required
pam_wheel):
pam_rootok . so
pam_wheel .s o
pam_unix . so
проверяет некоторые характеристики учетной записи,
к примеру, принадлежность к определенной группе , значение
• pam_ time -
•
и т.п.
запрещает доступ к службе в зависимости от дня недели и
времени дня. По умолчанию правила берутся из файла
conf.
UID
/etc/security/time.
Однако запрет накладывается лишь на момент входа в систему. Спо
соба принудительно заставить пользователя выйти из системы нет.
................................................................................... .
Янро
•
[,inux
....................... n.inux
раm_umаsk-устанавливает маску создания файлов.
или
• pam_unix
pam_unix2 - классическая аутентификация в
/etc/passwd и /etc/shadow (см . также
стиле, основана на файлах
UNIХ
модуль
pam _ userdb).
аутентифицирует пользователя с помощью базы данных
• pam_ userdb -
(см. также модуль
pam_unix).
заносит название службы , номер терминала, пользователя
• pam_ warn -
и друrие данные в системный журнал. Модуль можно использовать везде,
он не влияет на процесс аутентификации.
• pam_wheel -
позволяет rооt-доступ лишь для чл·енов группы
Часто этот модуль используется для
whee\.
su, чтобы лишь избранные пользова
тели могли пользоваться этой программой. Пример использования можно
найти в описании модуля
pam_rootok.
Если книга не посвящена отдельно РАМ, лучше всего рассматривать РАМ на
отдельных примерах .
11.4.1.
Файл
Ограничиваем доступ к системе по IР-адресу
/etc/security/access.conf
определить ,
используется модулем
каким пользователям
pam_access.so,
чтобы
позволено входить в систему и с каких
IР-адре сов.
Если открыть файл
access.conf,
то в нем будет достаточно много различных
примеров, которые хорошо прокомментированы. Если вы знаете английский
язык , то не составит особого труда во всем разобраться самостоятельно.
Формат этого файла следующий:
разрешения
пользователи
источники
Разрешение может начинаться с символа
"+"
(доступ разрешен) или
"-"
(доступ запрещен). Если нужно указать несколько пользователей, то их име-
•
IZII-·················-···--···-·------··------··------- - ·-------·------·---·------·--·
rtiпux _______ ; _. __ .. ___ _
l . 1a11a 11 . Гlо.11,юш11с.111111ру1111ы
на разделяют пробелом. Если нужно сделать исключение для некоторых
пользователей, то перед их именами указывают служебное слово ЕХСЕРТ.
Третье пол1:; может содержать список из одного или более имен консолей
(tty) - для несетевого доступа к системе, имен узлов (для сетевого досту
па), доменных имен (начинаются с".") , IР-адресов узлов , IР-адресов сетей
(заканчиваются"."). Также можно указать все источники
источников
(NONE)
или только локальные источники
(ALL), ни
(LOCAL).
один из
Теперь несколько примеров:
- : ALL
Е ХСЕ РТ
Первая консоль
r oo t:tt y l
-
это только консоль
root.
Другим пользователям запреще
но ее занимать. Мы запрещаем доступ(-) всем пользователям
(ЕХСЕРТ) пользователя
Следующий пример
-
root на
консоли
кроме
(ALL)
ttyl.
разрешение регистрации как
root с
определ енных IР
адресов :
+
+
r oot
r oot
19 2 . 168 . 1.1 1 92 . 168 . 1.4 192 . 1 68 . 1 . 9
1 2 7 .0 . 0 .1
Если нужно разрешить регистрацию
root
со всей подсети
192.168.1.0, тогда
укажите адрес этой подсети , указав точку вместо О:
+
r oot
1 92 . 168 .1.
Самый жесткий пример
r oot
-
запрещаем
root вообще
входить в систему:
ALL
Примечание . Обратите внимание, что комментарии в этом фай
ле начинаются с
#,
если вы хотите использовать один из приме
ров, приведенных в файле, убедитесь, что вы раскомментирова
ли нужную вам строку.
•
.. . --.. -. --.. -. -- ... --... -. . .. -... . ........... -... -. ·-. --- .. --.. --...... -. -...• -...
-
И 1 1ро
l ,inux
.......................~ir'i!\.IX
Чуть выше мы разрешили вход пользователя
root с определенных IР-адресов.
К сожалению, одного только редактирования access.conf будет недостаточ
но . Нужно еще отредактировать соответствующие файлы в /etc/pam.d. Нас
интересует регистрация по SSH (telnet уже не используется, поэтому вы бу
дете регистрироваться по SSH) и обычная регистрация в системе. Поэтому
нам нужно отредактировать файлы /etc/pam.d/sshd и /etc/pam.d/system-auth.
В этих файлах вам нужно добавить строчку:
account
requ ired
/ lib64/security/pam_a cces s. so
Если у вас 32-р азрядная система , тогда нужно добавить немного другую
строку :
account
/ liЬ/securi t y/pam_ acc e ss . s o
requ ired
11.4.2.
Ограничиваем время входа в систему
Безопасностью системы лучше управлять, когда вы бодрствуете. Поэтому
имеет смысл разрешить регистрацию только в это время, например, с
19:00
(вдруг кто-то немного задержится на работе).
Откройте файл
/etc/security/time.conf и добавьте
login ; tty*
! tt yp*;
&
! root
&
admin
&
;
в него строку:
!Al0800 - 1900
Здесь мы разрешаем пользо~ателям регистрироваться только с
На пользователей
файле
8:00 до
time.conf вы
root
и
admin
8:00 по 19:00.
это правило не распространяется. Также в
найдете еще несколько примеров .
Как и в случае с предыдущим файлом , вам нужно изменить файлы
pam.d/sshd и /etc/pam.d/system-auth, в
account
required
/etc/
которые нужно добавить строку:
/lib64/secu ri ty/pam_time . s o
или строку (для 32-разрядной системы):
•
. . .. . . .. .. . -. -- . -- ......... ---- .............. --- ......... ·- . ·· ·- ... -- ....... -....... ,
n.1пux ................. .
re qu ire d
acc oun t
11.4.3.
lm111a l l .
ll11.1 11.ю11:11cJ 111111p~1111ы
/ liЬ/security / pam_ti m e . so
Ограничение системных ресурсов с помощью РАМ
С помощью РАМ-модулей можно ограничить системные ресурсы, что по
лезно для защиты системы от DоS-атаки. Принцип DоS-атаки заключается
в том, что злоумышленник узурпирует все ресурсы системы , в результате
обычным пользователям ничего не остается . Ограничив системные ресурсы,
вы можете смягчить последствия DоS-атаки на ваш сервер. Конечно, полной
защиты этот способ не даст, но все равно ваш сервер будет продолжать рабо
тать, хоть и медленно. Все же это лучше , чем ничего.
Ограничить системные ресурсы можно с помощью
/etc/security/limits.conf.
Формат записей в этом файле такой:
д омен
т ип
ресурс
значение
В качестве домена указывается или имя пользователя, или имя группы поль
зователей ( @имя). Также можно указать звездочку
(*),
если ограничение
должно распространяться на всех пользователей.
Ограничения бывают мягкими
(soft) и жесткими (hard).
Мягкое ограничение
можно незначительно превысить , жесткое превысить нельзя .
Возможные значения третьего поля задают тип ограничиваемого ресурса и
представлены в таблице
Таблица
11.4.
11.4.
Ресурсы, которые можно ограничить с помощью
limits.conf
Элемент
Описание
core
Позволяет ограничить размер файла ядра (в килобайтах)
cpu
Задает максимальное процессорное время (в минутах)
data
•
Определяет максимальный размер сегмента данных (в килобайтах)
.. . . -----... --..... ·.. -.... ----. ---. ----. -. ---....... --... -... -.. -. -.. --.. -. . ... -. .
-
Ядро
Linttx
. . . .. . .. . .. ... ... .. . ... r.linux
Позволяет указать максимальный размер файла (в килобай-
fsize
тах)
Определяет максимальное количество параллельных регистраций пользователя. По умолчанию пользователю раз-
maxlogins
решается войти неограниченное количество раз разными
способами
-
по
SSH, FTP,
• Задает максимальное
nofile
с разных консолей и т.д.
число одновременно открытых файлов
Определяет число процессов, которые может запустить
nproc
пользователь
Задает приоритет, с которым будут выполняться процессы
priority
пользователя или группы
Максимальный размер стека (в килобайтах)
stack
Последнее поле определяет значение лимита. Теперь несколько примеров:
*
@ssh users
@ssh users
maxlogins
nproc
fsize
hard
hard
hard
3
5
24576
В первом случае мы ограничиваем число одновременных регистраций поль
зователей до
3
(консоль,
Xl 1,
если есть и
но) . Во втором пользователям из группы
не более
5 процессов
SSH - этого более чем
~sh_ users мы разрешаем
достаточ
запускать
одновременно. Также SSН-пользователям не разреша
ется создавать файлы размером более
24
Мб.
Обратите внимание: здесь мы просто задаем лимит на максимальный раз
мер файла. В принципе,
24
Мб вполне достаточно даже для хранения фото
графий с зеркальной камеры и больших документов
Word,
содержащих изо
бражения и другие объемные объекты. А видео и файлы большего размера
пусть пользователи хранят или на своих компьютерах, или входят иным спо
...
собом, например , по
FTP,
где можно более качественно ограничить опера
ции с файлами .
---------·: • --------------------------------- --------------------------- .
• --------
n..inux .................. .
После редактирования
Глава
11.
Пользователи II r· руппы
/etc/security/limits.conf никакие
другие файлы редак
тировать не нужно. Но описанные вами изменения будут действовать для
новых сеансов пользователей, поэтому желательно перезагрузить систему,
чтобы изменения действовали сразу для всех пользователей.
Если вам нужна дополнительная информация о РАМ, предлагаем ознако
миться с официальной документацией, доступной по адресу:
https://mirrors. edge.kernel. org/puЬ/linuxllibslpam/
•
··································--··············································-
Глава
12.
Блочный ввод/вывод
Я ;жро
Linux
12.1.
....................... r.linux
Блочные устройства
Блочные устройства
-
это физические устройства компьютера, позволя
ющие выполнять произвольный (а не последовательный) доступ к участкам
данных, называемых блоками.
Примеры блочных устройств
-
жесткий диск, DVD-накопитель, флешка.
Как правило, блочное устройство содержит файловую систему и прежде,
чем получить доступ к данным, нам нужно смонтировать файловую систему.
Поэтому можно сказать, что файловая система- это инструмент для "обще
ния" с блочными устройствами.
Кроме блочных устройств в
-
Linux
также есть и символьные устройства
это устройства с посимвол ьным вводом-выводом данных. Пример: кла
виатура, последовательный порт. Получается, что если доступ к данным
устройства выполняется в виде потока данных, оно относится к классу сим
вольных.
Вся разница между этими двумя типами устройств
в возможности выпол
-
нения произвольного доступа к данным, то есть в возможности устройства
выполнить поиск данных, переходя из одной позиции в другую . Взять ту же
клавиатуру. Она тоже выдает поток данных. Если вы наберете на клавиату
ре слово
hello,
•
то драйвер клавиатуры вернет поток из этих пяти символов,
•
•
•
. . . . .. .. ................ . .............. . .............................................
l . 1ава 12.
rl.inux .............. .
r».ю•111ыii 1шо, 1 / иы1ю. 1
расположенных в том порядке , в котором вы их ввели. При этом считывание
символов в другом порядке не только невозможно, но и не имеет смысла .
Жесткий диск работает совсем иначе. Драйвер жесткого диска может
потребовать прочитать содержимое определенного блока, а затем содержи
мое другого блока, причем эти блоки не обязательно должны следовать друг
за другом. Поэтому доступ к данным жесткого диска может выполняться
произвольным образом, а не в виде последовательного потока. Таким обра
зом, жесткий диск относится к блочным устройствам.
По сравнению с символьны:м:и устройствами при управлении блочными
устройствами в ядре им требуется уделять больше внимания , а также вы
полнять дополнительную подготовку. Связано это с тем, что символьные
устройства имеют всего одну позицию для считывания данных , причем
она всегда текущая. В отличие от него блочные устройства могут переме
щаться в любую позицию на физическом носителе информации . В самом
деле , не нужно создавать в ядре целую подсистему для обслуживания сим
вольных устройств , тогда как для блочных устройств это просто необ
ходимо . Такая подсистема необходима отчасти из-за сложности блочных
устройств . Однако основная причина такой мощной поддержки в ядре со
стоит в том , что скорость работы блочных устройств напрямую зависит от
скорости их обслуживания со стороны процессора. Действительно , выжать
максимум производительности из жесткqго диска значительно важнее , чем
получить некоторое увеличение скорости при работе с клавиатурой. Более
того , как будет показано ниже , сложность блочных устройств обеспечивает
большой простор для таких оптимизаций . Далее будет показано , как ядро
управляет работой блочных устройств и запросами к этим устройствам .
Рассматриваемая часть ядра называется уровн ем бл очного ввода -вывода
(Ыосk
12.2.
I/0 layer).
Структура блочного устройства
Наим еньший адресуем ый элеме нт бл очного устройства наз ы ва ет ся
сектором.
Сектора могут иметь разный размер, который ~ратен
размер сектора равен
512
2n, однако
чаще всего
байтам . Размер сектора определяется физически
ми параметрами устройства. Сектор является основным элементом любо
го блочного устройства. Устройства не могут обращаться к блокам данных ,
ЯЩJО
l,i11ux
...... ___ . _..... _______ t\.inux
размер которых меньше размера сектора , однако большинство блочных
устройств при выполнении одной команды позволяет оперировать несколь
кими секторами сразу. Хотя большинство блочных устройств и имеет раз
мер сектора, равный
512
байтам, все же существуют и другие стандартные
размеры сектора (например , у большинства накопителей на компакт-дисках
размер сектора составляет
2 Кбайт) .
Примечание. Сектор и блок
-
физическая единица . Блок
логическая. В одном блоке может
-
это разные вещи. Сектор
-
это
быть несколько секторов.
При разработке программного обеспечения преследуются разные цели, ис
ходя из которых выбирается минимально адресуемая единица данных , кото
рая называется блоком.
Блок
-
это абстракция файловой системы , т. е . все обращения к файловым
системам могут выполняться только с данными, кратными размеру блока.
Несмотря на то, что физические устройства сами по себе работают на уровне
секторов, ядро выполняет все дисковые операции на уровне блоков. Так как
наименьший возможный адресуемый элемент -
это сектор, размер блока не
может быть меньше размера одного сектора и должен быть кратен размеру
сектора. Более того, для ядра (так же как и для "железа" в случае секторов)
необходимо, чтобы размер блока был кратен
2". Ядро
также требует, чтобы
максимальный размер блока не превышал размер страницы памяти . Поэто
му размер блока равен размеру сектора, умноженному на число, кратное
2", и
не может быть больше размера страницы . Чаще всего используются размеры
блоков
512
байтов,
1 и 4 Кбайт.
12.3.
Буфер ы
При сохранении блока в памяти, скажем, посл е выполнения операций чте
ния или отложенной записи, он записывается в буфер
(buffer).
В каждый буфер записывается только один блок . По сути, буфер играет роль
объекта, представляющего дисковый блок в оперативной памяти .
Напомним: блок состоит из одного или нескол ьких секторов и по размеру не
может быть больше одной страницы п амяти .
a:t ------------------------------------------------------ ------------- ------------_,
1тша 12.
n..inux __ ___ ____ __ ____
Блоч11ыii ввод/ выво:1
Поэтому в одной странице памяти может находиться один или несколько
блоков. Поскольку для ядра требуется некоторая управляющая информация,
связанная с данными (например, какому блочному устройству и какому бло
ку соответствует буфер), то с каждым буфером связан свой дескриптор. Этот
дескриптор называется заголовком буфера
(buffer head)
и представляется с
помощью структуры buffeг_head, которая определена в файле <linux/Ьuffer_
head.h>.
В ней содержится вся информация, которая необходима ядру для
управления буферами:
struct buff~r_head {
unsigned long b_state ;
struct buffer head *Ь this page ;
/* · Флаги состояния буфера*/
/* Сп ис ок буфер о в , находящихся
в
struct page *b_page ;
sector t b_Ыoc k nr ;
size_t b_size ;
char *b_data ;
/*
/*
/*
/*
текущей
Ссылка
странице
на
Начальный
Размер
памяти*/
страницу
номер
памяти* /
блока*/
отображе ния* /
Ука затель
на
данные
внутри
страницы*/
struct Ыосk device *Ь bdev ;
/*
bh end_io_t *Ь end_io ;
/*
void *b_private ;
/*
struct list head Ь assoc_buffers ;
/*
struct address space *9_assoc_map ; /*
Св язанн ое
блочное устройство*/
Метод завершения
Зарезервировано
ввода - вывода*/
для
b_end_io */
С писок
свя занных
отображений
список
связанных
адресных
*~
пространств*/
atomic t
Ь
count ;
/*
Счетчик использования*/
};
Поле Ь _state хранит состояние буфера, а состояния могут быть следующими :
•
ВН _ Uptodate
-
буфер содержит корректные данные.
буфер изменен (содержимое буфера новее соответствующих
• BH _ Dirty -
данных на диске и поэтому буфер ; в конечном счете , должен быть записан
на диск).
•
ВН _ Lock
для буфера выполняется операция ввода/вывода с дисково
-
го устройства, поэтому он заблокирован для доступа со стороны других
процессов.
• BH_Req -
буфер включен в запрос на выполнение операции
• BH_Mapped -
1/0.
буфер содержит корректные данные и отображен на дис
ковый блок.
•
•
ВН _New
-
буфер только что отображен с помощью функции
get_ Ыо'сk()
·- ·· ·--···· · ·--· ·--- -·--·-·------··· -· ··--··---·--- · · --· ·- -···-----··· · --··---· ··- -
Я , 1р11 l,i1111x
•
______ ................. n.1nux
ВН _ Async_ Read
-
для буфера выполняется асинхронная операция чтения
с помощью функции
•
ВН _Async_ Write
-
end_buffer_ async_read()
для буфера выполняется асинхронная операция запи
си с помощью функции
•
ВН _Delay
-
end_buffer_ async_write()
с буфером не связан дисковый блок,
буфер является последним в последовательности смеж-
• BH_Boundary ных блоков.
•
ВН _Write_EIO
при записи буфера произошла ошибка ввода/вывода,
•
ВН_ Ordered - упорядоченная запись,
•
ВН _Eopnotsupp
-
• BH_Unwritten -
-
операция на заданном буфере не поддерживается ,
место под данные буфера было выделено на устройстве,
но сами данные еще не записаны ,
•
ВН_ Quiet
-
подавить ошибки при выполнении операций ввода-вывода
для этого буфера,
В поле
b_count
хранится счетчик использования буфера, Значение этого
поля увеличивается и уменьшается с помощью двух· встраиваемых функций,
которые определены в файле <linux/Ьuffer_head.h>, как показано ниже.
static inline void get_bh(st ru ct buffer head *bh)
(
atomic_inc(&bh->b_count) ;
static inline void put_bh(struct buffer head *bh)
(
atomic_dec (&bh->b_count);
Перед тем как обращаться к полям заголовка буфера, необходимо увели
чить значение счетчика использования с помощью функции
get_bh().
Это
гарантирует, что во время работы с буфером он не будет освобожден другим
процессом. Когда работа с заголовком буфера будет закончена, необходимо
уменьшить значение счетчика ссылок с помощью функции
put_bh().
Данному буферу соответствует физический блок с логическим номером
b_ Ыocknr,
который находится на устройстве
b_bdev.
lllt···················································· · ,·- ·················-·· ·· ·· '
1 1ава 12.
n.inux .... .......... .
li. 111•111ыii 1шо. 1 / 11ы110. 1
В поле Ь _yage хранится указатель на физическую страницу памяти, в ко
торой располагаются данные буфера. В поле Ь _data хранится указатель на
данные блока, расположенные на странице памяти Ь _yage, размер блока
хранится в поле Ь_size. Следовательно, блок хранится в памяти , начиная с
адреса
b_data
и заканчивая адресом
(b_data + b_size).
Заголовок буфера предназначен для описания соответствия между дисковым
блоком и буфером, находящимся в оперативной памяти компьютера и пред
ставляющим собой последовательность байтов, которые расположены в ука
занной странице памяти. Единственное назначение этой структуры данных
ядра
вып9лнение роли дескриптора отображения "буфер-блок".
-
12.4.
Планировщики ввода/вывода
Ожидающие события ввода-вывода планируются или сортируются с помо
щью ал.горитма постановки в очередь, также называемого лифтом
tor),
(eleva-
поскольку аналогичные алгоритмы можно использовать для наиболее
эффективного планирования лифтов. Не существует единого лучшего алго
ритма, выбор зависит от вашего оборудования и от рабочей нагрузки.
Настройка выполняется по диску, а не по разделу, поэтому, если на первом
диске есть разделы, содержащие
/,
/Ьооt и /Ьoot/efi, все три файловые систе
мы должны обрабатываться одинаково. Поскольку вещи в /Ьооt нужны лишь
изредка после загрузки, если вообще когда-либо, то рассмотрите возмож
ность использования вашего корневого раздела для выбора алгоритма для
всего
/dev/sda.
Настройка выполняется с помощью объекта ядра /sys/Ьlock/sd*/queue/sched
uler. Вы можете прочитать его текущее содержимое с помощью команды
cat. В выходных данных перечислены все алгоритмы организации очередей,
поддерживаемые ядром. Используемый в настоящее время, заключен в
квадратные скобки:
# grep .
/s ys / Ыock / sd* / queue / scheduler
/sys/ Ьlo ck/sda/queu e / scheduler:noop
/ sys/Ьlock/sdЬ/q ueue /sc heduler:noop
/ sys/Ыock/sdc/queue/scheduler :n oop
/ sys / Ьlock / sdd/queue /sc heduler:no o p
•
deadline
deadline
deadline
deadline
[cfq]
[cfq]
[cfq]
[cfq]
·--------------- ------ ------ ---- -------------------------------------------------- \
Ядро
..... ________ ......... . t\.iпux
[,inux
Вы можете изменить содержимое объекта ядра и выбрать другой алгоритм
с помощью
echo:
# cat /sys/Ьlock/sdd/queue/scheduler
noop deadline [cfq]
# echo deadline > /sys/Ьlock/sdd/queue/scheduler
# cat /sys/Ыock/sdd/queue/scheduler
noGp [deadline] cfq
Если вам лень :1итать дальше, то можем вкратце сказать следующее: исполь
зуйте deadline для интерактивных систем (рабочие станции, персональные
компьютеры) и поор для автоматических вычислений . Далее мы разберемся
с планировщиками ввода/вывода более подробно .
12.4.1. Алгоритм deadline
Алгоритм крайнего срока
(deadline)
пытается ограничить максимальную
задержку и сделать людей счастл ивыми . Каждому запросу ввода-вывода
назначается свой крайний срок, и он должен быть выполнен до истечения
этого таймера.
Для каждого устройства поддерживаются две очереди , одна сортируется по
секторам , а другая по крайнему сроку. Пока сроки не истекли, запросы вво
да-вывода выполняются в порядке секторов , чтобы свести к минимуму дви
жение головки и обеспечить наилучшую пропускную способность.
Данный алгоритм подойдет в следующих случаях :
1. Ваша система используется интерактивно. В вашей рабочей нагрузке
преобладают интерактивные приложения или пользователи жалуются на
низкую производительность работы диска .
2.
У вас есть база данных с большим количеством операций ввода/вывода.
3.
Операции чтения выполняются значительно чаще , чем операции запи
си , поскольку приложения чаще блокируются в ожидании именно чтения
данных
...
.
. -. .. -... --. . . -.... -.... . .. : ............... -....................... -............. .
n..iпux .............. .
1J 1ава
12.
БJJОЧIIЫЙ BBOJ t/Bl,ШOJ t
4. Ваше оборудование для хранения данных представляет собой массив
сеть хранения данных) или массив
SAN (Storage Area Network,
RAID
с
большими буферами ввода/вывода.
12.4.2. Алrоритм CFQ
Алгоритм
CFQ (Completely Fair Queuing)
или полностью справедливой
организации очередей сначала делит процессы на три класса: в режиме
реального (Jремени, с максимальной эффективностью
ствия
(Idle).
(Best Effort)
и бездей
Процессы реального времени обслуживаются раньше процес
сов максимальной эффективности, которые, в свою очередь, обслуживаются
раньше процессов бездействия.
•
Внутри каждого класса ядро пытается предоставить каждому потоку одина
ковое количество временных интервалов. Процессы по умолчанию относят
ся к классу
Best Effort,
и вы можете изменить приоритет ввода-вывода для
процесса с помощью команды
ionice.
Ядро использует последние шаблоны
ввода-вывода, чтобы предвидеть, будет ли приложение выдавать больше за
просов в ближайшем будущем, и если ожидается больше ввода-вывода, ядро
будет ждать, даже если другие процессы имеют ожидающие ввода-вывода.
Алгоритм
CFQ
может улучшить пропускную способность за счет уменьше
ния задержки . Пользователи чувствительны к задержке, и им не понравится
результат, когда их приложения связаны
CFQ.
Кому подойдет данный алгоритм:
•
Пользователи не используют систему в интерактивном режиме, во всяком
случае регулярно.
•
Вы не используете файловую систему
большую часть параллелизма в
12.4.3.
Планировщик
NOOP
XFS,
поскольку
CFQ
подавляет
XFS.
Алгоритм
NOOP
ничего не делает для изменения порядка или приори
-
тета, он просто обрабатывает запросы в том порядке, в котором они были
отправлены
•
.
.. . . . . . . . . . . . . . . . . . . . . . . . --------------------. --. --------------. -.• --------. ------.
И , 1ро J,iпux
_______________________ n..inux
Это может обеспечить наилучшую пропускную способность, особенно в
подсистемах хранения, которые обеспечивают собственную организацию
очередей, таких как твердотельные накопители, интеллектуальные контрол
леры
RAID
с собственным буфером и кэшем , а также в сетях хранения дан
ных.
Обычно это приводит к наибольшей задержке, поэтому это плохой выбор
для интерактивного использования.
Причины использования планировщика поор :
•
Ваша главная забота
-
пропускная способность, задержка вас не волну
ет. Пользователи не используют систему интерактивно.
•
Ваша рабочая нагрузка связана с процессором: большую часть времени
мы ждем, пока процессор что-то завершит, события ввода-вывода отно
сительно малы и широко разнесены.
Оба они предполагают, что вы выполняете высокопроизводительные авто
матические задания, такие как интеллектуальный анализ данных, научные
высокопроизводительные вычисления или рендеринг.
12.4.4. Настройка
планировщиков
Настройка планировщиков ввода:вывода заключается не только в выборе
нужного планировщика. У каждого планировщика есть свои параметры, ко
торые можно изменить с помощью файловой системы
sysfs.
Различные файлы (атрибуты) появляются в подкаталоге (объекте)
queue/
queue/
iosched при изменении содержимого (настройки) файла (атрибута)
scheduler. Проще увидеть, чем объяснить. Сами каталоги дисков содержат
одинаковые файлы и подкаталоги, включая файл queue/scheduler и подката
лог queue/iosched/:
# 1s - F /sys/Ыock/sdЬ/
alignment_offset discard alignment holders/
bdi@
events
inflight
capability
events_async
power/
dev
events_poll_msecs queue/
device@
ext range
range
В!I
removaЬle
ro
sdЬl/
size
slaves/
stat
subsystem@
trace/
uevent
.
·-.-.-.·----.. ----........... -... -... ---... -........ -... -... --............ -... ---.
1: 1ана 12 .
r.tinux ______________ _
# ls - F /sys/Ьlock/sdЬ/queue
add random
max hw sectors kb
discard_granularity max_ integrity_segments
discard_max_bytes
max sectors kb
discard zeroes data max segment size
hw sector size
max_segments
iosched /
min i mum io size
iostats
nomerges
logical Ыосk size
nr_request
Б.юч11ыii вво, 1 / выво. 1
optimal_i o_size
physical_Ыock_size
read ahead kb
rotational
rq_affinity
scheduler
write same_ max_bytes
Давайте назна~им три разных планировщика и посмотрим , какие настраива
емые параметры появляются в их подкаталогах queue/iosched:
# echo cfq > /sys/Ьlock/sdЬ/queue/scheduler
# echo deadline > /sys/Ыock/sdc/queue / scheduler
# echo noop > /sys/Ьlock/sdd/queue/scheduler
# ls - F
/sys/Ьlock/sd[bcd]/queue/iosched /
/sys/Ьlock/sdЬ/queue/iosched/:
back seek max
fifo_expire sync
back_seek_penalty group_idle
fifo_expire_async low_latency
quantum
slice_async
slice_async_rq
slice idle
slice_sync
target latency
write_ expire
writes starved
/sys/Ыock/sdc/queue/iosched/:
fifo batch
front_merges
read_expire
/sys/Ыock/sdd/queue/iosched/ :
Планировщик
cfq имеет двенадцать читаемых и
настраиваемых параметров,
планировщик крайнего срока - пять , а планировщик
noop -
ни одного (что
логично, поскольку это не планировщик вообще) .
Настройка планировщика
В таблице
щика
CFQ.
12.1 приводится
CFQ
описание настраиваемых параметров планиров
Не все параметры полезны, поэтому в таблице
только те, которые вам , может быть, придется изменить на
•
12.1 приводятся
практике .
.. . . . . . . . . . . . . . . . . -... -........ - ....... -... -............... -......................
-
Ящ>о l , iщ1x
Табл ица
. .. . . . .... .. ..... . . ....
12.1.
Параметры план ировщика
n.iпux
CFQ
О писание
Атрибут
Количество миллисекунд, в течение которого асин-
хронный запрос (буферизованная запись) может оставаться необслуженным .
fifo - expire- async
Если требуется более низкая задержка буферизо в анной записи, уменьшите значение по умолчанию до
250
мс или рассмотрите возможность переключения
на планировщик
deadline
Количество миллисекунд, в течение которых син-
хронный запрос (чтение или 1-iебуферизованная за-
пись
O_DIRECT)
может оставаться необслуживае-
.fifo_ expire_sync
мым.
Если требуется более низкая задержка чтения, уменьшите ее со
125
мс по умолчанию или рассмотрите
возможность перехода на планировщик
О
=
deadline
отключено: задержка игнорируется , каждому процессу предоставляется полный квант времени.
1=включено:
low_latency
справедливость пропускной способ-
ности, установите максимальное время ожидания
300
миллисекунд для кю~дого процесса, выдающего
запросы ввода-вывода для устройства. Подойдет для
потоковой передачи мультимедиа-данных в реальном
времени
Количество запросов ввода-вывода, отправляемых на
устройство одновременно, что ограничивает глубину
очереди. Увеличьте это значение, чтобы повысить
quantum
пропускную способность оборудования для хранения
данных с собственным глубоким буфером ввода1
вывода, такого как
SAN
и
RAID
за счет увеличения
задержки
j
•
ID--.. ··-· --............ -.. ··-... -... ---··· --·--....... --....... -.... -.. ·-..........
j
1J1a11a 12 .
rt..inux .............. .
J;J ю•1111,1ii 1ш0J t/н1.11ю1 1
Время в миллисекундах, в течение которого
cfq будет
простаивать в ожидании дальнейших запросов.
Установите О для твердотельных накопителей или
для внешнего
slice idle
RAID
с собственным кэшем. Оставьте
значение по умолчанию
него хранилища без
8 миллисекунд для внутрен
RAID, чтобы уменьшить количе-
ство операций поиска
Настройка планировщика
Таблица
12.2
deadline
содержит параметры планировщика
dead/ine,
мы сейчас их и
рассмотрим.
Таблица
12.2.
Параметры плаtlировщика
Атрибут
deadline
Описание
Количество операций чтения или записи, выполняемых
в одном пакете.
Более низкие значения могут дополнительно умень-
.
fifo _ batch
.
шить задержку
Более высокие значения могут увеличить пропускную
способность на вращающихся механических дисках
(HDD),
но за счет меньшей задержки.
Вы выбрали планировщик
deadline чтобы
ограничить
задержку, поэтому, вероятно, не хотите ее увеличивать
Количество миллисекунд, в течение которых должен
быть обслужен запрос на чтение. Уменьшите это
read_expire
значение с
500
по умолчанию до
100
в системе с инте-
рактивными пользователями. Помните, что задержка
выше
•
..... ... . -
100
мс будет раздражать пользователей
·: ·· ........... -- .... -....... -.... -............. ···- --.......... --......
-
Я . tро
[,inux
_______________________ n.inux
Количество миллисекунд , в течение которых должен
быть обслужен запрос на запись. Оставьте значение по
write_ expire
умолчанию
5000,
пусть операции записи выполняются
асинхронно в фоновом режиме, если ваше приложение
не использует много синхронных операций записи
Число пакетов чтения, которые могут быть обработаны
writes- starved
перед обработкой пакета записи. Увеличьте это значение по умолчанию, равное 2 , чтобы дать более высокий приоритет операциям чтения
12.5.
Настройка общих параметров блочного
ввода/вывода
В /sys/Ьlock/sd*/queue вы можете настроить параметры, представленные в
таблице
Таблица
12.3.
12.3.
Общие параметры блочного
Атрибут
1/0
Описание
.
. Максимально допустимый размер запроса ввода/вывода в килобайтах, который должен находиться в еле-
тах
-
sectors- kb
дующих пределах:
= max(l, logical_Ыосk_
size/ 1024)
Максимальное значение = max- hw sectors- kb
-
Минимальное значение
& 1 - -------------------------------------------------------------------------------- - ·
t'l.iпux
I ~ 1ава
______________ _
12.
Б. 10•111ыii вио. 1/ выво, 1
Максимальное количество запросов на чтение и за-
пись, которые могут быть поставлены в очередь одновременно, прежде чем следующий процесс, запрашивающий чтение или запись, будет переведен в спящий
режим. Значение по умолчанию
запросов на чтение и
nr_requests
128
128
означает, что
128
запросов на запись могут
быть поставлены в очередь одновременно.
Большие значения могут увеличить пропускную
способность для рабочих нагрузок, записывающих
множество небольших файлов, меньшие значения ·
увеличивают пропускную способность при больших
операциях ввода-вывода.
Вы можете уменьшить это значение, если используете
приложения, чувствительные к задержке
Если он не равен нулю, устройство хранения само сообщило о своем собственном оптимальном размере
optimal_io_size
ввода-вывода.
Если вы разрабатываете свои собственные приложе-
ния, делайте его запросы ввода-вывода кратными этому размеру, если это возможно
Количество килобайт, которое ядро будет читать вперед во время операции последователыюго чтения .
кбайт по умолчанию, если диск используется с
read- ahead- kb
128
LVM,
сопоставитель устройств может использовать более
высокое значение. Если ваша рабочая нагрузка выполняет много больших потоковых операций чтения,
большие значения могут повысить производительность
Должно быть О для твердотельных дисков, но некоторые из них неправильно сообщают о своем состоянии
ядру.
rotational
Если неправильно установлено значение
1 для SSD,
установите его на О , чтобы отключить ненужную логику планировщика, предназначенную для уменьше-
ния количества операций поиска
"
·--------------------------------------------------------------------------------- -
Глава
13.
Механизмы кэширования
чтения и записи ядра Linux
____________________ . _. n.iпux
Я , tро l,i1111x
13.1. Дисковый
кэш и отложенная запись
Когда заканчивается физическая оперативная память, неиспользуемые в
текущий момент данные могут быть перемещены на диск в область
подкачки (об этом мы поговорим отдельно). Освобожденная область памя
ти будет использоваться для хранения данных и кода, необходимый систе
ме в данный момент времени. Когда данные, сброшенные в область под
качки
(swap,
своп), снова понадобятся системе, в своп будут выгружены
другие ненужные прямо сейчас системе данные, а эти будут загружены
во вновь освободившееся пространство. Понятно, что такой механизм су
щественно замедляет обработку данных, но зато позволяет обрабатывать
больше данных, чем может поместиться в физической памяти . Исходя из
этого, самый простой способ увеличить производительность компьютера
-
добавить оперативной памяти. Тогда меньше данных будет сбрасываться
на диск и повысится скорость их обработки. Следующий недорогой способ
модернизации
-
переход на SSD-накопители, скорость работы которых в
несколько раз превышает скорость работы с обычными жесткими дисками,
поэтому операции с областью подкачки будут осуществляться в несколько
раз быстрее.
Получается , что, используя механизм подкачки, мы теряем в производитель
ности . Нужно чем-то данные потери компенсировать . Как раз на этот случай
. . . . ------------ ------------------------------- ------ --- ---------- --- ------------- _,
n..inux ........... .
в ядре
Linux
1, lalШ 1.1 .
\\!':\,IIIIIHll,I l,llllll(JIШ,1111111 '111'11111111 1.1111\CII 11. 1();\ \ , il\\l\
реализована дисковая кэш-память, которая называется стра
ничным кэшем,
(page cache).
Процесс, благодаря которому изменения, внесенные в станичный кэш,
сохраняются на диске, называется отложенной записью страниц
(page
writeback).
Говоря простыми словами, данный механизм позволяет повысить произво
дительность дисковых операций .
Дисковый кэш является о:ень важным компонентом системы по следующим
причинам:
•
Доступ к данным, хранящимся на диске, осуществляется на несколько
порядков медленнее, чем доступ к оперативной памяти (миллисекунды
против наносекунд). С точки зрения
CPU
доступ к данным, расположен
ным в оперативной памяти компьютера, выполняется намного быстрее,
чем на диске, а выборка данных из кэш ей первого и второго уровня
L2)
•
(L 1 и
процессора выполняется еще быстрее.
Если к некоторым данным осуществлялся доступ, то с достаточно боль
шой степенью вероятности к этим же данным в ближайшем будущем
потребуется обратиться снова .
Принцип, согласно которому операции обращения к некоторым дан~ым
имеют тенденцию группироваться друг с другом во времени, назьiвается
временной локализацией
•
(temporal locality).
Он гарантирует, что если данные кэшируются при первом доступе к ним,
то существует большая вероятность того, что при следующем обращении
к ним в ближайшем будущем они будут находиться в кэш-памяти. Тот
факт, что доступ к памяти выполняется намного быстрее, чем к диску, а
также высокая вероятность повторного использования данных, находЯ
щихся в кэше, позволяют добиться существенного увеличения произво
дительности системы в целом
13.2.
Методы кэширования
Страничный кэш состоит из страниц физической памяти. Содержимое этих
-
страниц соответствует физическим блокам на диске . Размер кэша может
•
.. . --. -----.......... -............ -.......................... -........ -....... . ...
Ядро
[,inux
....................... n..inux
динамически изменяться
-
это вполне естественно. Когда есть свободная па
мять, он увеличивается, когда памяти не хватает
-
он уменьшается. Устрой
ство хранения данных, которое кэшируется, называется внешней памятью,
поскольку в этом случае диск как бы расположен за пределами кэша и ис
пользуется в качестве первоисточника данных, которые в нем хранятся.
Прежде чем начать операцию чтения, например, если из приложения вызы
вается функция
read(),
ядро сначала проверяет, находятся ли нужные данные
в страничном кэше. Если они там есть, то дисковая операция не выполняется,
а данные копируются прямо из памяти. Если данные были найдены в кэше,
тогда это считается удачной попыткой
(cache hit), а вот если данных там
(cache miss). После неудачной
блочных операций I/O, чтобы считать
не было, тогда поп'ытка считается неудачной
попытки ядру нужщ) выполнить ряд
данные с диска. Как только эти операции будут выполнены, ядро помещает
считанные с диска данные в страничный кэш. Все последующие обращения
к этим данным будут выполнены из кэша, обращений к диску не будет. Нуж
но отметить , что кэшируются только те данные, к которым осуществляется
доступ. Если программа, например, прочитала только часть файла, то только
эта часть будет помещена в кэш, а не весь файл.
С кэшированием чтения все понятно. А что насчет кэширования записи?
Представим, что некоторое приложение выполняет системный вызов
write().
Далее может использоваться одна из трех стратегий:
1.
Без кэширования
(nowrite) -
записываемые данные кэшироваться не
будут. Если в кэше находится фрагмент данных, соответствующий тому,
который в настоящий момент выводится процессором на диск, то этот
фрагмент в кэше будет аннулирован. В результате при следующей опе
рации считывания этого фрагмента с диска он будет снова загружен в
кэш. В результате при следующей операции считывания этого фрагмента
с диска он будет снова загружен в кэш-память. Такая стратегия очень ред
ко используется при реализации кэш-памяти, так как при этом не только
не кэшируются записываемые на диск данные,
но еще и аннулируется
содержимое кэша. В результате снижается производительность дисковой
подсистемы и увеличиваются накладные расходы.
2.
Кэш со сквозной записью
(write-through cache)- данные,
записываемые
на диск, одновременно обновляются как в дисковом файле, так и в па
мяти . Данные после обновления кэша незамедлительно сбрасываются на
диск. В этой стратегии данные в кэше и во внешней памяти находятся
•
11!1 ·.. --.. --... -... --... -"". -.".... -.-.... ".. "" ... -".. "-.. --... --... --".. -."-... ---..
n..iпux ........... .
1 ·лава
13 . Мсхашвмы
к111111р1ша111111 •11с111111111а1111с1111 1 1pa l.i1шx
в согласованном состоянии. Не нужно аннулировать содержимое кэша.
Также нужно отметить простоту этой стратегии.
3.
Отложенная запись
(write-back) -
данные при записи помещаются непо
средственно в страничный кэш. Незамедлительное или непосредствен
ное обновление внешней памяти не выполняется. Вместо этого страницы
с обновленными данными в кэше помечаются как несохраненные
(dirty)
и помещаются в список несохраненных страниц
ществует специальный процесс, называемый
(dirty list). В системе су
writeback, который перио
дически сохраняет страницы, находящиеся в этом списке, на диск. В ре
зультате _происходит синхронизация данных, находящихся в памяти и на
диске. После этого признак не сохранения страниц сбрасывается. Страте
гия с отложенной записью считается более прогрессивной по сравнению
со стратегией со сквозной записью. Из-за переноса операции сохранения
на более поздний срок система может собрать все измененные до этого
момента данные и записать их на диск за один раз. Производительность
дисковой системы существенно повышается, как и сложность реализа
ции стратегии кэширования.
А что насчет удаления данных из кэша? Ведь его объем не безграничный
и
мы. не
можем
прокэшировать
все
на
свете,
поэтому
нужно
проду
мать алгоритм удаления данных из него. В
алгоритм вытеснения данных из кэша
в
Linux
Linux для этого используется
(cache eviction). Вытеснение данных
выполняется путем простой выборки синхронизированных (т.е.
тех, что уже сохранены на диске) страниц памяти и замещения их содер
жимого чем-нибудь другим. Если таких страниц недостаточно в кэше, ядро
запускает процесс отложенной запис и , чтобы можно было освободить до
полнительные страницы. Самое сложное здесь решить, что именно нужно
вытеснять. Нужно избавляться от тех страниц памяти, к данным которых не
будут обращаться в ближайшем будущем. Понятно, что чтобы знать какие
именно страницы нам 1:1е понадобятся в будущем, нужно как-то заглянуть в
это будущее. По этой причине такую стратегию ч.асто называют алгоритмом
предсказа ния. Очевидно , что данная стратегия просп~ идеальна, но ее невоз -.
можно реализовать.
Поэтому вместо стратегии предсказания используется либо стратегия ми
н.~ин ал ьного использования (в различных ОС) либо стратегия с двумя
списками (в
•
.
Linux).
Начнем со стратегии минимального использования .
" " " " " . " " " " " " . " " " " " " . " """" "
..
" ""
... ..
""
""
". """
..
""". """
..
".".". ". "
..
" ""
..
" "". """"
...
И , 1ро [,i1шх
________ . ___ .. __ . ______ t't.inux
Одним из самых удачных алгоритмов аппроксимации, особенно для кэш
памяти общего назначения, считается алгоритм замещения элемента с са
мым старым временем последнего обращения
(least recently used, LRU). Для
LRU требуется, чтобы с
реализации стратегии вытеснения по алгоритму
каждой страницей кэш-памяти бьmа связана временная метка, фиксирующая
время последнего обращения к ней, либо чтобы список всех страниц кэш
памяти был упорядочен по времени последнего обращения. Тогда можно
легко удалить страницы с самым старым временем последнего обращения
или удалить страницы, находящиеся в начале списка (при условии, что стра
ницы с недавним временем обращения находятся в его конце). Чем дольше
к фрагменту данных, находящихся в кэш-памяти, никто не обращается, тем
меньше шансов на то, что к нему кто-то обратится в ближайшем будущем.
Все довольно просто , Однако есть и недостаток, который проявляется при
однократном доступе к множеству файлов на диске. В таком случае помеще
ние всех страниц с самым старым временем последнего обращения в начало
списка не является оптимальным. Как и прежде, ядро не может знать за
ранее, сколько раз будут обращаться к каждому конкретному файлу. Однако
ядру известно, сколько было обращений к файлу за прошедший интервал
времени.
Теперь перейдем к стратегии с двумя списками
(two-list strategy).
Вместо
поддержки одного списка элементов, упорядоченных по времени последне
го обращения (так называемый список
LRU),
в
Linux
используются два
списка: активный и пассивный. Страницы, находящиеся в активном списке,
рассматриваются как "необходимые", и по этой причине их нельзя вытеснять.
Страницы из пассивного списка могут быть вытеснены из кэша. Страницы
помещаются в акт!iвный список, только если при обращении к ним они на
ходятся в пассивном списке. При обслуживании обоих списков используется
псевдо-LRU подход: элементы добавляются в конец списка и удаляются из
его начала так же , как и в очередях. Размеры этих списков поддерживаются
примерно одинаковыми. Если активный список становится слишком длин
ным по сравнению с неактивным списком, часть его элементов переносится
в неактивный список и становится доступной для вытеснения. Стратегия с
использованием двух списков позволяет избавиться от недостатка класси
ческого алгоритма
LRU,
связанного с однократным доступом к большому
числу элементов. Она позволяет применить простой псевдо-LRU подход для
управления элементами списков. Описанный выше подход с двумя списка
ми часто называют
LRU/2. Его можно
LRU/n.
обобщить для случая с n-списками, и
тогда он будет называться
•
. . . --.................... . .................. -· ............. -.... -............ -..... .
1 1,11\,1 1\
rl.tnux .. ......... .
13.3.
\Jex:11111 l\11,1 1, )11111/)0IHIIIIOI '111.'111111 11 lШIIICJI 11,1р:1 (jщ1х
Кэширование н а практике
Как уже отмечалось, ядро
раций чтения и записи
Linux
для повышения производительности опе
использует собственный механизм кэширования ,
называемый кэшем страниц или дисковым кэшем. Основная цель данного
механизма -
копировать данные и двоичные файлы из хранил ища в память ,
тем самым сокращая дисковые операции ввода-вывода и повышая общую
производительность.
По умолч~нию вся свободная физическая память используется операцион
ной системой для целей кэширования страниц , и в зависимости от рабочих
нагрузок операционная система управляет своим состоянием,
к э шируя ,
повторно используя и удаляя файлы по мере необходимости .
Даже при текущей более высокой пропускной способности SSD-накопител ей
кэширование файлов в памяти приводит к повышению производительности
системы .
Также довольно распространено заблуждение, что операционная система
Linux
использует слишком много памяти для кэша и это может отрицатель
но сказаться на пользователях систем с небольшим объемом ОЗУ, пользова
телей ноутбуков и мини-систем. На самом деле это хорошо. Использование
большого объема памяти под кэш означает, что многие вещи уже кэширова
ны и многие из наших приложений будут работать быстрее из памяти.
Важно всегда помнить, что кэшированная память всегда является свободной
доступной памятью, которая будет освобождаться по мере необходимости.
Если процессу нужно будет больше памяти, то она будет получена за счет
кэша .
Давайте посмотрим, как работает кэш на практике на примере использова
ния файла размером
2 Гб.
На момент проведения следующего эксперимента
(если вы хотите повторить за нами) убедитесь (команда/rее
- h),
что у вас
больше свободной памяти, чем размер файла, который вы будете читать. В
нашем случае свободной памяти должно быть больше чем
2 Гб .
Посмотрим, что у нас с памятью до начала эксперимента :
# free - wh
Me m:
Swap :
•
to tal
5 . 8G
u sed
9 4М
fre e
5 . 7G
ов
ов
ов
s hared
608 К
b uffe r s c ache
2 . lM
49М
availaЫe
5 . бG
.. -------- --. ---. ----. ---. ---. ----. ---. ---.. ---- ---.. ---. ---.. -------------------. . .
Ящ)()
l.i11Ux
_______________________ n.inux
Далее мы сгенерируем файл размером
2 Гб
и сбросим все кэши:
# head - с 2G </dev/urandom > dummy . file
# echo 3 > /proc/sys/vm/drop caches
Затем мы подсчитаем количество строк в файле и вычислим продолжитель
ность выполнения этой операции:
# time wc - 1
dщnmy.file
8387042 dummy . file
real 0m3.731s
user 0m0.278s
sys 0ml . 223s
Выполним ту же команду снова :
# time wc - 1 dummy . file
8387042 dummy . file
real 0ml . 045s
user 0m0 . 575s
sys 0m0 . 471s
Второе выполнение заняло гораздо меньше времени, потому что файл был
закэширован в страничном кэше, и это само по себе улучшило операцию
чтения. Давайте еще раз посмотрим, что у нас с памятью:
_# free - wh
total
Mem : 5.8G
Swap :
ов
used
94М
free
3 . 7G
ов
ов
Свободной памяти стало на
shared
608К
2
buffers
2.lM
cache • availaЫe
2 . lG
5 . SG
ГБ меньше, а использование буферов и кэша
значительно увеличил ось.
Кэш
-
это часть памяти, в которой хранятся файлы и двоичные файлы,
таки е как общие библиотеки, данны е, чтобы будущие запросы на эти дан
ны е м огл и обрабатываться быстрее.
Буферы
-
это метаданные, относящиеся к кэ шу.
a t --------------------------------------------------------------------------------'
n..inux ........... .
1. 1а11а 13
Mt·x:11111 !\JЫ 1.: 111111р1111:1111111 •1 н· 111111 11 1a1111t·11 11 111а
l .i1111,
Снова сбросим кэши:
# sysctl - w vm . drop
caches=З
Далее мы будем использовать команду
vmtouch,
с помощью которой можно
увидеть, прокэширован файл (или его части) или нет.
# vmtouch - v dummy . file
dummy . file
[
]0/52 428 8
Files: 1
Directories : О
Resident Pages : 0/524288 0/2G 0 %
Elapsed: 0 . 013999 seconds
Затем опять прочитаем наш файл:
# time wc -1 dummy . file
8387042 dummy .file
real OmЗ . 732s
user Om0 . 284s
sys Oml . 539s
Посмотрим, что скажет
vmtouch:
# vmtouch - v dummy . file
. file
[OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOJ524288/52 4288Files : 1
Directories : О
Resident Pages : 524288/524288 2G/2G 100%
Elapsed : 0 . 024309 seconds
dщmny
Как видим, наш файл прокэширован полностью.
Все это хорошо и понятно, когда размер доступной оперативной памяти пре
вышает размер файла, который мы пытаемся прочитать. Но не всегда это
так. Что будет с кэшем, если мы попытаемся прочитать файл, размер которо
го больше, чем объем доступной памяти?
•
.... ------ ------- ------.---... ---.. --- ------- --------- --.. ---- -- ------. ----- -----·ID
Я . tро
l,inux
_______________________ t'l.1nux
Закэшируем большой файл:
# time wc - 1 big . file
33544011 big . file
real Om14 .4-26s
user Oml . 202s
sys Omб . 737s
# vmtouch - v
Ыg
Ыg . file
.file
[
00000000000000000000000000000000000000000) 1621005/2097152
Files : 1
Directories : О
Resident Pages: 1621005/2097152 6G/8G 77.3 %
Elapsed : 0.077948 seconds
Размер файла
только
6 Гб.
8 Гб,
но как мы видим из вывода
vmtouch,
закэшировано было
Что с производительностью? Давайте прочитаем файл еще раз:
# time wc - 1 big . file
33544011 big . file
real Oml4 . 260s
user Oml.959s
sys Om4.741s
При повторном чтении производительность не увеличилась. Почему? Как
видно из вывода
vmtouch,
"голова", то есть начало файла в кэш не попала.
Хорошо , а что произойдет, если мы попытаемся прочитать хвост файла? Да
вайте попробуем:
# time tail - 5000000 big . file >/dev/null
real Om4 . 696s
user Om2 . 687s
sys Om2 . 001s
Как видите, при чтении файла с конца, мы получили прирост в производи
тельности . Получилось как бы скользящее · окно (рис.
13 .1)
и голова файла
не попала в кэш.
•
1111-··· ···-···-.. ·-·· -..... -·-· -.... ·--... -···-· ..... ···-· ---· ···-· ... ···-.......... .
t'l.iпux ........... . '
l . 1ава IJ . i\lсха11111мы 1,;ш111рона111111 ч1с1111я 11 3ап11с11 sцра J,in11x
tail
head
......
-
"
tail
-
------------- --head
Рис.
13.1.
"
Начш~о файла не прокэшировано
Кэш страниц прост, встроен в ОС и обеспечивает явные улучшения произво
дительности при чтении и записи данных. Играет важную роль в собствен
ных процессах
Linux и совместном использовании данных, оптимизируя вы
полнение ядра и пользовательского пространства.
•
........................................ .............. .......... ....................
•
Глава
14.
Устройства и модули
Я!lрО
[,inux
14.1.
_______________________
n.iпux
Типы устройств
Как ранее было упомянуто, в
Linux существует три типа устройств:
блочные,
•
символьные и сетевые.
•
Блочные устройства (Ыkdevs) позволяют адресовать фрагменты дан
ных, находящиеся на устройстве и называемые блоками.
Обычно такие устройства поддерживают операцию позиционирования, бла
годаря которой возможен произвольный доступ к данным . Примеры блочных
устройств: жесткие диски, DVD-накопители , флешки. Для доступа к блоч
ным устройствам используется специальный файл, называемый узлом блоч
ного устройства (Ыосk
device node ),
который, как правило, смонтирован в
виде отдельной файловой системы.
•
Символьные устройства
(cdevs) не позволяют адресовать отдельные
блоки данных, они предоставляют доступ к данным только в виде непре
рывного потока символов (байтов). Примеры: клавиатура, мышь, прин
теры, а также практически все псевдоустройства. Для доступа к символь
ным устройствам используется специальный файл, называемый узлом
символыюго устройства
(character device node).
В отличие от блочного
устройства приложение взаимодействует с символьным устройством на
прямую через узел этого устройства.
•
.... ------- ------ ----- -------------------------- ------------------ --------- ---------.
•
l ~ ia вa
n.inux .............. ... .
•
Сетевые устройства
(netdevs)
14.
Ус·, ройства и моду: 111
предоставляют доступ к сети, напри
мер, к Интернету, с помощью физического адаптера (например, сетевой
адаптер
Ethernet
или беспроводной адаптер
802.11 (Wi-Fi)).
В отличие от
других типов устройств, обращение к этим устройствам выполняется че
рез специальный интерфейс, называемый АРl-сокетом
(socket API).
Чтобы система могла работать с устройством, ей необходим драйвер этого
устройства. Именно он: "объясняет" системе, как именно нужно работать с
тем или иным устройством. Одно не все драйверы устройств в
Linux работа
ют с физически:r,,_1:и устройствами, которые можно увидеть и пощупать. Неко
торые драйверы являются виртуальными и обеспечивают доступ к функци
ональным возможностям ядра. Такие виртуальные устройства называются
псевдоустройствами. Самые известные из них
- генератор случайных чи
/dev/random и /dev/urandom), "пустое" устройство (/dev/
устройство (/dev/zero) и др. Однако большинство драйверов
сел ядра (устройства
null),
"нулевое"
все-таки работают с физическими устройствами.
14.2.
Модули ядра
14.2.1. Написание
Как уже отмечалось ранее, ядро
Linux
простого модуля
является монолитным (выполняется
в общем защищенном адресном пространстве). Однако также ядро является
и модульным, то есть имеется возможность расширения функционала ядра
посредством модулей. Ядро позволяет выполнять динамическую загрузку и
удаление кода ядра в процессе работы системы.
Соответствующие подпрограммы, данные, а также точки входа и выхода
группируются в общий бинарный образ, загружаемый объект ядра, который
называется модулем. Поддержка модулей позволяет создать минимальное
базовое ядро операционной системы, а все дополнительные воз~ожности
и драйверы скомпилировать в качестве загружаемых модулей, т.е. самосто
ятельных объектов. Модули также позволяют удалять и повторно загружать
код ядра, что облегчает отладку, а также' дает возможность загружать драй
веры по необходимости в ответ на появление новых устройств с функциями
"горячего" подключения.
'-
....
....... -- ... -. -------------------- ------------: . ---- ---------------------------
я ,, , 1 т1 , i,111,
Модуль
-
....................... n.1nux
это определенным образом написанная программа.
Попробуем написать модуль самостоятельно. В лист.
14.1
приведен "пустой"
шаблон, который ничего не делает, но вы можете использовать его для на
писания собственного модуля ядра.
Листинг
14.1.
Шаблон модуля ядра
Linux
#include <linux/init . h>
#include <linux/module . h>
#include <linux/kernel . h>
/*
* hello_init - функция инициализации , вызывается
* В случае успешной загрузки модуля возвращает
* и ненулев ое значение в противном случае .
при загрузке модуля .
значение
нуль ,
*/
static int hello_ init(void)
{
printk(KERN_ALERT " Init . \n ");
return О;
/*
* hello_exit - функция завершения ,
*/
static void hello_exit(void)
вызывается
при
выгрузке
модуля .
printk(KERN_ALERT "Exiting!\n " ) ;
}
module_init(hello_init) ;
module_exit(hello_exit);
MODULE_ LICENSE( "GPL " ) ;
MODULE_AUTHOR( " Shakespeare " );
MODULE_DESCRIPTION( " Hello , World! " ) ;
Функция
hello_init()
регистрируется с помощью макроса
module_init()
в ка
честве точки входа в модуль. Она вызывается ядром при загрузке модуля.
Вызов
module_init() -
это не вызов функции, а макрос, который устанав
ливает значение своего параметра в качестве функции инициализации для
текущего модуля. Все функции инициализации должны соответствовать
прототипу:
int my_i nit(void) ;
. . ..----------. -------------------------. ----------. ----. ---•---. ----~ --.. --. ---. -- -·
1J1a 11a 14.
n.1nux ................. .
Ус I poiic I ЩI 11 MOJtYJ III
Поскольку функция инициализации редко вызывается за пределами модуля,
ее обычно не нужно экспортировать за пределы видимости файла и можно
объявить с ключевым словом static.
Функции инициализации возвращают значение типа
int.
Если инициализа
ция (или то, что делает функция инициализации) прошла успешно, то функ
ция должна возвратить нулевое значение. В случае ошибки функция должна
прекратить выполняемые действия и возвратить ненулевое значение.
В рассмотренном нами случае эта функция просто выводит сообщение и
возвращает нулевое значение. В реальных модулях функция инициализа
ции регистрирует ресурсы, инициализирует работу оборудования, выделяет
структуры данных и т.д. Если рассматриваемый файл будет статически ском
пилирован в образ ядра, то функция инициализации помещается в этот образ
и будет вызвана при загрузке ядра.
Точка выхода из модуля регистрируется с помощью макроса
module_exit().
В данном примере мы зарегистрировали в качестве точки выхода функцию
hello_exit().
Ядро вызывает эту функцию перед удалением модуля из па
мяти.
Как правило , в функции завершения нужно освободить все используемые
ресурсы, остановить работу и выполнить аппаратный сброс оборудования, а
также выполнить другие необходимые при завершении работы модуля дей
ствия. Обычно в функции завершения выполняются действия, обратные тем,
что были сделаны в функции инициализации и в процессе работы модуля,
особенно это относится к освобождению всех ресурсов, оставшихся после
работы модуля. После возврата из функции завершения модуль выгружается
из памяти.
Функция завершения должна соответствовать прототипу
void my_exit (void );
Так же как и в случае функции инициализации, ее можно объявить как
static.
Если этот файл будет скомпилирован в статический обра:з ядра, то данная
функция не будет включена в образ и никогда не будет вызвана (так как если
нет модуля, то код никогда не может быть удален из памяти).
Макрос
MODULE_LICENSE()
.
позволяет указать лицензию на право копи
рования модуля
•
.-- - ................... -- -........... --..... -.. -........ -... -........ -............. . .
Ядро
[,inux
....................... n.1nux
Загрузка в память модуля без лицензии
флага
tainted
GPL
приведет к установке в ядре
(буквально "запорченный"). Лицензия на право копирования
модуля служит двум целям.
Во-первых, для информационных целей. Большинство разработчиков ядра
считают отчеты об ошибках, в которых установлен флаг
tainted,
не заслу
живающими доверия, поскольку это предполагает, что в ядро был загружен
бинарный модуль (т.е. такой модуль, который невозможно отлаживать). Во
вторых, в модулях без лицензии
служат "только для
Наконец, макрось1
GPL нельзя использовать символы,
которые
GPL".
MODULE_AUTHOR()
и MODULE_DESCRIPТION()
позволяют указать автора модуля и его короткое описание соответственно.
Назначение этих макросов чисто информационное.
14.2.2.
Сборка модуля
В пределах дерева исходных кодов ядра
Первым делом нужно решить , где именно будет находиться модуль в дере
ве исходных кодов. Драйверы необходимо хранить в подкаталогах каталога
drivers/,
который находится в корне дерева исходных кодов ядра. В этом ка
талоге драйверы делятся на классы, типы и собственно на отдельные драй
веры. Например, символьные устройства находятся в каталоге
блочные
-
в каталоге drivers/Ьlock/, устройства
USB -
drivers/char/,
drivers/
в каталоге
usЫ. Эти правила не являются жесткими, поскольку многие устройства при
надлежат к разным категориям. Например, большинство USВ-устройств яв
ляются символьными, но они располагаются в каталоге drivers/usЫ, а не в
drivers/char/. Несмотря
на подобные сложности, такая организация является
понятной и четкой, после того, как вы в ней разберетесь.
Предположим, вы хотите создать драйвер символьного устройства и сохра
нить его файлы в подкаталоге
drivers/char/.
В этом каталоге находится боль
шое количество исходных файлов на языке С, а также ряд других подката
логов. Если драйвер имеет всего один или два исходных файла, их можно
поместить непосредственно в этот каталог.
Если код драйвера состоит из нескольких исходных или других вспомога
тельных файлов,
. . . . . . ...............................................................................
n.inux ................. .
то лучше всего создать отдельный подкаталог. Здесь не существует каких
то жестких правил. Предположим, вы хотите создать отдельный подкаталог.
Для определенности предположим, что вы хотите написать драйвер для на
шего HelloWorld-мoдyля. Следовательно, необходимо создать подкаталог
helloworld в
каталоге
drivers/char/.
После этого необходимо добавить новую строку в файл
находится в каталоге
drivers/char/.
Makefile,
который
Для этого отредактируйте файл
drivers/
char/Мakefile и добавьте в него следующую запись:
obj-m += helloworld /
Эта строка указывает системе построения, что при компиляции модулей
необходимо войти в подкаталог
helloworld/.
Скорее всего, при компиляции
драйвера вам потребуется указать отдельный параметр конфигурации,
например
CONFIG_FISHING_POLE.
В этом случае в файл
Makefile
необходимо добавить строку вида:
obj-$(CONFIG FISHING_POLE) += helloworld /
И наконец, в каталоге
Makefile,
drivers/char/helloworld
необходимо создать файл
содержащий следующую строку:
obj-m += helloworld.o
Теперь система построения перейдет в каталог
fishing.ko из исходного файла fishing.c.
helloworld/ и
создаст модуль
Здесь вас может сбить с толку указан
ное расширение объектного файла .о, но в результате будет создан модуль с
расширением
.ko. Как уже говорилось, скорее всего, при компиляции модуля
драйвера с числовым программным управлением вам нужно будет указать
параметр конфигурации. В таком случае в новый файл
Makefile
необходимо
добавить следующую строку:
obj-$(CONFIG FISHING_POLE) += hell o . o
•
······-·············-----------·----·-··-·-·---·----·····-··--·----·-·----- ··· -·---811
И , 1ро
l . i1111,
.......................
t\.iпux
Вне дерева исходников ядра
Иногда нужно откомпилировать модул ь вне дерева каталогов исходников.
Например, вы не хотите перекомпилировать все модули и ждать выполнения
команды
если вы заметили ошибку в своем драйвере и вам
make modules,
нужно просто пересобрать один модуль , а не все сразу. Для этого вынесите
модуль за пределы дерева исходных кодов ядра и создайте
Makefile,
в кото
рый нужно добавить одну строчку :
obj -m := hel l oworld . o
В результате файл
helloworld.c будет скомпилирован
в файл
helloworld.ko.
1
14.2.3.
Установка модулей
Скомпилированные модули должf{ы быть инсталлированы в каталог /liЫ
modules/вepcия/kemel. Здесь каждый подкаталог каталога
kemel/
соответ
ствует расположению файлов модуля в дереве исходных кодов ядра . Напри
мер, для версии ядра
5.2.10
скомпилированный модуль драйвера
helloworld
будет находиться в файле /l iЬ/modules/5 . 2.10/keme l/drivers/char/helloworld.
ko, если
исходный код находился непосредственно в каталоге
drivers/char/.
Для _инсталляции скомпилированных модулей в правильные каталоги ис
пользуется следующая команда:
ma ke mod u l e s instal l
Разумеется, эту команду необходимо выполнять с правами пользователя
14.2.4.
root.
Загрузка модул_ей
Обычно для загрузки модуля в память используют утилиту
insmod. Эта ути
лита очень простая: она "просит" ядро загрузить в память указанный вами
•
. .. ....... ..... . ..... .... · · · ·· · · .... ........... .. .................................. .
n..iпux _______ ______ ____ _
модуль. Утилита
insmod
lтша
14.
Yc1poiic1вa 11 '\Ю;t~ш1
не отслеживает зависимости и не выполняет ни
какой интеллектуальной обработки ошибок. Использовать ее очень просто.
Обладая правами пользователя
root,
нужно ввести команду
insmod module.ko
где вместо
module.ko
необходимо указать имя файла модуля, который тре
буется загрузить . Так, для загрузки модуля управления удочкой выполните
следующую команду:
insmod helloworld.ko
Удалить модуль можно аналогичным образом с помощью утилиты
Для этого, обладая правами пользователя
root,
rmmod.
нужно выполнить приведен
ную ниже команду, в которой вместо параметра
module
укажите имя загру
женного в память модуля.
rmmod module
Например, для удаления модуля управления введите следующую команду:
rmmod helloworld
14.3.
Разработка сложных модулей
14.3.1.
Компиляция модулей из нескольких файлов исходного
кода
Представим, что наш модуль
Hello World был модернизирован и теперь
- helloworld.c и helloadds.c. Чтобы
состоит из двух файлов исходного кода
.
откомпилировать модуль из двух файлов и чтобы компилятор понимал, что
они относятся к одному модулю, нужно добавить в
'
Makefile инструкции :
.-. --------------------------- ... --.. --------------- -----------------------------.. .
Я , tро (,i11ux
... ... ................. n.inux
obj - m := h ellowo r ld . o
hell oworld- objs · = hellowor l d . o helloads.o
В этом примере сначала будут скомпилированы файлы
helloadds.c, а затем
скомпонованы в файл модуля
14.3.2. Зависимости
Утилиты работы с модулями ОС
и
между модулями
Linux
поддерживают зависимости между
модулями . Это означает, что если модуль
при загрузке модуля
helloworld.c
helloworld.ko.
mod 1 модуль mod2
mod 1 зависит
от модуля
mod2,
то
будет загружен автоматически.
Информация о зависимостях между модулями должна быть сгенерирована
администратором. В большинстве дистрибутивов ОС
•
Linux эта информация
генерируется автоматически и обновляется при загрузке системы. Для гене
рации информации о зависимостях между модулями необходимо, обладая
правами пользователя
root,
выполнить приведенную ниже команду.
depmod
Для быстрого обновления и генерации информации только о более новых
модулях, чем сам файл зависимостей , необходимо, обладая правами пользо
вателя
root, выполнить другую
d e pmod
команду:
-А
Информация о зависимостях между модулями хранится в файле /liЫ
modules/вepcия/modules . dep.
14.3.3.
Загрузка модулей с зависимостями
Утилита
insmod не очень интеллектуальная. Поэтому также существует ути
лита modprobe, которая позволяет загрузить модуль с учетом зависимостей,
•
. ... ... . . . . . -- ....... -- ........... -- ....... . ........... . ...... -... .... . .. . ......... .
fliпux ................. .
1тша 14.
Ус I рой с I на 11 I\IOJt)'. 111
выполняет проверку и обработку ошибочных ситуаций, позволяет передать
модулям параметры конфигурации и обладает другими полезными функци
ями. Для управления загрузкой и выгрузкой модулей мы настоятельно реко
мендуем использовать именно ее.
Для загрузки модуля в ядро с помощью утилиты
пользователя
root,
modprobe, обладая правами
запустите команду:
modprobe module [
параметры модуля]
где вместо параметра module необходимо указать имя загружаемого модуля.
Все следующие далее аргументы интерпретируются как параметры, которые
передаются модулю при загрузке.
Утилита
modprobe пытается загрузить не только указанный модуль,
но и все
модули, от которых он зависит. Следовательно, это наиболее предпочтитель
ный механизм загрузки модулей ядра.
Утилита
modprobe
также может использоваться для удаления модулей из
ядра. Для этого, обладая правами пользователя
root, запустите
команду
modprobe -r modules
где вместо параметра
modules
нужно указать один или несколько модулей,
которые необходимо удалить. В отличие от
rmmod, утилита modprobe так
же удаляет и все модули , от которых зависит указанный модуль, если по
следние не используются. В справочном руководстве операционной систе
мы
Linux
приведен список других , менее распространенных параметров
этой команды.
.
'
·· · · ·· ·· ···························································· · ············· - 8 8
Глава
15.
Управление хранилищем
Ядро
l,inux
....................... n.inux
В этой главе мы рассмотрим довольно таки важные вещи, имеющие значе
ние не только для работы ядра
-
Linux, но
и для самой операционной системы
подключение нового жесткого диска и его разметка в классическом вари
анте
без всяких менеджеров томов. Также мы рассмотрим
-
LVM
и то, как
можно расширить пространство группы томов, например, когда вы увеличи
ли дисковое пространство виртуального сервера.
15.1.
Подключение нового жесткого диска и его
разметка
Классической программой для разметки жесткого диска в
гих операционных системах является программа
Windows
программа
fdisk
fdisk.
Linux
и дру
Конечно, в той же
совсем другая, но названия программ совпадают.
Рассмотрим пример использования этой программы. Представим, что мы
подключили новый жесткий диск и нам нужно "ввести" его в эксплуатацию.
Тренироваться лучше всего в виртуальной машине, особенно, если вы в пер
вый раз осуществляете разметку диска.
Формат вызoвafdisk такой:
..
# fdisk
<устройство>
•
... . .. . . .. . ... . ..... .. . . .. .. .. ..... .. .. .. . ... . . ...... .. .. . . ..... ... . .. ... .. . . .... .
Глава
n.inux _________________ _
Да, команду fdisk нужно запускать с правами
что новым является устройство
15.
root.
У11равле11ие хра111ы11111ем
Далее мы будем считать,
/dev/sdb:
# fdisk /dev /sdb
Посмотрите на рис.
15.1. Я запустил
программу
fdisk для
нового и неразме
ченного жесткого диска. Программа сообщила мне, что:
•
Все и~менения хранятся только в' памяти и не переносятся на жесткий
диск до тех пор, пока вы их не запишите.
•
Устройство не содержало таблицы разделов и была создана таблица раз
делов
DOS
(по умолчанию).
Рис.
•
15.1.
Зanycкfdisk для нового жесткого диска
Рис.
15.2.
Список команд fdisk
.---- ------------- ---------------- ----------------- ------------------ ----------- ---111
Я ; {ро
Linux
______________ . ________ n..inux
Первым делом ознакомимся со списком команд fdisk. Введите команду т
для получения справки. Список команд в последних версиях fdisk разбит
на группы (рис.
Таблица
15.1.
15.2). В
таблице
15 .1 приведен
список команд fdis·k .
Команды программы fdisk
Команда
Описание
Сделать раздел активным. Данный флаг был нужен для
а
старых версий
Windows,
которые не могли загружаться
с неактивных разделов . Сейчас эта команда попросту не
нужна, а в мире
ь
с
Linux -
тем более
Редактировать вложенную ВSD-метку
Применить флаг совместимости с
DOS
'
d
Удалить раздел
/
Вывести известные типы разделов
п
Добавить новый раздел
р
Вывод таблицы разделов
t
Изменить тип раздела
V
Проверить таблицу разделов
т
Вывод справ~.
и
Изменить единицы измере1щя
х
Дополнительная функциональность (только для экспертов)
w
Записать таблицу разделов на диск и выйти
q
Выход без сохранения изменении
-
•
a:t---------·-·······-··---························-·······-·--···········--····----·
n.iпux .................. .
Глава
15. У11равлс11ие
Создать новую пустую таблицу разделов
g
Создать новую пустую таблицу разделов
G
SGI
хра1111 Jшщем
GPT
(для ОС
IRIX)
о
s
Создать новую пустую таблицу разделов
DOS
Создать новую пустую таблицу разделов
Sun
Наша задача - создать раздел (или несколько разделов, здесь решать вам) и
подмонтировать его (их) к корневой файловой системе.
Первым делом выведем таблицу разделов командой р (рис.
из рис.
60
15.3,
15.3).
Как видно
таблица разделов пуста, а размер нашего жесткого диска всего
Гб.
Corrro,,шl
(m
l'ог
l1elp):
р
isk /dev/sdb: 60 GiB, 61121509110 bytes, 125829120 s ectors
IJ11ils:
sect.11гs
.,есt.ог
size (\(19ic,1l/p/11p;ic,1\):
ol' 1 "S12
\ЛI size (miнi111..1nvпpf.irn,,I):
l)isklal)f:) t.1Jpe: dos
isk i<teнtifier: 0x1fc'?26dB
'urrmaнd
(m
fог
}1е
~,12 htjl,1:s
~,1?. htJt.es / •,1;,: l)1Jt.es
~,.17. l)IJl.es / ~.,1?. lllJt.,:s
1 ) :
Рис.
15.3.
Пустая таблица разделов
Наш диск довольно скромного размера, поэтому программа создала таблицу
разделов
DOS.
Для больших жестких дисков лучше создать табли_цу разде :
лов GРТ. Если программа неправильно выбрала тип таблицы разделов или
вы хотите изменить его принудительно, введите команду g. Посмотрите на
рис.
15.4:
я изменил тип таблицы разделов, а затем опять отобразил таблицу
разделов. Она по-прежнему пуста, но обратите внимание на ее тип
-
теперь
у нас таблица разделов GРТ.
•
•••• • ••••••••••• • •• • •••·· · ·• .. ···················· ··· ········ · -········-- · · · ·· · · · · · - I D
Я , tро
Linux
_____ . _... __________ . __ n..inux
Примечание. Таблица разделов
GPT (GUID Partition ТаЫе) яв
Firmware lnterface) стандарта, который был предложен компанией lntel на смену
стандарта BIOS. Таблица GPT использует современную систему
адресации логических блоков (LBA), а не старую систему CHS
(цилиндр-головка-сектор). Но самое главное - это размер раз
дела. В GPT можно создать раздел размером до 9.4 Збайт (9.4
х 1021 байт), а в MBR - максимальный размер раздела всего 2.2
Тб (2.2 х 1021 байт).
ляется частью стандарта
1· flf'
(ExtensiЫe
l р) • lj
1 11rr,n.11нi
(m
!rт,,te,I
,, 11ew Cl'T Ji,;kl,,beJ ((;IJID:
1пrr,n.,щl
r.m
fш·
!,с
EFI
J,clp)
,:')'J[11E11(1В'J
1ZE6 'J1H
C:l'JВCШ,f:'IDП).
р
isk /dev/sdb: 60 GiB, 61121509110 bytes, 125829120 sectors
of 1 • ',12
',12 Ьчtс•;
i:c•· ( lоч iс,,1/рJнгiи, 1 J: ',12 hчtes / ~,1/ btJte:;
1"11 si::c 'mi11irrttrrvoptim,1I). ~,1? Ь')1.1::; / ',12 h>Jte;
i•, : k 1" J,,· 1 Сч1н· i1 р t.
Pi·k i~eнt.ilicr·: ?Э'Л:4![11AB'J·12Ef,-'J11Г·C:J'JDCИl,E'IDE3
:111 i t.<;
·:,:, t,,r•
,,,т1пr ...
iorr,n.ш,t
lm f'11r J1elp):
Рис.
15.4.
Изменение таблицы разделов
Настало время создать раздел. Введите команду п. Программа попросит вас
ввести (рис.
•
15.5):
Номер раздела
-
это первый раздел , поэтому введите
1.
В принципе, ког
да вы будете создавать второй раздел , программа автоматически предло
жит вам ввести номер
2.
• Первый сектор раздела. Просто нажмите Enter - программа автомати
чески предложит правильный вариант.
•
Последний сектор раздела . Если вы хотите создать раздел на весь жест
кий диск (то есть использовать все доступное пространство), тогда
просто нажмите
Enter.
В противном случае укажите размер раздела.
Проще всего это сделать, используя модификаторы +Ми
для создания раздела размером
...
30
+G,
например,
Гб укажите +З ОG . Если у вас очень
большой жесткий диск, где пространство измеряется терабайтами, ис
пользуйте модификатор Т, например,
+ 1Т.
. . -- ---- -- .. -- .. --. -- --. -- -. --- . ------- -.. --.. ---. --------. ----. ---. -- ---- --. -- _,
Глава
t'tinux _________________ •__
orrwn.•1111
',11
·"
(m
t I f J он
t
IJ
1
'f'I
f
11г
1н·
1111ml)t"1
t111
,1•( 101,
1 р)
11
1 1 ?.В, (1t·f ,н~ lt
1)
(
<1
11.-1.J
))t\i'f 1t 1011
ortnt.ннt
(m f11г
1
of
ltJpc
Управление храншшщем
1
i/H1B 1/.'1B7'J0H6, (lt•f~н•lt ~·и1в)
•'Р( tor, ос
н 1z,·{K,M,(,,'I ,Г}
(%И4Н
r1·,,tt>(l
15.
'(.~н11л
f
1/'Jili""ЩIJf,,
11c~,ц,tt·m'
(ннi
of
1l1•f<щJI
,,1zc
1/',Н,,:'<IШН,)
(}И
t,tH
"'
lн"lp)
Рис.
15.5.
Создание иового раздела
Программа сообщит вам, что один раздел создан. Также будет сообщен раз
мер разде~а . По умолчанию тип раздела
filesystem).
t
<номер
-
файловая система
Linux (Linux
Если вы хотите изменить тип раздела, введите команду:
раздела>
Например:
t 1
Рис.
15.6.
Подсказка по типу раздела
Далее нужно или ввести код типа раздела или ввести команду
подсказки (рис.
•
L
для вывода
15.6) .
.----.. --. . -. -------. -. ---........ -----.. -. ---..... --·. -. -.. ---.. --. ---.. --- . ---... .
Ядро
Linux
_______________________ (linux
Проблема вся в том, что нет способа постраничного просмотра типов раз
дело в , . а все они н~ помещаются на одном экране. Поэтому все равно при
дется обращаться к документации. Однако в большинстве случаев изменять
ти п раздела не нужно, поскольку при создании раздела он создается уже
нужного типа . Исключение может возникнуть разве что для раздел а подкач
ки
(Linux swap ).
Его код
- 82.
Если вы передумали менять тип раздела, просто нажмите
Enter.
Теперь
введите р для просмотра нашей таблицы раздел ов. Всегда просматривайте
таблицу перед ее записью . После этого введите команду
изменений и выход~ из программы (рис.
Рис.
15. 7. Весь
w для сохранения
15.7).
сеанс разметки диска: от создания таблицы разделов до записи
изменений
Создать раздел мало. Нужно еще создать файловую систему. Не будем ни
чего выдумывать и создадим стандартную файловую систему
ext4 командой
mkfs.ext4:
# mkfs . ext4
/dev/sdЫ
•
а:а - ------.---.---.. ------. -----.--.. --------.---.. ---.--. -----.--. -----.---.. ------.
Глава
n..inux .................. .
15 . У11равJ 1е11ие
Результат выполнения этой команды приведен на рис.
Рис.
15.8.
хра11ш1ищем
15.8.
Создание файловой системы и монтирование жесткого диска
После этого нужно создать точку монтирования для нового раздела и под
монтировать раздел (название точки монтирования можете изменить по сво
ему усмотрению):
# mkdir /mnt/sdЫ
# mount /dev/sdЫ
# 1s /mnt / sdЫ
/mnt/sdЫ
Почти все готово. Осталось только добавить запись. в
/etc/fstab
для автомати
ческого монтирования созданного раздела:
/dev/sdЫ
/mnt/sdЫ
ex t4
defaults
1 1
Вот теперь можно приступать к использованию нового жесткого диска .
•
.. ---.. - .. ---... -... -.... -.. --... --....... -.... -... -.... -· .. -... --... -... --... -.... .
Ядро
Linux
15.2.
_______________________ n..inux
Менеджер логических томов
15.2.1.
Введение в
LVM
Впервые менеджер логических томов
(LVM, Logical Volume Manager)
LVM 1), но более активно он стал
применяться только в дистрибутивах с ядром 2.6 (уже вторая версия LVM 2).
появился в ядре
2.4
(его первая версия
Некоторые современные дистрибутивы используют
создают пулы
LVM,
LVM
в некоторых же
чанию. Чтобы понять, нужен ли
LVM даже не
вам LVM, нужно
по умолчанию и
установлен по умол
разобраться, что это
такое. В этой части главы все будет изложено максимально доступно, так
что бояться использовать
LVM
не стоит. В тоже время, если вам необхо
димы точные академические определения и дополнительная информация ,
обратитесь к
Linux LVM Howto (http://tldp.org/HOWTO/LVM-HOWTO/),
в
котором много технических подробностей (если они вам нужны) и не
совсем все сразу понятно.
LVM -
это дополнительный уровень абстракции над аппаратными сред
ствами, позволяющий собрать вместе несколько дисков в один логический
диск, а затем разбить его так, как вам хочется.
Примеров использования
LVM
множество. Самый простой из них
-
объединение нескольких небольших дисков в один диск большего размера.
Например, вам досталось даром (или почти даром) • несколько SSD-дис·ков
небольшого размера, скажем, по
ка, чтобы получить один
128 Гб и вы хотите объединить эти 2-3
большой диск 256-384 Гб.
дис
Второй пример тоже часто распространен. Представим , что система у вас
установлена на небольшом диске, пусть даже на том же SSD-диске размером
80
Гб. Для
Linux
такой объем вполне достаточен, но рано или поздно сво
бодное место закончится (все зависит от файлов, с которыми вы работаете).
Вы покупаете диск большего размера, скажем, на
500
Гб или даже на
1 Тб.
Но система уже установлена и переустанавливать ее не хочется. Что делать?
Здесь вам поможет
LVM.
Первый приведенный мною пример
( объединение
трех дисков во время
установки) слишком тривиален и с ним справится любой, даже самый на
чинающий пользователь -просто во время установки нужно выбрать
LVM
•
&1---------------------------------------------------------------------------------·
f'liпux __________________ _
l ; iaвa
15 .
У11равлс1111с хра11или1щ•м
(если, конечно , дистрибутив его поддерживает) и выбрать диски, которые вы
объединяете в группу (пул) .
Второй пример более сложный только за счет того, что система уже уста
новлена, и мы договорились , что переустанавливать ее не будем. Поэтому он
и заслуживает рассмотрения в этой главе, а дополнительную информацию
вы сможете найти в
Linux LVM Howto,
ссылка на который была приведена
ранее.
15.2.2. Уровни
абстракции
LVM
Прежде, чем перейти к рассмотрению практической стороны вопроса, нуж
но разобраться с тремя уровнями абстракции, с которыми вам придется
столкнуться в
•
LVM. Вот эти
уровни:
физические тома. Это могут быть разделы или
PV (Physica\ Volume) -
целые , еще не размеченные д иски .
группа томов. Физические тома объединяются в
• VG (Vo\ume Group) -
группу и создается единый диск , который вы можете разбить так, как вам
хочется .
•
LV (Logical Volume) диска (VG), который вы
логический раздел. Это раздел нашего единого
можете отформатировать в любую файло вую си
стему и использовать так, как вам хочется, как обычный раздел о бычного
жесткого диска.
Прежде, чем мы продолжим, вы должны знать об одном недостатке.
Тома
LVM
не поддерживаются загрузчиком
GRUB .
LVM.
Поэтому если в ы ис
пользуете этот устаревший з агрузчик, вам нужно создать отдельный р аздел
/Ьооt за пределами
/dev/sdal
LVM.
Грубо говоря , если у вас есть диск
/dev/sda,
р аздел
должен монтироваться к /Ьооt. В него будет установлен загрузчик.
Размер этого раздела должен быть небольшой , примерно
100
Мб (вполне
будет достаточно) .
Что же касается
GRUB2, то
он нормально загружается с
LVM
и никакой до
полнительный раздел создавать не нужно .
•
. -------- -- -. ----- -- . -- --·-- -- --- . -- --. -------. -- ---- --- . --. ·- --.. --. -- -- ·- ---- --.. . .
Ядро
Linux
....................... n.inux
15.2.3. Немного
практики
Первым делом вам нужно установить пакет
lvm2 ,
если он еще не установ
лен.
# apt - g e t install lvm2
# yum inst a ll lvm2
Команда установки этого пакета для
Fedora/CentOS
приведена на всякий
случай, так как в большинстве случаев этот пакет в этих дистрибутивах
установлен по умолчанию.
Будем считать, что система сейчас установлена на
монтирован как
/. Больше
/dev/sdal ,
который под
никаких разделов на этом диске не создано
-
для
упрощения примера. Мы подключили второй жесткий диск, который пока
еще не разбит. Имя этого диска
- /dev/sdb.
Если на втором диске не созданы разделы, то создавать их и не нужно. Вы
можете сделать все устройство сразу физическим томом
есть разделы
-
(PV). Если
на нем
не беда, вы можете добавить в группу томов все разделы
поочередно .
Тратить время на создание разделов не хочется, тем более , что это и не нуж
но , поэтому создаем
команда
PV
на все устройство
/dev/sdb.
Для этого используется
pvcreate:
# pvc r eate /dev/sdb
Phys·ical volume " /dev/sdb " successfully created
Теперь нужно создать группу томов с помощью команды
vgcreate.
Данной
команде нужно передать имя группы (пусть это будет ту_vg) и указать фи
зическое устройство:
# vgc r eate my_vg /dev/sdb
Volume group " vgO " successfully created
Создаем отдельные логические тома (команда
ки
(swap)
и разделов
/home, /tmp
и
/var.
lvcreate) для раздела подкач
-L задает размер раздела,
Параметр
•
8 8 - ················.······························-·························-·······-·
1J 1ана 15. У11раи: 1е11ие
n..inux __________________ _
например, -LЗOG задает размер
30
хра1111 . шщем
Гб. Параметр -п задает имя логического
тома:
#
#
#
#
lvcreate
l vcreate
lvc r eate
lvcrea t e
-n
-n
-n
-n
swap - 18G ту- vg
home - 1500G my - vg
var - 130G ту - vg
t mp - 15G my - vg
Последний параметр
-
это имя нашей группы. При желании можно создать
отдельный раздел и для
но, как правило, программное обеспечение (а
/usr,
оно в основном устанавливается в
обшем, смотрите сами
-
/usr)
в
Linux
много места не занимает. В
никто не мешает ввести еше одну команду
lvcreate.
Тем более что у нас еще осталось место (если учитывать, что у нас жесткий
диск на
1 ТБ).
Теперь разберемся , что и где мы создали. Просмотреть информацию по фи
зическим томам, группам томов и логическим разделам можно с помощью
команд
pvdisplay, vgdisplay
и
lvdisplay
соответственно.
Созданные нами разделы будут храниться в папке
/dev/my_ vg/. В
л оге вы найдете файлы
будут ссылки, а не файлы ,
home, tmp, var (правда, это
этом ката
но суть от этого не меняется) .
Когда созданы логические тома, можно создать на них файловые системы
(отформатировать их). Вы можете использовать любую файловую систему,
я предпочитаю
#
#
#
#
#
ext4:
mkfs . ex t4 - 1 va r · /de v/my_ vg/var
mkfs .e x t4 - L h ome /dev/my_vg/home
mkfs . ext4 - 1 tmp /dev/my_vg/tmp
mkswap - 1 swap /dev/my_vg/swap
swapon /dev/my vg/swap
Первые три команды создают файловую систему
my_ vg/var, /dev/my_ vg/home
и
/dev/my_ vg/tmp.
ext4
на устройствах
/dev/
Последние две создают раз
д ел подкачки и активируют его.
Настало время заняться перемешением данных. Суть в следующем
-
нужно
подмонтиррвать пооч ередно новые тома и скопировать в них содержимое
/hоше и /var:
•
•.·-. -·-.. ·.·. -.... --.......................--... -- -·-· .. -·· ..... --... ---...··-... ---ID
Я , 1ро
l.inux
..... .... .............. t't1nux
# mkdir /mnt/home
# mkdir /mn t /va r
# mount / dev /my_vg / home / mnt / home
# mount /de v/my_ vg/var /mnt /va r
#
#
ер
-а
ер
-а
/home/* / mnt / home
/var/ * /mnt / var
# umount /mnt/home
# umount / mnt /vq.r
В папку
/tmp
копировать ничего не нужно . Нужно только изменить права
доступа:
#
#
#
#
mkdir /mnt/ tmp
mount / dev / my vg/tmp /mnt/tmp
ehmod - R a+rwx /mnt/tmp
umount / tmp
Почти все. Теперь нужно добавить в
вые системы
/home, /var, /tmp
/dev/mapper /my_vg-h ome
/dev/mapper /my_vg - var
/ dev /mapper / my_vg - tmp
/dev/mappe r /my_vg - swap
/etc/fstab
записи, монтирующие файло~
и указать в нем раздел подкачки:
/ home
/var
/tmp
п о пе
Все готово. Остал ось только ввести команду
ext4 relatime
ext4 relatime
ext4 noat i me .
swap SW
reboot,
1 1
1 1
о 2
о
о
чтобы система переза
грузилась. Корневая файловая система осталась на старом жестком диске
(как и
/usr),
а каталоги , которые занимают больше всего места, были пере
мещены на логические разделы
LVM.
•
&1---------------------------------------------------------------------------------- ·
J alaBa
n..inux ____ .. _.. ____ .....
15.3.
15 .
Y11p.tHJICIIIIC xpaJIIJ J IIIЩCM
Расширение LVМ-пространства
Предположим, что вы расширили дисковое пространство виртуального
сервера. Однако одного расширения в панели управления недостаточно
-
чтобы система увидела изменения, нужно произвести определенные дей
ствия. В принципе, задачу расширения пространства сервера можно было
решить иначе, например, добавить еще один виртуальный жесткий диск,
а дальше или использовать классический способ или же добавить диск в
группу ТО!'._ЮВ
-
все зависит от того, как настроена операционная система
виртуального сервера. Но случилось то, что случилось
-
вы уже расшири
ли жесткий диск, а вернуть ресурсы в пул, как правило, нельзя. Поэтому
рассмотрим процедуру расширения виртуального диска.
Первым делом, посмотрим, сколько сейчас дискового пространства доступ
но. Для этого используется уже известная команда df с параметром -h, чтобы
вывод был в удобочитаемом формате:
df -h
Рис.15.9. Команда
df-h
На данный момент общий размер группы томов
составляет
19
/dev/mapper/vgroup 1-root
Гб . Однако мы расширили диск и теперь нам нужно расши
рить размер этой группы томов до полного размера диска.
Чтобы система увидели новый объем жесткого диска, нужно пересканиро
вать аппаратную конфигурацию. Для этого мы будем использовать следую
щую команду:
•
.. .. ... . .. . ---- ..... ........................... .................................... .
Ядро
Linux
e cho 1 >
....................... t\.inux
/sys/Ыock/sda/device/rescan
Запустите утилиту parted (используется для работы с разделами диска):
parted
Введите команду р для просмотра имеющихся разделов (рис.
ните номер раздела 1 который мы будем расширять
(2)
15.10).
Запом
и новый размер диска
(42.9GB).
Рис.
15.10.
Текущая таблица разделов
Запустим команду изменения раздела:
resizepart
Укажем номер раздела :
Partiti on number? 2
...
•
. - -. --. -. ---- -. -. --. -. --------- ---·-. -.. ---. ---.. ---. ----. - ------. ---..• ------ -. -- .
n.iпux ..... ............. .
А затем
-
Глава
15 .
УправJ 1с1111с xpa1111 J111111t'\I
конец раздела - нужно указать как раз то самое значение
42.9GB -
именно так, без пробелов .
ootic:. ubuntu1804.,.,,# echo 1 > /sys/Ыock/sda/device/rescan
rootle.'ubuntu1804: .... # parted
NU Parted 3.2
1
sing /dev'/sda
Туре
,Jelcome tc GNU Parted:
'help' to vie~v
а
list of commands.
( parted I р
1odel: vr,11,,are Virtual disk (scsi)
isk /de1.,'sda: 42.9GB
ector si:e (logical.'physical): 5128/5126
artition ТаЫе: msdos
isk Flags:
Jumber
1
2
Start
10.i9kB
1000118
End
10001•18
21. 5G8
Size
999f18
20. 5GB
Туре
File system
primary
primary
ext4
Flags
boot
lvm
{parted) resi:epart
artition number? 2
nd'
[21.SGB]' 42.9GB
(partedi quit
nformat ion; You may need to update / etc /f s tab.
root(41Ubuntul804: -.,#
1
Рис.
Введите команду
15.11.
Из.менение размера раздела
quit для выхода из parted. Parted сделал свою работу.
Оста
лось сообщить ядру об изменениях размера:
pvresize / dev / sda2
Physical volume " / dev/sda2 " changed
1 physical volume(s) resized / О physical volume(s) not resized
Расширим логический том:
lvextend -r - 1 +100 %FREE /dev/mapper /vg r oup l - root
По окончанию работ введем df - h чтобы убедиться, что дисковое простран
ство расширилось.
Посмотрите на рис.
15 .12.
На нем результат выполнения команд
pvresize,
lvextend и df Последний вывод сообщает нам, что размер группы томов
vgroup 1-root теперь составляет 41 Гб. Мы успешно расширили том до ново.о размера .
············································································· ····· -l!lil
Я11ро
Linux
root(Clubuntu1804: .... #
_......... _____________ rlinux
pvresi:e /dev/sda2
Physical volume "/dev/sda2" changed
1 physical volume(s) resized; 0 physical volume(s) not resi:ed
root{aiubuntu1804: ... # lvextend -r -1 +100%FREE /dev/mapper/\,groupl-root
Size of logical volume vgroupl/root changed from 18.11 GiB (4637 e)(_tentsJ to <38.07 GiB (9745 ext
ts).
Logical \·olume vgroupl; root succes-:.full:.; resized.
agcount=12, agsi:e=40064€
sects::=512
attr=2, projid32Ьit=l
eta-Clata=1 de\' /mapper, vgroupl root isi:e:::512
crc=l
Ьlks
finobt:::l spinodes=0 rmapbt=0
reflin~=0
bsizec4096
Ьlocksc4748288, imaxpctc25
suni t=0
swidthc0 Ьlks
naming
=version
ascii-ci:::0 ft;,pe:;;l
bsi:ec4096
log
=internal
bsi zec4096
Ыocks:::2560, \'ersion:;;2
sectsz:;;512
sunit::.0 ьН:s, lazy-count:;;1
realtime =попе
exts::;;4096
Ыocks:;;0, rtextents:;;0
data Ыocks changed from 4748288 to 9978880
root(Фubuntu1804: .... # df -Н
Filesystem
Si:e Used Av·ail Use¾ l·iounted on
udev
1. бG
0 1.бG
0% /dev
~pfs
315r·i 4 . sr.1 ЗllM
2% /run
/ ~e_v/mapper /\•groupl- root
41G 2. ЗG
396
6%
tmpfs
0 1.6G
1. бG
0% /de\r/shm
mpfs
5. Зfi
0% /runilock
0 5. Зf1
tmpfs
1. бG
0 1.6G
0% /sys/fs/cgroup
/dev/sdal
967f\ 147[1 75411 17% /boot
mpfs
31511
0% /run/user/0
0 315fi
rootlalubuntul804: --.#
data
Рис.15.12. Том расширен
...
•
- ------ -. -- --. ---. -------. ---- -------- •. ---. ---------------- ----------- ----- -. ---.
•
Приложение
1.
Файлы к·онфиrурации
Linux·
.......................
ft.iпux
Пl.1. Конфигурационные файлы
Чтобы эффективно настраивать и ядро , и систему Linux, нужно ориентиро
ваться в содержимом конфигурационного каталога. Если загляните в
/etc,
то
кроме подкаталогов в нем вы обнаружите и файлы, которые находятся не
посредственно в
/etc. Описание
этих файлов приведено в таблице Пl .1. Со
держимое каталога может отличаться в зависимости от используемого дис
трибутива и установленного программного обеспечения. Но общая картина
будет примерно одинаковой во всех дистрибутивах.
Таблица Пl.1. Файлы из каталога
Файл
/etc
Описание
Конфигурация цвета для утилиты
DIR- COLORS
GREP- COLORS
ls.
Здесь вы мо-
жете указать, каким цветом будут выводиться каталоги, файлы, ссылки и т.д.
Конфигурация цвета для утилиты
grep
•
11111 ·. -------.----.-----------.----.----.------.--.-----.... -... -........ --.. ---.. --..
1Iри л ожение 1. Файлы
n..inux _________________ _
ко11фш )' ращш
l,inux
Содержит параметры для корректировки аппарат-
adjtime
ных часов
База данных псевдонимов для почтовых агентов
aliases
(МТА)
Содержит пользователем , которым запрещено использовать планировщик
at.deny
at.
Дополнительная ин-
формация доступна в
man at
Конфигурация (таблица расписания) планировщика
anacrontab
anacron
Глобальный файл конфигурации оболочки
bash.
Локальные файлы конфигурации находятся в до-
bash.bashrc
машнем каталоге каждого пользователя
Содержит ключи для DNS-cepвepa Ьind9
Ьind.keys
Содержит список номеров портов в диапазоне от
600
до
1024,
которые не могут быть использованы
Ьindresvport. Ыасk-
Ыndresvport, который обычно вызывается
list
службами. По умолчанию запрещены порты
631,636,664, 774,921,993
и
995,
IRC623,
которые исполь-
зуются различными сетевыми службами
Список пользовател•ей, которым запрещено исполь-
cron.deny
зовать
Таблица расписания демона
crontab
crond
Конфигурация NТР (сервер времени)
crony*
•
cron
Файл конфигурации для оболочки С
csh.cshrc
•
• - - - - • - - - - - - - • - - - • - - - - - • - - •• - - - • - - - • - • - -
Shell
о - - - • - - - - - • - - - •• - - •• - - - - - - - - - - •• - - - - • - - - • •
•
1111
Ядро
Linux
_______________________ t'linux
Глобальный файл конфигурации для С
Shell.
Опре-
деляет поведения во время регистрации пользова-
теля
csh.login
(login)
в системе. На самом деле
-
это сцена-
рий , который запрещено редактировать вручную.
Он должен изменяться только время обновления
системы. Вместо этого лучше редактировать
csh.login.local,
/etc/
если вам нужно внести изменения в
настройки вашего локального окружения
crypttab
defaultdomain
dhclient.conf
dhclientб.conf
dhcpd.conf
dhcpdб.conf
Содержит информацию о зашифрованных томах
Содержит доменное имя для сервисов
dracut.conf
NIS+
Файл конфигурации для DНСР-клиента, версия
IPvб
Файл конфигурации для DНСР-сервера
Файл конфигурации для DНСР-сервера, версия
IPvб
dialog,
опре-
деляет цветовую схему диалог~вых интерфейсов,
построенных с помощью пакета
dnsmasq.conf
и
Файл конфигурации для DНСР-клиента
Конфигурационный файл для пакета
dialogrc
NIS
Конфигурационный файл для
dialog
dnsma.sq (DNS-
маскарадинга)
Содержит параметры
dracut - средства,
initramfs
которое
формирует
•
1111- -------------. ------------. ------. -----------------------. ---. -----------. -. -. ---.
Приложение
rlinux _________________ _
drirc
1.
Файлы конфигурации
Конфигурационный файл для репозитария
DRI
cvs
Файл используется РАМ-модулем
environment
Linux
pam_env.
Содер-
жит переменные окружения, описанные в виде пар
КЛЮЧ=ЗНАЧЕНИЕ, по одной паре в одной строке
Параметры
esd.conf
EsounD (Enlightened Sound Daemon),
который используется для смешивания вместе не-
которых цифровых аудио потоков для проигрывания на одиночном устройстве
Содержит 48-битные Ethemet-aдpeca и соответству-
ethers
ющие им IР-адреса или имена узлов. Может использоваться некоторыми сетевыми службами для
разрешения МАС-адресов в IР-адреса
exports
Содержит список экспортируемых файловых систем
Информация о релизе
fedora-re\ease
F edora
Информационный файл, содержит некоторые ха-
filesystems
рактеристики и атрибуты файловых систем . В нем
нет ничего особенно интересного
Содержит список файловых систем, которые будут
fstab
монтироваться автоматически при загрузке системы
Список пользователей, которые НЕ могут войти в
систему по
ftpusers
ля
root
FTP.
Среди них вы найдете пользовате-
и многие другие системные учетные запи -
си, которые используются для сетевых сервисов и
обычно обладают повышенными привилегиями
•
.--------- -- ---.---.. --------.---.. --.-...... -... -.. ----.--.... -.. --.. -- -.. --- .. ---1111
....................... n..inux
group
Содержит группы пользователей
host.conf
Задает порядок разрешения доменных имен
hostname
Содержит доменное имя узла
Ранее использовался для разрешения IР-адресов в
доменные .имена . Сейчас для этого используется
система
hosts
DNS,
но вы все равно можете определить
в нем некоторые IР-адреса, если ваша сеть не использует
DNS
или же вам нужно переопределить
разрешение для определенного IР-адреса. Обе ситуации в наше время настолько редки, что похожи
на что-то из области технической фантастики
hosts.*
Файл конфигурации локальной сети
Если существует файл
hushlogins,
hushlogins
file ~/.hushlogin или /etc/
осуществляется «тихий» вход (это от-
ключает проверку
e-mail
и вывод последнего вре-
мени входа и сообщения дня
Если существует файл
(Message ofDay)).
/var/log/lastlog, то выводится
время последнего входа в систему
idmapd.conf
Конфигурация демона
idmapd
idn.conf
Файл конфигурации для
idnalias.conf
Псевдонимы кодировок для
idnkit
idnkit
•
1111-... -.. -... -... --.-.-.... --... --.. --.. ----.--... --.-.-.. --... -...... -.... -....... -.
~
n.inux ....... ......... .
inputrc
issue
issue.net
krb5 .conf
ld.so.cache
ld.so.conf
1Jrшюжс1111с 1.
Фаiiлы "°'1ф111 урации
IJnux
Позволяет задавать обработку отображения символов в специальных ситуациях . Используется редко
Приглашение, которое выводится при входе в си-
стему (ссылка на /usr/liЬ/issue)
Приглашение, которое выводится при сетевом вхо-
де в систему (ссылка на /usr/liЬ/issue.net)
Параметры
Хэш-версия файла
Kerberos
ld.so.conf. Создается утилитой
ldconfig
Настройка динамического связывания во время выполнения
Задает параметры преобразования некоторых сим-
lesskey
волов/клавиш, вы не будете редактировать этот
- файл
libao.conf
libaudit.conf
Конфигурация библиотеки
libao (обычно
дается аудио-драйвер по умолчанию)
Конфигурация библиотеки
libaudit
Контрольные определения для пакета
\ogin.defs
здесь за-
shadow.
Например, зде сь можно з адать количество неудачных попыток входа в систему и многие другие параметры
•
logrotate.conf
Задает параметры ротации журналов
machine-id
Содержит идентификатор машины
·······---------- --- ·--····--·---------- -----····-···------··--····-···-···--··--· -1111
Ядро
Linux
mail.rc
manpath.config
mime.types
mke2fs.conf
- -- - - - - - - - - - - - - - - - - - - - - ainux
Файл конфигурации программы
Этот файл используется пакетом
стройки путей тап и
man-db для
cat
на-
Содержит список МIМЕ-типов и соответствующих
им расширений файлов
Файл конфигурации программы
Содержит сообщение дня
motd
mail
mke2fs
(Message ofthe Day). В
зависимости от настроек системы может выводиться при входе в систему
mtools.conf
netconfig
Данный файл является частью пакета
mtools.conf.
Файл конфигурации сети. Теперь используется
только с кодом ТI-RPC в библиотеке
libtirc
netgroup
Содержит описание конфигурации сетевых групп
networks
Статическая информация о сетевых именах
nfsmount.conf
nscd.conf
nsswitch.conf
Файл конфигурации монтирования
Конфигурационный файл для
NFS
nscd (Name Service
Cache)
Параметры
NSS (Network Service Switch)
•
111:1------------------------... -.. ---.. ----.------. ---------------------. --------. ---..
1lrшюжс1111с 1.
n.inux ................. .
Файл конфигурации сервера времени
ntp.conf
os-release
Фай.1ы ю111ф111 уращш (,i1шх
Содержит информацию о релизе: номер версии, кодовое имя и т.д. (ссылка на /usr/liЬ/os-release)
База данных паролей
passwd
Этот файл используется программой
permissions
ntpd
chkstat
и кос-
венно некоторыми RРМ-скриптами для проверки
или установки прав и режимов файлов и каталогов
при установке
. Этот
printcap
файл автоматически генерируется
cupsd,
его
не нужно редактировать. Все изменения , внесенные
в этот файл, будут потеряны
Не изменяйте этот файл во избежание потери изменений во время очередного обновления системы.
profile
Если вам нужно изменить этот файл, отредактируй-
те
/etc/profile.local,
чтобы установить ваши локаль-
ные настройки, например, глобальные псевдонимы,
переменные
protocols
pythonЗstart
pythonstart
raw
•
VISUAL и
EDIТOR и т.д.
Список IР-протоколов
Startup-cцeнapий
Python 3 для
сохранения истории
интерпретатора и автодополнения имен
То же, что и pythonЗstart, но для старых версий
Python
Определяет параметры привязки rаw-устройств к
блочным устройствам
.......-... -.... -....... --"... "... -... -"............. "."-.... "... -... -"."--".. -"-.8111
Я , 11ю l,i1111,
rc.splash
resolv,conf
rpc
....................... n..inux
Сценарий, определяющий внешний вид индикатора
начальной загрузки
Конфигурационный файл для системы разрешения
имен
Список протоколов удаленного вызова процедур
(RPC)
rsyncd.conf
Файл конфигурации для
rsyncd, secrets
Пароли
screenrc
securetty
Параметры программы
rsyncd
screen (менеджер экрана с
VTl00/ANSI)
эмуляцией терминала
Содержит имена устройств терминалов
(tty),
на ко-
торых разрешает вход в систему пользователю
'
services
root
Список служб (сервисов)
Пароли из файла
/etc/shadow.
shadow
rsyncd
/etc/passwd
физически хранятся в
Поэтому фактически в
/etc/passwd хра-
нится список пользователей , а пароли этих пользователей находятся в
/etc/shadow,
доступ к которому
ограничен
shells
slp.conf
smartd.conf
Список установленных в системе интерпретаторов
Файл конфигурации
OpenSLP SPI
Файл конфигурации демона
smartd
118·....................... ·-···--· -- -···· ............... -- --- ---- -- --.. -- --- --.---... ,.
n.inux _________________ _
1Iр11ложс1111с 1. Фaii:iм
ко11ф111 уращ111
l ,inux
Позволяет определить, кому можно использовать
sudoers
команду
sudo
Некоторые параметры питания
suspend.conf
Файл конфигурации
sysctl.
Кроме этого файла
также читает параметры из
sysctl.conf
conf, /run/sysctl.d/* .conf и
sysctl
файлов /etc/sysctl.d/*.
некоторых других
Содержит список терминалов и определяет их тип
ttytype
,
Параметры для пакета
usb - modeswitch
usb_modeswitch
vconsole.conf
Конфигурационн·ый файл для виртуальной консоли
v1rc
Файл конфигурации текстового редактора vi
Параметры программы
wgetrc
xattr.conf
wget
Задает, как обработать расширенные атрибуты при
'
копировании между файлами
Пl .2. Подкаталоги с конфигурационными
файлами
Далее мы «пройдемся» по подкаталогам каталога
находится в каждом из них (табл. Пl
/ etc
.2) .
/etc с
целью выяснить, что
Содержимое вашего каталога
может отличаться в зависимости от дистрибутива и уже установленных
программ . Вполне вероятно, что у вас не будет некоторых каталогов, пред
ставленных в таблице П 1.2, но будут некоторые другие каталоги , назначение
которых можно найти или в справочной системе
•
Linux, или
в Интернете .
.-... -.--- -- -- -... --· -- ---- -·-----... -----.---.-- ----- -........ -----···-.... -----·t:1111
V
Я , tJ)O l,i1шx
Таблица
___ ___ . ________________ t.'t1nux
17.2.
Подкаталоги каталога
/etc
Описание
Каталог
Содержит файл конфигурации
N etworkManager
Manager и
Network
файлы конфигураций сетевых
соединений в некоторых дистрибутивах
PackageKit -
это открытый и свободный на-
бор приложений для обеспечения высоко-
PackageKit
уровневого интерфейса для различных менеджеров пакетов. Этот каталог содержит
файлы конфигурации
Xll
abrt
Package~it
Параметры графического интерфейса
(Х
Конфигурация
Xl 1
Window)
abrtd -
демона автоматиче-
ских отчетов о сбоях
Каталог альтернатив по умолчанию. Файл
является частью подсистемы
altematives
altematives,
update-
которая обслуживает символи-
ческие ссылки, определяющие команды,
файлы и каталоги, используемые по умолчанию
В этих каталогах находятся конфигураци-
онные файлы демона аудита
audit и audisp
- auditd и его
диспетчера событий (audit event dispatcher).
Основной конфигурационный файл - /etc/
audit/auditd.conf. В нем задается поведение
демона и некоторые настройки, например,
расположение журнала по умолчанию
/var/
log/audit/audit.log •
~
. . . . . -. ------- ----. ---.. --- ---... ---. -. -. --. --. -. -.. ---. -----. ---------- --------_,
llp11111 ,1, , · 1111 , · 1 «l•a11 . 11,11,1111ф111~р.щ1111 l . i1111,
n.1nux ................. .
apt
bash comletion.d
Конфигурация менеджера пакетов
apt
Параметры автодополнения командной
строки для оболочки
bash
Демон Ьinfmt.d настраивает дополнительЬinfmt.d
ные двоичные файлы для выполнения во
время загрузки. В этом каталоге находятся
его конфигурационные файлы
cockpit
Конфигурация панели управления
Пакет
cifs-utils
cifs-utils
Cockpit
содержит средство монти-
рования ресурсов общего доступа
CIFS
в
Linux.
SMB/
В этом каталоге находятся
конфигурационные файлы пакета
cifs-utils
Содержит файлы, которые загружаются в
память одновременно с файлами из катало-
crond.d
га
/var/spool/cron.
После этого демон
загружает содержимое файла
cron
/etc/crontab и
начинает его обработку
Содержат сценарии, которые будут вы-
cron.daily, cron.hourly, cron.
mounthly, cron.weekly
полнены демоном
cron,
соответственно,
ежедневно , ежечасно , ежемесячно и еженедельно
Содержит параметры конфигурации систе-
cups
мы печати
CUPS (Common Unix Printing
System)
В пакете
дули
cupshelpers
python-cupshelpers содержатся моPython, которые помогают создавать
приложения и утилиты с использованием
Руthоn-интерфейса к
CUPS.
В этом катало-
ге находятся параметры этого пакета
•
..... .. .. .. .. . ..... ...... .. . ... . ...... ........ ... .. ... . . .. ..... .. .... ........ ... · · -
Ящю
l . i1111x
..................... . . t\.1nux
crypto-policies
dbus-1
Конфигурация крипта-политик
Содержит файлы конфигурации демона
dbus-daemon
Содержит некоторые параметры по умол-
default
чанию , например , параметры загрузчика
GRUB
depmod - программа для создания файла
modules.dep и mар-файла . В этом каталоге
depmod.d
находятся ее файлы конфигурации . Как
администратор сервера, вы можете о них
просто забыть , они вам не пригодятся
dhcp
Конфигурация DНСР-сервера
dnf
Конфигурация менеджера пакетов
dracut
dracut.conf.d
заменяет
mkinitrd
для создания
загрузочной файловой системы в оперативной памяти
(ramdisk).
Здесь находятся
конфигурационные файлы
firewalld
dnf
dracut
Конфигурация брандмауэра
Содержит конфигурационные файлы под-
fonts
системы шрифтов. В частности, файл /
etc/fonts/fonts .conf описывает каталоги со
шрифтами , каталоги с кэшем шрифтов , а
также описывает аналоги шрифтов
gnupg
Содержит конфигурационный файл
GnuPg
•
ID-------------.---.-----------------.-... -.. --................ -............ -... --..
fl.1пux ................. .
l lp11 10,1,t:11111: 1 Фaiim.1 1,1111ф111 ур:щ1111
J,i11U\
Содержит файлы, относящиеся к загрузчи•
grub.d
ку
GRUB . Вам
не нужно редактировать эти
файлы, они предназначены для служебных
целей
init.d
Содержит сценарии системы инициализа•
ции
Параметры подсистемы маршрутизации.
iproute2
Например, могут использоваться для
IP·
балансировки , то есть объединения
нескольких Интернет•каналов в один
Параметры
lSCSl
Параметры
Java
joe
iSCSI
Java
Содержит конфигурационные файлы тек-
стового редактора joe
'
jvm, jvm-common
Параметры виртуальной машины
Содержит файлы с расширением
ld.so.conf.d
Java
conf,
ко-
торые используются для поиска разделяе-
мых библиотек
libnl
logrotate.d
те
•
Конфигурационные файлы библиотеки
libnl
Конфигурация средства ротации журналов
Файлы конфигурации файлового менеджера
Midnight Commander
.. --------------------.. -----·: ---------------------------. ---. ----. ---. ---. ------ID
И , tpll
l ,illll\
....................... n.1nux
Программа
mcelog
mcelog
позволяет расшифро-
вать аппаратные ошибки. Настраивается
посредством конфигурационных файлов в
каталоге
/etc/mcelog
программа для добавления и
modprobe -
удаления модулей из ядра
modprobe.d
Linux.
Соответ-
ственно в одноименном подкаталоге ката-
лога /etc находятся ее конфигурационные
файлы
modules-load.d
openldap
opt
Содержит параметры некоторых модулей
ядра. По умолчанию в этом каталоге пусто
Содержит конфигурационные файлы сервера каталогов
OpenLDAP
Файлы конфигурации для
/opt/
Параметры конфигурации модулей аутен-
pam.d
тификации РАМ (PluggaЫe
Authentication
Modules)
Параметры программы
pkcsl 1
PKCS# 11 (Cryptoki)
Содержит список GРG-ключей
Plymouth plymouth
использу-
которые находятся на зашифрованных
устройствах
pki
pkcs 11,
емой для управления объектами данных,
свободный графический экран
загрузки для
Linux.
Этот каталог содержит
его конфигурационные файлы
•
................................................................ ......... .... ........
'
1Iр11 . 10жсю1с 1. Фaii ."JЫ
n..inux ..... .... : ....... .
~-.:011ф111 уращш
Linux
Содержит конфигурационные файлы парт
кета
pm-utils.
Пакет
pm-utils -
это инфра-
структура управления питанием нового
поколения
postfix
Конфигурационные файлы почтового агента
Файлы конфигурации протокола РРР
ррр
pptp.d
Postfix
Файлы конфигурации демона
pptpd
(про-
токол РРТР)
Относится к системе миграции между версиями дистрибутива
products.d
openSUSE.
Дополни-
тельная информация может быть найдена
по ссылке
http://doc.opensuse.org/products/
draft/SLESISLES-deployment_sd_ draft/cha.
update.s le.html
PulseAudio -
это звуковой сервер для
РОSIХ-систем. Его основное назначение
pulse
смешивать звуковые потоки от разных
приложений, что позволяет нескольким
потокам воспроизводиться одновременно.
Здесь находятся конфигурационные файлы
PulseAudio
rc.d
rsyslog.d
•
Ссылка на каталог
init.d
Конфигурация демона протоколирования
rsyslogd
... .... ....... .... . .. -- .. -- .... -....... ----. -...... -.............................. . . .
Я J t po
l,i,iux
................ ......... n..inux
Различные параметры системы управления
пакетами
rpm
RPM.
Обычно файлы из этого
каталога не требуют изменения. Дополни-
тельную информацию можно получить по
адресу
samba
sasl2
security
selinux
http: //wiki.opennet.ru/RPM
Конфигурационные файлы
'
Samba
Параметры
SASL (Simple Authentication
and Security Layer)
Еще один параметр конфигурации, относящийся к модулям аутентификации РАМ
Содержит файлы конфигурации системы
безопасности
SELinux
При создании новой учетной записи пользователя создается его домашний каталог в
каталоге
skel
/home,
при этом в созданный до-
машний каталог пользователя копируются
файлы из каталога
/skel.
Все помещенные
в этот каталог файлы будут скопированы в
созданный домашний каталог
ssh
ssl
Содержит файлы конфигурации
клиента и SSH-cepвepa
Файлы конфигурации
Кроме файла
sudoers.d
SSH-
OpenSSL
/etc/sudoers, настройки sudo
могут определяться содержимым файлов
из каталога
/etc/sudoers.d
•
....................................... . ... ..........................................
j
n.inux ______ __ __ __ _____ _
l lrшюжс111н: 1. Фай J 1ы
конфш ~ращш
l,i11ux
Содержит конфигурационные файлы всей
системы. В этом каталоге очень много раз-
личных конфигурационных файлов. На-
sysconfig
пример, в каталоге
/etc/sysconfig/network вы
найдете конфигурационные файлы сетевых
интерфейсов. А в файле
clock хранится
вы-
бранный при установке часовой пояс
sysctl.d настраивает параметры ядра при
sysctl.d
загрузке, здесь находятся его конфигурационные параметры
systemd
udev
Конфигурационные файлы демона
systemd
Файлы конфигурации и файлы правил ме-
неджера устройств
udev
Конфигурационные файлы пакета
wpa_supplicant
wpa_
supplicant (обеспечивает поддержку WEP,
WPAиWPA2)
xdg-open -
это независимый пользователь-
ский инструмент для настройки приложе-
ний рабочего стола по умолчанию. В этом
каталоге находятся его конфигурационные
xdg
файлы. Например, в каталоге
autostart находятся
/etc/xdg/
все программы, которые
могут быть запущены автоматически. Однако запускаются лишь те, которым разре-
шен запуск_ в определенной сессии
Содержит дополнительные файлы конфи-
xinetd.d
гурации суперсервера
xinetd
(в современ-
ных дистрибутивах не используется)
xml
•
Конфигурационные файлы библиотеки
libxml
·-------------·-····-------·---·--·-··-···---··-····-··--·························-ID
Приложение
2.
Командный
интерпретатор bash
Ядро l.iш1x
....................... rl.inux
В этом приложении мы рассмотрим командный интерпретатор
bash.
Это
больше, чем просто средство для ввода команд, у него есть свои параметры
и свои команды. Да, да , именно команды. На
(подобно тому, как в
MS DOS
подобны языку программирования
т.д . Знание возможностей
bash
вания операционной системы
bash
можно написать сценарии
создавались ВАТ-файлы). Возможности
-
bash
есть управляющие структуры, циклы и
не менее важно для полноценного использо
Linux,
чем использование функций ядра или
рабочего окружения. Обо всем этом мы поговорим в данной главе.
П2 .1 . Настройка
bash
bash - это самая популярная командная оболочка (командный интерпрета
Linux. Основное предназначение bash - выполнение команд, ·введен
ных пользователем. Пользователь вводит команду и bash ищет программу,
тор)
соответствующую команде , в каталогах , указанных в переменной окруже
ния РАТН . Если такая программа найдена, то
bash
запускает ее и передает
ей введенные пользователем параметры. В противном случае выводится
сообщение о невозможности выпол нения команды.
•
111---.. ---.. ----. --......... ---- ----- ------........................................ .
n.inux ................. .
Интерпретатор
bash -
1/р11 J южс1111с 2. Комащщый
,ш I t.•pщ>t' 1 а I ор
lms/1
не единственная оболочка, доступная в вашей систе
ме . Список доступных оболочек доступен в файле
случаев по умолчанию используется
/etc/shells. В
большинстве
bash.
Файл
/etc/profile содержит глобальные настройки bash, он влияет на всю
- на каждую запущенную оболочку. Обычно /etc/profile не нужда
в изменении, а при необходимости изменить параметры bash редакти
систему
ется
руют один из файлов:
обрабатывается при каждом входе в систему;
• ~/.bash_profile • ~/.bashrc -
обрабатывается при каждом запуске дочерней оболочки;
• ~/.bash_logout- обрабатывается
Файл
~/.bash_profile
при выходе из системы.
часто не существует, а если и существует, то в нем есть
всего одна строка:
source ~/ . bashrc
Данная строка означает, что нужно прочитать файл
.bashrc. Поэтому будем
.bashrc. Но помните,
считать основным конфигурационным файлом файл
что он влияет на оболочку текущего пользователя (такой файл находится
в домашнем каталоге каждого пользователя, не забываем:
"~"
означает до
машний каталог). Если же вдруг понадобится задать параметры, которые
повлияют на всех пользователей, то нужно редактировать файл
Файл
.bash_history
/etc/profile.
(тоже находится в домашнем каталоге) содержит исто
рию команд, введенных пользователем. Здесь вы можете просмотреть свои
же команды , которые вы накануне вводили.
Конфигурация
bash хранится
в файле
.bashrc.
Обычно в этом файле задают
ся псевдонимы команд, определяется внешний вид приглашения командной
строки, задаются значения переменных окружения.
Псевдонимы команд задаются с помощью команды
alias,
вот несколько при
меров:
alias h= ' fc - 1 '
alias ll='ls - laFo '
•
.... ... . ... . .. . -........................... -.............. -.......................
-
Я . 1ро
Li1111x
.......................
n..iпux
alias l= ' ls -1'
alias g= ' egrep -i'
Псевдонимы работают просто: при вводе команды
полнена команда
! на самом деле
будет вы
ls -!.
Теперь рассмотрим пример изменения приглашения командной строки. Гло
бальная переменная
PS 1
отвечает за внешний вид командной строки. По
умолчанию командная строка имеет формат:
пользователь@к омпьют ер : рабочий_каталог
Значение
PS 1 при этом
будет:
PS1= ' \ u@ \ h: \ w$ '
В табл. П2.1 приведены допустимые модификаторы командной строки.
Таблица П2.1. Модификаторы командной строки
Модификатор
\а
АSСП-символ звонка (код
использовать
-
07).
Не рекомендуется его
очень скоро начнет раздражать
\d
Дата в формате "день недели, месяц, число"
\h
Имя компьютера до первой точки
\Н
Полное имя компьютера
\j
..
Описание
Количество задач, запущенных в оболочке в данное
время
\!
Название терминала
\п
Символ новой строки
•
.. .. .... ....... ..... .... ---- ........... . .... -- --- · ··- -··· ...... .. . .. . .. .. .. .. .... .
l lp11 110,l,L'I IIIL'
t.\.1nux ................. .
2
J(нм:111 , 1111.111 1111 н·р11рt• 1:1111)1
lr
Возврат каретки
1s
Название оболочки
lt
Время в 24-часовом формате (ЧЧ: ММ: СС)
IT
Время в 12-часовом формате (ЧЧ: ММ: СС)
1@
Время в 12-часовом формате (АМ/РМ)
lu
Имя пользователя
Версия
lv
IV
Версия
bash
вариант)
(полная версия: номер релиза, номер
патча)
Текущий каталог (полный путь)
lw
IW
bash (сокращенный
lu/\/1
Текущий каталог (только название каталога, без
пути)
1/
Номер команды в истории
1#
Системный номер команды
Если
UID
пользователя равен О, будет выведен символ
1$
#,
иначе
-
символ$
11
Обратный слэш
$ ()
Подстановка внешней команды
Вот пример альтернативного приглашения командной строки:
PSl= ' [\u@\h]
•
$ (date + %m/% d /% y)
\$ '
.. . -.. --... -... --.... --. ---.. -... --. .. -... --... -... --....... --.................... . . .
Ядро l,iщ1x
....................... n.1nux
Вид приглашения будет такой:
[denis@hosting] 08/04/19 $
В квадратных скобках выводится имя пользователя и имя компьютера, за
тем используется конструкция
$() для
подстановки даты в нужном нам фор
мате и символ приглашения, который изменяется в зависимости от иденти
фикатора пользователя.
Установить переменную окружения можно с помощью команды
export,
что
будет показано позже .
П2.2. Зачем нужны сценарии
bas/1
Представим, что нам нужно выполнить резервное копирование всех важных
файлов, для чего создать архивы каталогов
/etc, /home
и
/usr.
Понятно, что
понадобятся три команды вида:
tar - cvjf
имя
~pxивa . tar . bz2
катало г
Затем нам нужно записать все эти три файла на
программы для прожига
DVD
с помощью любой
DVD.
Если выполнять данную операцию раз в месяц (или хотя бы раз в неделю),
то ничего страшного . Но представьте, что вам.нужно делать это каждый день
или даже несколько раз в день? Думаю, такая рутинная работа вам быстро
надоест. А ведь можно написать сценарий, который сам будет создавать ре
зервные копии, и записывать их на
вить чистый
DVD
DVD!
Все, что вам нужно,
-
это вста
перед запуском сценария.
Можно пойти и иным путем: написать сценарий, который будет делать
резервные копии системных каталогов, и записывать их на другой раздел
жесткого диска. Ведь не секрет, что резервные копии делаются не только на
случай сбоя системы, но и для защиты от некорректного изменения данных
пользователем. Помню, удалил важную тему форума и попросил своего хо
стинг-провайдера сделать откат. Я был приятно удивлен, когда мне предо
ставили на выбор три резервные копии
-
осталось лишь выбрать наиболее
.... - ----.. ·-· -. -···· ... -· -- . ·- ----- .. --·· .. ..... -... --· ..................... --··-. ' .
f.l1nux .. .. . ....... . . . .. .
l lp11 J южc1111c 2.
Koм:111 1 1111,iii 11111 t·рщн· 1 :11щ> l1t1.\l1
подходящую . Не думаете же вы , что администраторы провайдера только и
занимались тем , что три раза в день копировали домашние каталоги пользо
вателей? Поэтому, автоматиз ация
-
штука полезная , и любому администра
тору нужно знать, как автоматизировать свою рутинную работу.
П2.3. Сценарий "Привет, мир!"
По традиции напишем первый сценарий , выводящий всем известную фразу:
Hello, world!.
Для редактирования сценариев вы можете использовать люби
мый текстовый редактор , например ,
nano
или ее (листинг П2.1) .
Листинг ПР2.1 . П е рв ый сцена рий
# ! /Ьin/bash
echo
" Привет ,
мир! "
Первая строка нашего сценария
-
это указание , что он · должен быть обра
ботан программой /Ьin/Ьash . Обратите внимание: если между
#и !
окажется
пробел, то данная директива не сработает, поскольку будет воспринята как
обычный комментарий . Комментарии начинаются, как вы уже наверня ка
знаете, с решетки :
#
Комментарий
Втор&я строка
-
это оператор
сценарий под именем
$
chmod
+х
hello
echo ,
выводящий нашу строку. Сохраните
и введите команду:
hello
Для запуска сценария введите команду :
. /hello
•
................................................................................... . .
И , tpct
l , illll\
........ . .............. n.,nux
На экране вы увидите строку:
Привет ,
мир !
Чтобы вводить для запуска сценария просто
hello
(без
./),
сценарий нужно
скопировать в каталог /usr/Ьin (точнее, в любой каталог из переменной окру
жения РАТН):
#
ер
./hello /u?r/bin
П2.4. Переменные в сценариях
В любом серьезном сценарии вы не обойдетесь без использования перемен
ных . Переменные можно объявлять в любом месте сценария, но до места их
первого применения . Рекомендуется объявлять переменные в самом начале
сценария, чтобы потом не искать, где вы объявили ту или иную переменную.
Для объявления переменной используется следующая конструкция:
переменная=з н ачение
Пример объявления переменной:
ADDRESS=firma . ru
echo $ADDRESS
При объявлении переменной знак доллара не ставится, но он обязателен при
использовании переменной. Также при объявлении переменной не должно
быть пробелов до и после знака=.
Значение для переменной указывать вручную не обязательно
-
его можно
прочитать с клавиатуры :
' read ADDRESS
•
ID-·········-·-------- --··--· -----·--·--·······-······-·-··········-········ - ·- · -·--·
l lp11
n.1nux . ................ .
io ,1,L· 11 11L· .'
К11м:111 , щ1.11i 1111н·р11ре1а111р /11/\/1
или со стандартного вывода программы:
ADDRESS='hostname'
Чтение значения переменной с клавиатуры осуществляется с помощью
инструкции
read.
При этом указывать символ доллара не нужно. Вторая
команда устанавливает в качестве значения переменной
команды
В
ADDRESS
вывод
hostname.
Linux часто используются переменные окружения .
Это специальные пере
менные, содержащие служебные данные. Вот примеры некоторых часто ис
пользуемых переменных окружения :
• BASH -
полный путь до исполняемого файла командной оболочки
• BASH_VERSION -
версия
bssh;
bash;
•
НОМЕ-домашний каталог пользователя, который запустил сценарий;
•
НОSТNАМЕ
• RANDOM • OSTYPE • PWD • PS 1 -
имя компьютера;
случайное число в диапазоне от О до
32 767;
тип операционной системы;
текущий каталог;
строка приглашения;
• UID - ID
• USER -
-
пользователя, который запустил сценарий;
имя пользователя .
Для установки собственной переменной окружения используется команда
export:
# присваиваем переменной значение
$ADDRESS=firma.ru
# экспортируем переменную - делаем ее переменной окружения
# после этого переменная ADDRESS будет доступна в других сценариях
export $ADDRESS
•
.. . . . . . --.. .... ·.--.. --....... -..................... ---. ---.. -... -.... --.. -. -. -..... .
И , 11ю
l , i1111,
....................... r.L1nux
П2.5. Передаем параметры сценарию
О~ень часто сценариям нужно передавать различные параметры , например,
режим работы или имя файла/каталога. Для передачи параметров использу
ются следующие специальные переменные:
• $0 -
содержит имя сценария;
• $n -
содержит значение параметра (п
• $# -
позволяет узнать количество параметров, которые были переданы.
-
номер параметра);
Рассмотрим небольшой пример обработки параметров сценария . Я пони
маю, что конструкцию
case-esac вы, возможно,
не знаете, но общий принцип
должен быть понятен (листинг П2.2).
Листинг П2.2. Получение параметров сценария
#
#
Сценарий
имя
должен
сценария
вызываться
так :
параметр
# Анализируем первый параметр
case " $1 " in
start)
# Действия при получении параметра start
echo " Запускаемся ... "
stop)
# Действия при получении параметра stop
echo " Завершаем работу ... "
*)
# Действия в остальных случаях
# Выводим подсказку о том , как нужно использовать
# завершаем работу сценария
echo " Использовать : $0 {startlstop }"
exit 1
сценарий ,
и
esac
Думаю, приведенных комментариев достаточно, поэтому подробно рассма
тривать работу сценария из листинга П2.2 не будем .
•
•
111- ---·---··--··-·-·--···--··---··-·-·--··---··---·---··- - --------------·---·· - ---·--
11 р11
t\.1nux ................. .
•П2.6.
111 ,1,L· 1111 c :'
Ксща~щ11ыi1
1111 н•р111н• 1а I нр
/1а,/1
Обработка массивов
Интерпретатор
позволяет использовать массивы. Массивы объявляют
bash
ся подобно переменным.
Вот пример объявления массива:
ARRAY[O]=l
ARRAY[1]=2
Выводим элемент массива :
echo $ARRAY[0]
П2. 7. Циклы for и
while
Как и в любом языке программирования , в
Мы рассмотрим циклы
циклы
until и select,
for
и
while,
bash можно использовать циклы.
bash дос,тупны также
хотя вообще в
но они приме~яются довольно редко.
Синтаксис циклаfоr выглядит так:
f or
do
переменная
in
список
команды
done
В цикле , при каждой итерации, переменной будет присвоен очередной эле
мент списка, над которым будут выполнены указанные команды. Чтобы
было понятнее, рассмотрим небольшой пример :
for n in 1 2
do
echo $n ;
done
•
З;
·---------------------------------------------··--------·---··---·----·--·· ·--· --- -
Ищюl,i1111,
........... •............ t\.1nux
Обратите внимание: список значений и список команд должны заканчивать
ся точкой с запятой.
Как и следовало ожидать, наш сценарий выведет на экран следующее:
1
2
3
Синтаксис цикла
while
do
while выглядит немного
иначе:
условие
команды
done
Цикл
while
выполняется до тех пор, пока истинно заданное условие. Под
робно об условиях мы поговорим, возможно, чуть позже, а сейчас напишем
аналог предыдущего цикла, т. е. нам нужно вывести
while,
1, 2
и
3,
но с помощью
а не for:
n=l
while [ $n -lt 4 ]
do
echo " $n "
n=$(( $n+l ));
done
П2.8. Условные операторы
В
bash доступны два условных
оператора: ifи
case.
Синтаксис оператора iftледующий:
if
1 then
1
elif условие 2 then
условие
команды
команды_2
•
.....................................................................................
1Iр11 . южсн11с 2.
n.1nux ....... .......... .
elif
условие_N
К1ша11 , щыii 11111ер11ре1 а1ор
has/1
then
команды_N
else
команды
N+l
fi
Оператор
if в bash
работает аналогично оператору
if в
других языках про
граммирования. Если истинно первое условие, то выполняется первый спи
сок команд, иначе
elif,
-
проверяется второе условие и т. д. Количество блоков
понятно, не- ограничено.
Самая ответственная задача
-
это правильно составить условие. Условия
записываются в квадратных скобках. Вот пример записи условий:
# Переменная N
[ N==l0 ]
# Переменная N
[ N!=l0 ]
10
не
равна
10
Операции сравнения указываются не с помощью привычных знаков
> или <,
а с помощью следующих выражений:
•
-lt -
меньше;
• •
-gt -
больше;
-/е
меньше или равно;
•
-
• -ge -
больше или равно;
•
равно (используется вместо=).
-eq -
Применять данные выражения нужно следующим образом:
[
переменная
выражение
значениеlпеременная]
Например:
•
··························· ·······················································-
Я , tро l.i1111\
#
[
#
[
............. . ......... n.inux
N меньше 10
$N - lt 10 ]
N ме н ьше А
$N - lt $А ]
В квадратных скобках вы также можете задать выражения для проверки су
ществования файла и каталога :
•
-е файл
-
условие истинно , если файл существует;
• -d каталог •
-х файл
-
С оператором
условие истинно , если каталог существует ;
условие истинно , если файл является исполняемым .
case мы
уже немного знакомы , но сейчас рассмотрим его син
таксис чуть подробнее:
cas e
переменная
in
1)
команды_l
,,
з начение_N)
команды_N
,,
значение
* ) команды_по
esac
умолчанию ;;
Значение указанной переменной по очереди сравнивается с приведенными
значениями (значение_! ,
.. .,
значение_N) . Если есть совпадение, то будут
выполнены команды, соответствующие значению. Если совпадений нет, то
будут выполнены команды по умолчанию . Пример использования
case
был
приведен в листинге П2 . 2.
П2.9. Функции в
В
bash
bash
можно использовать функции . Синтаксис объявления функции сле
дующий:
имя
•
()
{
список ;
•
················.··································································
n.iпux ................. .
l lp11 . 1o;кc1111 c ~
К11м:111 , щыii 11111 t·pщ>t· 1 а 111р l1tl\l1
Вот пример объявления и использования функции:
list_txt ()
{
echo " Text files in current directory :"
1s * . txt
}
П2.10. Практические примеры сценариев
Проверка прав пользователя
Для сценариев , требующих полномочий
кой пользователь запустил сценарий.
root, сначала нужно проверить , ка
UID пользователя root всегда равен О.
Проверка, является ли пользователь , запустивший сценарий , пользователем
root, может выглядеть так ,
как показано в листинге П2.3.
Листинг П2.3. Проверка полномочий пользователя
# ! / Ьin / bash
ROOT UIQ=0
if [ " $UID " - eq " $ROOT UID "
then
echo " Root "
else
echo " Обыч н ый пол ьз ователь "
fi
exit
О
Проверка свободного дискового пространства с уведомлением
по
e-mail
Следующий сценарий проверяет свободное дисковое пространство серве
•
ра и отправляет уведомление по
e-mail
администратору, если осталось
······--------------------------------------·--------···-·-------------·-- ---- ---· •
Я . 1ро
l,inux
меньше
2000
_______________________ n..inux
Мбайт дискового пространства. Сценарий целесообразно за
пускать через планировщик заданий (например , через
cron)
с заданной пе
риодичностью (например , каждый час) . Код сценария приведен в листинге
П2.4 .
Листинг П2.4. Проверка свободного дискового пространства
#!/Ьin/bash
# В переменную freespace будет записано свободное пространство
# на контролируемом диске - /dev/sdal (в Мбайт)
freespace='df - m I grep " /dev/sdal " 1 awk ' {print $4) ' •
# Если места на диске< 2000 МЬ , то отправляем п и сьмо администратору
if [ $freespace - lt 2000 ] ;
then
echo " На сервера меньше< 2000 МВ " 1 mail -s " Свободное место заканчивается !"
admin@firma . ru
fi
•
1111- ------------------------. --. -. -----. --- ------. ------. ----------------------- -----.
Приложение
3.
Сетевая файловая
система NFS
Я , tро l,i1111x
....................... n..1nux
ПЗ.1. Вкратце о
NFS
и установке необходимых
пакетов
Сетевая файловая система
(NFS, Network File System) -
старый_, но прове
ренный способ предоставления доступа к общим файлам.
NFS
позволяет
монтировать файловые системы, которые физически находятся на других
компьютерах в вашей локальной сети.
Принцип работы
NFS
прост: на сервере устанавливается демон
nfsd,
ко
торый экспортирует файловые системы. NFS-клиент монтирует экспорти
руемые файловые системы. После монтирования с удаленной файловой
системой можно работать, как с локальной
-
для пользователя ничего не
изменится, разве что скорость доступа к файлам будет чуть ниже, поскольку
данные ведь передаются по сети.
В вашей сети может быть несколько NFS-cepвepoв _и несколько
клиентов. По сути, каждый NFS-клиент может выступать и в роли
cepвepa, но обычно
NFS
NFSNFS-
используется иначе. Выделяется один NFS-cepвep,
который будет экспортировать общую файловую систему, которая может ис
пользоваться для хранения общих файлов
-
довольно частый сценарий .
•
. . ..... ··-. -- ---- ---- - ---- -- . --- --- -. ------- ---- ----··· ............................. .
l lp11 J IOЖClll1C
f.t1nux ................. .
1. ('('(('IШSI ф:tii.юв:ш CIICl('M:I
~,.- s
Чтобы установить NFS-cepвep и/или NFS-клиент произведите поиск пакета
по слову 'nfs'. Далее прочитайте описания пакетов и установите необходи
мые вам пакеты. Названия пакетов могут отличаться в зависимости от дис
трибутива. Например, в
openSUSE на
сервере нужно установить следующие
пакеты:
• nfs-kernel-se_rver • nfswatch -
содержит NFS-cepвep;
утилита мониторинга NFS-трафика (можно не устанавливать);
• quota-nfs -
система дисковых квот для
NFS.
На клиенте нужно установить только пакет
ПЗ.2. Файл
В файле
nfs-client.
/etc/exports
/etc/exports
прописываются экспортируемые файловые системы.
Эти экспортируемые файловые системы могут монтировать клиенты, Об
щий формат записи в файле
файловая_система
exports
[компьютер ]
следующий:
(опции)
Вот типичный пример:
/ home / puЫic
(rw)
/ home / templates . (ro)
В данном случае каталог /home/puЫic сервера будет доступен NFS-клиентам
для чтения и записи
(rw),
а каталог
/home/templates -
только для чтения
(ro).
При желании можно еще и указать узлы, которым будет доступен экспорти
руемый каталог, например:
/ home/sharel 192 .1 68.1 . 100 (rw)
/ home / share2 host . example . com (rw)
/ home / shareЗ *.example . com (rw)
•
················································································· · -
Я д ро l.iпux
_______________________ r.linux
Здесь первый каталог
(/home/share) будет доступен только узлу с IР-адресом
192.168.1 .100, второй каталог - только узлу с доменным именем host.
example.com, а третий - всем узлам из домена example.com. Также можно
указать целую IР-сеть и ее маску, например:
/home/s hare4 192 .1 68:1 . 0/28 (rw)
В данном случае получить доступ к
/home/share4 смогут лишь первые 16
- от 192.168.1.0 до 192.168.1.15. Компьютеры с IР-адресами
192.168.1.16 и выше не смогут использовать эту файловую систему.
IР-адресов
Обычно можно обойтись только опциями
ro, rw
и
noaccess.
Последняя ис
пользуется для запрещения доступа к файловой системе. Например, вы хо
тите запретить узлу
192.168.1.5
доступ к файловой системе:
/ h ome/share4 192.168.1 .5 (noaccess)
Остальные опции
NFS
приведены в таблице ПЗ .1.
Таблица ПЗ.1. Опции экспорта файловой системы в
Опция
all_squash
insecure
link absolute
link- relative
root_squash
по _root_squash
NFS
Описание
Преобразует идентификаторы групп и пользователей в
анонимные
Разрешает запросы с любых портов, см.
secure
Не изменяет символические ссылки (по умолчанию)
Абсолютные ссылки будут преобразованы в относительные
Преобразует все запросы от
root в
запросы от анонимно-
го пользователя
Разрешает доступ к файловой системе от имени
рекомендуется
root.
Не
•
1111-------------------------... --.. --.. --... --------------------. ----.-------. -------,
n.1nux ........ . .... . ... .
Принимает з апросы на монтировани е файловой систе
secure
мы только с портов с номерами <
может создавать только
1024.
Такие порты
root, по этому такое
соединение
считается безопасным. Используется по умолчанию
После редактирования файла
пустить службу
не забудьте перезапустить или за
/etc/exports
nfs:
# service nfs start
или
# service nfs restart
ПЗ.3. Использование NFS-клиента
Для монтирования сетевой файловой системы используется та же команда
mount.
Синтаксис вызова команды такой:
mount - t n f s
сервер : ФС
точка_мон т и р о ван ия
Вот пример:
mount -t nfs 192 . 168 . 1.157 : /home/share /mnt/share
Сервер
192.168.1.157 экспортирует файловую
монтируем эту файловую систему к каталогу
вать на момент вызова команды
метр
-t, который задает тип
mount).
систему
/home/share. Мы под
/mnt/share (должен существо
Также обратите внимание на пара
файловой системы .
Конечно , вы не будете вводить эту команду после каждой перезагрузки .
По этому если удаленную файловую систему нужно использовать постоян
но , лучше прописать ее в файле
/etc/fstab:
192 . 168 . 1 . 157 : / home / share /mnt/ share nfs bg , hard , rw
•
О
О
.
...... .. .... ..... ···- ... ·-·. ·-·· .............. --- .............................. - - - -
}1 \l)CI
l .i1111,
....................... n.1nux
Нужно отметить, что
NFS -
довольно старое решение, как говорят, класси
ческое. Существуют различные варианты сетевых и распределенных фай
ловых систем, например , ClusterNFS, OpenAFS , Parallel Virtual File System
(PVFS)
и др.
Основной недостаток
NFS -
отсутствие какого-либо шифрования передава
емых по сети данных. Если вы. используете
NFS
в защищенной локальной
сети, то это, как правило , не проблема (при отсутствии угроз внутри сети).
Но когда есть нео9ходимость передавать данные по Интернету, то нужно ис
пользовать шифрование. Один из способов добавления шифрования к
-
использование виртуальных частных сетей
(VPN),
NFS
в которых все данные
между удаленными системами передаются в зашифрованном виде . В этом
случае
NFS
имеет право на существование в Интернете.
Список использованны х источников
информации:
•
Колисниченко Д.Н.
«LINUX. Полное
руководство по работе и администриро-
ванию»
•
https://ru.wikipedia.org/wiki/Softlanding_Linux_ System
•
www.kemel.org
•
https://docs.huihoo.com/doxygen/linux/keme\/3.7/structtask_ struct.html
•
http: //tldp.org/НOWTO/LVM-HOWTO/
•
http://www.iakovlev.org/index.html
•
https: //miпors.edge.kemel.org/puЬ/linux/libs/pam/
•
https ://www.freepik.com/free-vector/minimal-white-background-wi th-3 d-circulardesign_ 8776623 .htm?query=c#from_ view=detail_ also\ike
•
https://www.insight-it.ru/category/linux/
•
http://wiki.opennet.ru/RPM
•
https ://it-Ыack.ru/linux/3 /
•
. ....... .... .. .... ..... .. . ... . .... .... ... ---- ----- ... -- . ----·-·····-· ...... -- ··- -···
Матвеев М. Д.
Ядро
Linux
СБОРКА
~
НАСТРОИКА
УПРАВЛЕНИЕ
Ipynna подготовки
издания:
Зав . редакцией компьютерной литературы : М. В. Финков
Редактор : Е. В. Финков
Корректор: А. В. Громова
ООО "Издательство Наука и Техника"
ОГРН
1217800116247, ИНН 7811763020, КПП 781101001
192029, r. Санкт-Петербург, пр . Обуховской обороны, д. 107, л~т. Б,
Подпис а но в печать 13.02.2023. Формат 70х100 1/16.
Бумага газетная . Печать офсетная . Объем 22 п .л .
Тираж 1500. З аказ 6032.
пом . 1-Н
Отпечатано с готового оригинал-макета
ООО «Принт-М »,
142300, М . О ., r. Чехов , ул .
Полиграфистов, д.1