Опубликовано

Представляем книгу “Расширения ядра Linux: драйверы и модули”

Расширения ядра Linux: драйверы и модули

Представляем книгу Олега Цилюрика “Расширения ядра Linux: драйверы и модули”. В книге подробно рассмотрено программирование драйверов ядра Linux, исследованы возможности расширяемости ядра при помощи модулей. Основная версия ядра – 5.15. Код примеров отработан и проверен на десятках различных инсталляций Linux, установленных из различных дистрибутивов и разных семейств дистрибутивов: Fedora, CentOS, Debian, Ubuntu, Mint. Уделено внимание архитектурам x_64, x_86, ARM, а также одноплатному компьютеру Raspberry Pi и драйверам устройств, подключаемых по USB. Затронут стандарт POSIX, разобраны API ядра, работа с Raspberry Pi, системные вызовы и подключение разнообразных периферийных устройств.

 

Ядро Linux — шедевр низкоуровневого кода на языке C. Разработка ядра не прекращается уже почти 30 лет, и занимается этим глобальное сообщество энтузиастов и профессионалов. Системные вызовы ядра Linux, тонкости управления памятью или параллельная обработка запросов – все эти темы важны сами по себе и в совокупности, но есть и ещё одна важная тема, до сих пор освещённая на русском языке фрагментарно и неравномерно: программирование драйверов и модулей ядра.

Именно этой теме посвящён фундаментальный труд, впервые публикуемый в качестве отдельной книги. Он зародился в начале 2000-х как материал для корпоративного курса и постоянно обновлялся вплоть до ноября 2022 года – и в данной версии выходит на бумаге. Новейшая версия ядра, учтённая в книге, – 5.15.

В книге подробно разобраны API ядра, системные вызовы, обработка сигналов, взаимодействия с периферийными устройствами и, в частности, с протоколом USB. Уделено внимание процессорным архитектурам x_64, x_86, ARM, а также одноплатному компьютеру Raspberry Pi и драйверам внешних устройств. Рассмотрена конфигурация и загрузка модулей и всевозможные варианты кастомизации ядра, рассмотрен стандарт POSIX.

Книга ориентирована на опытных программистов и системных администраторов, работающих с Linux. Призвана послужить достойным аналогом и дополнением классической работы «Драйверы устройств Linux. 3-е издание» Джонатана Корбетта и соавторов (Corbet J., Rubini A., Kroah-Hartman G. Linux Device Drivers, 3rd Edition).

Хорошая книга не дарит тебе откровение, хорошая книга укрепляет тебя в твоих самостоятельных догадках.
Андрей Рубанов, «Хлорофилия»

Книгу “Расширения ядра Linux: драйверы и модули” можно купить со скидкой в интернет-магазине издательства “БХВ“.

От автора……………………………………………………………………………………………….. 11

Предыстория………………………………………………………………………………………………………………………………. 11

Кому адресована книга?…………………………………………………………………………………………………………… 13

Структура книги………………………………………………………………………………………………………………………… 15

Соглашения, принятые в тексте………………………………………………………………………………………………… 18

Код примеров и замеченные опечатки…………………………………………………………………………………….. 19

Замечания о версиях ядра…………………………………………………………………………………………………………. 22

Обновляемость ядра………………………………………………………………………………………………………………….. 23

Использованные источники информации………………………………………………………………………………… 25

Обновления текущей редакции текста…………………………………………………………………………………….. 25

Глава 1. Модули с высоты птичьего полёта…………………………………………… 27

Linux и GNU………………………………………………………………………………………………………………………………… 27

FAQ                                                                                                                                                                   28

Модуль в иерархии программных систем……………………………………………………………………………….. 29

Наш первый модуль ядра………………………………………………………………………………………………………….. 31

Сборка модуля……………………………………………………………………………………………………………………. 31

Загрузка и исполнение………………………………………………………………………………………………………. 33

Точки входа и завершения………………………………………………………………………………………………… 34

Внутренний формат модуля……………………………………………………………………………………………………… 36

Диагностика модуля………………………………………………………………………………………………………………….. 38

Уровни диагностики в /proc………………………………………………………………………………………………. 42

Представление адресов в Linux………………………………………………………………………………………… 43

Форматы вывода………………………………………………………………………………………………………………… 45

Основные ошибки модуля…………………………………………………………………………………………………………. 48

Обсуждение………………………………………………………………………………………………………………………………… 50

Глава 2. Архитектура и вокруг………………………………………………………………. 53

Ядро: монолитное и микроядро……………………………………………………………………………………………….. 53

Траектория системного вызова………………………………………………………………………………………………… 55

Библиотечный и системный вызов из процесса………………………………………………………………. 56

Под капотом системного вызова………………………………………………………………………………………. 63

Отслеживание системного вызова в процессе…………………………………………………………………. 66

Различия программ пространств ядра и пользователя………………………………………………………….. 67

Интерфейсы модуля…………………………………………………………………………………………………………………… 70

Взаимодействие модуля с уровнем пользователя…………………………………………………………… 70

Взаимодействие модуля с ядром………………………………………………………………………………………. 75

Коды ошибок………………………………………………………………………………………………………………………. 77

Загрузка модулей………………………………………………………………………………………………………………………. 77

Автоматическая загрузка модулей…………………………………………………………………………………… 78

Запрет загрузки (черный список модулей)………………………………………………………………………. 79

Параметры загрузки модуля…………………………………………………………………………………………………….. 80

Конфигурационные параметры ядра………………………………………………………………………………………. 85

Параметры в ядре………………………………………………………………………………………………………………. 85

Параметры в модуле………………………………………………………………………………………………………….. 88

Подсчет ссылок использования………………………………………………………………………………………………… 91

Обсуждение………………………………………………………………………………………………………………………………… 93

Глава 3. Инструментальное окружение………………………………………………….. 95

Основные команды…………………………………………………………………………………………………………………….. 95

Системные файлы………………………………………………………………………………………………………………………. 96

Графика, терминал и текстовая консоль…………………………………………………………………………………. 99

Управление текстовыми консолями……………………………………………………………………………………….. 100

Коротко о компиляторе GCC………………………………………………………………………………………………….. 102

Ассемблер в Linux……………………………………………………………………………………………………………………. 105

Нотация AT&T…………………………………………………………………………………………………………………. 107

Инлайновый ассемблер GCC………………………………………………………………………………………….. 108

Создание среды сборки модулей ядра…………………………………………………………………………………… 110

Работа над кодом…………………………………………………………………………………………………………………….. 114

В деталях о сборке…………………………………………………………………………………………………………………… 117

Переменные периода компиляции………………………………………………………………………………….. 117

Дополнительные параметры периода компиляции………………………………………………………. 118

Версионность ядра в коде модуля………………………………………………………………………………….. 118

Как собрать одновременно несколько модулей?………………………………………………………….. 120

Как собрать модуль и используемые программы к нему?……………………………………………. 120

Пользовательские библиотеки………………………………………………………………………………………… 121

Как собрать модуль из нескольких объектных файлов?………………………………………………. 123

Рекурсивная сборка…………………………………………………………………………………………………………. 125

Подписывание модулей…………………………………………………………………………………………………………… 127

Инсталляция модуля……………………………………………………………………………………………………………….. 130

Нужна ли новая сборка ядра?………………………………………………………………………………………………… 131

Динамическая сборка модулей (DKMS)………………………………………………………………………………… 133

Обсуждение………………………………………………………………………………………………………………………………. 138

Глава 4. Внешние интерфейсы модуля…………………………………………………. 139

Драйверы: интерфейс устройства………………………………………………………………………………………….. 139

Символьные устройства………………………………………………………………………………………………….. 143

Варианты реализации……………………………………………………………………………………………. 145

Ручное создание имени………………………………………………………………………………….. 146

Использование udev……………………………………………………………………………………….. 151

Динамические имена………………………………………………………………………………………. 155

Разнородные (смешанные) устройства………………………………………………………… 159

Управляющие операции устройства…………………………………………………………………….. 162

Множественное открытие устройства………………………………………………………………….. 169

Счетчик ссылок использования модуля……………………………………………………………….. 177

Режимы выполнения операций ввода/вывода……………………………………………………… 180

Неблокирующий ввод/вывод и мультиплексирование……………………………………….. 181

Блочные устройства………………………………………………………………………………………………………… 190

Особенности драйвера блочного устройства………………………………………………………. 193

Обзор примеров реализации………………………………………………………………………………….. 194

Регистрация устройства…………………………………………………………………………………………. 195

Подготовка к регистрации……………………………………………………………………………… 195

Диски с разметкой MBR и GPT……………………………………………………………………… 197

Заполнение структуры…………………………………………………………………………………… 199

Завершение регистрации……………………………………………………………………………….. 201

Таблица операций устройства………………………………………………………………………………. 201

Обмен данными……………………………………………………………………………………………………….. 205

Классика: очередь и обслуживание ядром………………………………………………….. 210

Очередь и обработка запроса в драйвере……………………………………………………. 212

Отказ от очереди…………………………………………………………………………………………….. 214

Пример перманентных данных……………………………………………………………………… 215

Некоторые важные API………………………………………………………………………………….. 215

Результаты тестирования………………………………………………………………………………………. 216

Файловая система FUSE…………………………………………………………………………………………. 221

Интерфейс /proc……………………………………………………………………………………………………………………….. 228

Терминальные значения в /proc и /sys……………………………………………………………………………. 230

Использование /proc………………………………………………………………………………………………………… 231

Специфический механизм procfs……………………………………………………………………………. 232

Варианты реализации чтения……………………………………………………………………….. 240

Запись данных………………………………………………………………………………………………… 244

Общий механизм файловых операций………………………………………………………………….. 245

Интерфейс /sys………………………………………………………………………………………………………………………….. 251

Создание и использование имен в /sys……………………………………………………………………………. 253

Ошибки обменных операций…………………………………………………………………………………………… 261

Сетевые интерфейсы и протоколы…………………………………………………………………………………………. 263

Сетевые инструменты……………………………………………………………………………………………………… 265

Сетевые интерфейсы………………………………………………………………………………………………. 265

Инструменты наблюдения……………………………………………………………………………………… 269

Инструменты интегрального тестирования…………………………………………………………. 276

Структуры данных сетевого стека…………………………………………………………………………………. 278

Драйверы: сетевой интерфейс………………………………………………………………………………………… 279

Создание сетевых интерфейсов…………………………………………………………………………….. 279

Новая схема, и детальнее о ее создании………………………………………………………………. 281

Операции сетевого интерфейса……………………………………………………………………………… 286

Переименование сетевого интерфейса………………………………………………………………….. 291

Путь пакета сквозь стек протоколов………………………………………………………………………………. 293

Прием: традиционный подход………………………………………………………………………………. 293

Прием: высокоскоростной интерфейс…………………………………………………………………… 294

Передача пакетов……………………………………………………………………………………………………. 297

Статистика интерфейса…………………………………………………………………………………………………… 298

Виртуальный сетевой интерфейс……………………………………………………………………………………. 301

Протокол сетевого уровня………………………………………………………………………………………………. 307

Еще раз о виртуальном интерфейсе……………………………………………………………………………….. 314

Протокол транспортного уровня……………………………………………………………………………………. 321

Использование драйверов Windows……………………………………………………………………………….. 323

Обсуждение………………………………………………………………………………………………………………………. 324

Глава 5. Внутренние API ядра………………………………………………………………. 326

Механизмы управления памятью…………………………………………………………………………………………… 326

Карта памяти……………………………………………………………………………………………………………………. 326

Динамическое выделение памяти…………………………………………………………………………………… 330

Распределители памяти…………………………………………………………………………………………………… 334

Слябовый распределитель………………………………………………………………………………………………. 336

Страничное выделение……………………………………………………………………………………………………. 344

Выделение больших буферов…………………………………………………………………………………………. 344

Динамические структуры и управление памятью………………………………………………………… 345

Циклический двусвязный список…………………………………………………………………………… 345

Модуль, использующий динамические структуры……………………………………………… 349

Сложноструктурированные данные…………………………………………………………………….. 351

Еще об инициализации объектов ядра………………………………………………………………….. 351

Служба времени………………………………………………………………………………………………………………………. 352

Информация о времени в ядре…………………………………………………………………………………………. 352

Источник прерываний системного таймера…………………………………………………………. 355

Дополнительные источники информации о времени…………………………………………… 356

Три класса задач во временной области……………………………………………………………………….. 357

Измерения временных интервалов…………………………………………………………………………………. 358

Временные задержки……………………………………………………………………………………………………….. 365

Таймеры ядра…………………………………………………………………………………………………………………… 371

Таймеры высокого разрешения………………………………………………………………………………………. 372

Абсолютное время……………………………………………………………………………………………………………. 375

Часы реального времени (RTC)………………………………………………………………………………………. 376

Время и диспетчеризация в ядре…………………………………………………………………………………….. 381

Параллелизм и синхронизация………………………………………………………………………………………………. 382

Потоки ядра………………………………………………………………………………………………………………………. 385

Создание потока ядра…………………………………………………………………………………………….. 385

Свойства потока……………………………………………………………………………………………………… 387

Новый интерфейс потоков……………………………………………………………………………………… 389

Синхронизация завершения…………………………………………………………………………………… 394

Синхронизация в коде……………………………………………………………………………………………………… 401

Критические секции кода и защищаемые области данных………………………………… 401

Механизмы синхронизации…………………………………………………………………………………… 402

Условные переменные и ожидание завершения…………………………………………………… 402

Атомарные переменные и операции……………………………………………………………………… 405

Битовые атомарные операции………………………………………………………………………. 405

Арифметические атомарные операции………………………………………………………… 406

Локальные переменные процессора……………………………………………………………………… 407

Предыдущая модель………………………………………………………………………………………. 407

Новая модель………………………………………………………………………………………………….. 408

Блокировки………………………………………………………………………………………………………………. 409

Семафоры и мьютексы…………………………………………………………………………………… 410

Спин-блокировки……………………………………………………………………………………………. 415

Блокировки чтения/записи…………………………………………………………………………….. 417

Сериальные (последовательные) блокировки……………………………………………… 420

Мьютексы реального времени………………………………………………………………………. 422

Инверсия и наследование приоритетов………………………………………………………… 422

Множественное блокирование………………………………………………………………………………. 423

Уровень блокирования…………………………………………………………………………………………… 424

Предписание порядка выполнения……………………………………………………………………….. 430

Аннотация ветвлений……………………………………………………………………………………… 430

Барьеры…………………………………………………………………………………………………………… 431

Обработка прерываний…………………………………………………………………………………………………………… 432

Общая модель обработки прерывания…………………………………………………………………………… 433

Наблюдение прерываний в /proc……………………………………………………………………………………. 436

Регистрация обработчика прерывания………………………………………………………………………….. 439

Обработчик прерываний: верхняя половина………………………………………………………………… 442

Управление линиями прерывания…………………………………………………………………………. 444

Пример обработчика прерываний………………………………………………………………………… 444

Отложенная обработка: нижняя половина……………………………………………………………………. 446

Отложенные прерывания: softirq…………………………………………………………………………… 446

Тасклеты………………………………………………………………………………………………………………….. 450

Демон ksoftirqd………………………………………………………………………………………………………… 452

Очереди отложенных действий: workqueue…………………………………………………………. 452

Сравнение и примеры…………………………………………………………………………………………….. 455

Обсуждение………………………………………………………………………………………………………………………. 460

Глава 6. Периферийные устройства в модулях ядра…………………………….. 466

Поддержка шинных устройств в модуле……………………………………………………………………………….. 466

Анализ оборудования……………………………………………………………………………………………………………… 468

Подсистема udev………………………………………………………………………………………………………………. 473

Идентификация модуля……………………………………………………………………………………………………. 477

Ошибки идентификации модуля……………………………………………………………………………………… 479

Устройства на шине PCI…………………………………………………………………………………………………………. 480

Подключение к линии прерывания…………………………………………………………………………………. 491

Отображение памяти……………………………………………………………………………………………………….. 492

DMA…………………………………………………………………………………………………………………………………… 493

Устройства USB……………………………………………………………………………………………………………………….. 499

Некоторые технические детали……………………………………………………………………………………… 499

Поддержка в Linux…………………………………………………………………………………………………………… 501

Пара слов о USB-модемах………………………………………………………………………………………………. 503

Устройства USB в коде модуля………………………………………………………………………………………. 506

Многофункциональные USB-устройства………………………………………………………………………. 514

Устройства в пространстве пользователя…………………………………………………………………………….. 520

Аппаратные порты…………………………………………………………………………………………………………… 521

Особенности доступа………………………………………………………………………………………………………. 526

Проект libusb…………………………………………………………………………………………………………………….. 527

GPIO…………………………………………………………………………………………………………………………………… 536

Глава 7. Расширенные возможности программирования……………………… 543

Операции с файлами данных………………………………………………………………………………………………….. 544

Запуск новых процессов из ядра……………………………………………………………………………………………. 552

Сигналы UNIX………………………………………………………………………………………………………………………….. 554

Вокруг экспорта символов ядра…………………………………………………………………………………………….. 561

Неэкспортируемые символы ядра………………………………………………………………………………….. 564

Использование неэкспортируемых символов……………………………………………………………….. 572

Подмена системных вызовов…………………………………………………………………………………………… 576

Добавление новых системных вызовов………………………………………………………………………….. 584

Скрытый обработчик системного вызова……………………………………………………………………… 591

Динамическая загрузка модулей……………………………………………………………………………………………. 600

…из процесса пользователя…………………………………………………………………………………………….. 601

…из модуля ядра……………………………………………………………………………………………………………….. 609

Подключаемые плагины………………………………………………………………………………………………….. 613

Обсуждение………………………………………………………………………………………………………………………………. 623

Глава 8. Отладка в ядре……………………………………………………………………….. 628

Отладочная печать………………………………………………………………………………………………………………….. 629

Интерактивные отладчики……………………………………………………………………………………………………… 629

Отладка в виртуальной машине…………………………………………………………………………………………….. 632

Отдельные отладочные приемы и трюки………………………………………………………………………………. 635

Модуль, исполняемый как разовая задача……………………………………………………………………. 635

Тестирующий модуль………………………………………………………………………………………………………. 637

Интерфейсы пространства пользователя к модулю……………………………………………………… 640

Комплементарный отладочный модуль………………………………………………………………………… 642

Пишите в файлы протоколов…………………………………………………………………………………………… 645

Некоторые мелкие советы в завершение……………………………………………………………………….. 645

Чаще перезагружайте систему!……………………………………………………………………………… 645

Используйте естественные POSIX-тестеры………………………………………………………….. 646

Тестируйте чтение сериями……………………………………………………………………………………. 646

Заключение………………………………………………………………………………………….. 647

Приложение 1. Краткая справка по утилите make………………………………… 649

Приложение 2. Тесты распределителя памяти………………………………………. 652

Приложение 3. Четыре способа записи в защищенную страницу…………. 666

Описание проблемы………………………………………………………………………………………………………………… 666

Отключение страничной защиты: ассемблер……………………………………………………………………….. 667

Отключение страничной защиты: API ядра………………………………………………………………………….. 668

Снятие защиты со страницы памяти……………………………………………………………………………………… 670

Наложение отображения участка памяти…………………………………………………………………………….. 671

Тест выполнения………………………………………………………………………………………………………………………. 672

Обсуждение………………………………………………………………………………………………………………………………. 674

Позднее дополнение………………………………………………………………………………………………………………… 675

Источники информации……………………………………………………………………….. 677

Предметный указатель…………………………………………………………………………. 681

Об авторе……………………………………………………………………………………………… 685

Цилюрик Олег Иванович

Цилюрик Олег Иванович — программист-разработчик с более чем 40-летним опытом, преподаватель, автор нескольких книг по Linux и Unix, высоко оцененных профессионалами и широкой читательской аудиторией.

Добавить комментарий