Что такое kernel driver

Обновлено: 08.07.2024

Современные приложения и игры отличаются большим размером и детальной прорисовкой графики. Соответственно, работа с ними требует от ПК особой мощности. Часто пользователи сталкиваются, что во время работы и игрового процесса возникает Windows ошибка kernel – критический сбой в процессе работы. Некоторые компьютеры показывают BlueScreen – синий экран смерти, в некоторых случаях устройство перестает откликаться на любое действие.

Ошибка kernel. Общие сведения о неполадке

Ошибка Kernel-Power имеет кодировку 43. Возникновение такой проблемы означает, что у компьютера выявлено нарушение мощности ядра системы. Она относится к 63й категории, что означает невозможность Windows обрабатывать одновременно большое количество запросов и выполнять сложные операции. Именно это объясняет процесс торможения и подвисания современных компьютерных аркад.
На самом деле, выяснить точные проблемы возникновения Kernel-Power достаточно сложно, даже официальный сайт Майкрософт не предоставляет конкретных данных.

Существует ли лечение?

В случае, когда ПК зависает, отказываясь реагировать на любую команду мыши или клавиатуры, помогает только режим перезагрузки, попасть в который можно только с помощью длительного нажатия и удерживания кнопки питания. Но это не гарантирует дальнейшую бесперебойную работу. Вероятнее всего, что первые несколько минут/часов система проработает без нареканий, а затем повторно появится проблема.
Опытным путем стало понятно, что полная переустановка системы тоже не помогает. Отсюда напрашивается вывод, что проблема находится на уровне взаимодействия системы, ПО, ОЗУ, ПЗУ и жесткого диска. Действительно, прочитав рекомендуемые требования на упаковке диска с игрой, можно обнаружить что требования, предъявляемые к «железу», для того чтобы игра установилась, запустилась и шла ровно и плавно достаточно высокие. Кроме этого, рекомендуется проверить все ли шлейфы подключены к разъемам нет ли заломов, а также стабильность работы блока питания.

Windows ошибка kernel. Настройка Биоса

Одной из причин, вызывающих Kernel-Power является критический перегрев процессора. Это может случиться по двум причинам:

  • Его слишком сильно разогнали
  • Он не предназначен для сильных нагрузок
  • Высохла термопаста
  • Плохая система отвода тепла

Первое действие, которое нужно выполнить в таком случае, это проверить исходные данные ЦП и снизить все завышенные показатели, непосредственно связанные с разгоном. Так как для большинства обычных пользователей такие манипуляции выполнить достаточно трудно, в этом случае рекомендуется просто сделать откат до базовых заводских настроек.
Если вы используете не ноутбук, а простой компьютер, то можно достать материнскую плату и на некоторое непродолжительное время вынуть батарейку. Можно попробовать перевести Clear CMOS из положения «1-2» в положение «2-3» меньше чем на минуту, а затем вернуть его в исходное положение. Это тоже приведет к полному сбросу. Правда, этот способ тоже не гарантирует решения проблемы.

Тестирование центрального процессора

При повторном обнаружении Kernel-Power стоит провести тестирование центрального процессора ПК. Для этого скачивается и распаковывается специальная программа Everest. С ее помощью можно выяснить какие компоненты дали сбой. Правда, сделать восстановление через утилиту невозможно. Оптимально провести тестирование при помощи Prime95. Выбираете Just Stress Testing в опциях раздела Torture Test.

Сбой работы Kernel-Power может быть связан с ошибками в работе оперативной памяти. Проверить память можно несколькими способами. Первый – при помощи стандартной системной программы, введя в командную строку «mdsched»,и запустив перезагрузку системы с ее тестированием. Выполнить это можно только при условии, что вы зашли через учетную запись Администратора.
В случае, если проверка не выявила никаких неполадок можно прибегнуть к физическому способу – поочередно извлекать из своих слотов планки оперативной памяти каждый раз выполняя перезагрузку ПК. Если после определенного извлечения компьютер работает нестабильно, значит проблема кроется в ней, и стоить заменить ее на идентичную.

Проблема с жестким диском

Еще одна распространенная проблема заключается в том, что многие жесткие диски плохо стыкуются в 64-х битной операционной системой. Чаще всего этим страдают винчестеры бренда Seagate, установленные в большинстве современных бюджетных ноутбуков.
Для проверки необходимо скачать и установить HDD Life или HDD Health, запустить соответствующую проверку. В редких случаях может потребоваться обновление прошивки жесткого диска до последней версии. Если неполадки заключаются в винчестере, решения может быть два – замена жесткого диска или ремонт в соответствующих сервисных центрах. Правда, он не дает гарантий, что через некоторое время вам не потребуется приобретать новый жесткий диск.
Можно попробовать самостоятельно восстановить битые кластеры жесткого диска при помощи пакета утилит HDD Regenerator, но и она не гарантирует восстановление жесткого диска в его первоначальное состояние.

Проблема звуковых и видеокарт

Такая проблема зачастую возникает в случае, если на ПК были установлены две звуковые или видеокарты. Установленные программы пытаются работать с обеими, что приводит к сильнейшим сбоям на программном уровне. Для решения данной проблемы следует удалить один из чипов или правильно настроить параллельную работу двух карт.

Драйвера сетевой карты

Появление ошибки Kernel-Power может быть спровоцировано не обновлёнными вовремя драйверами сетевой карты или неправильная их распаковка и установка. В этом случае можно попробовать сделать следующее:

Зайти на официальный сайт разработчика и скачать последнюю версию, после чего провести установку,
Если версия относится к последним, полностью удалить драйвера, после чего переустановить их и перезапустить ПК.

Обновление системы

Для того, чтобы постараться избежать появления многих системных ошибок, рекомендуется разрешить Windows обновлять элементы самостоятельно в автоматическом режиме. Проблемы, связанные с «железом», это не решит, а вот системных избежать удастся.
Зайдите в Центр обновления Windows, поставьте галочку напротив нужного режима. В этом случае, предпочтение стоит отдать полной автоматизации, чтобы избежать ручных действий.

Kernel-Power представляет собой серьезную и непростую ошибку, конкретные причины которой установить пока не удалось. Если ни один из вышеперечисленных методов не дал положительного результата, или проблема пропала на короткий промежуток времени, а затем появилась снова, рекомендуется обратиться в сервисную службу.


Меня всегда интересовало низкоуровневое программирование – общаться напрямую с оборудованием, жонглировать регистрами, детально разбираться как что устроено. Увы, современные операционные системы максимально изолируют железо от пользователя, и просто так в физическую память или регистры устройств что-то записать нельзя. Точнее я так думал, а на самом деле оказалось, что чуть ли не каждый производитель железа так делает!

В чём суть, капитан?

В архитектуре x86 есть понятие «колец защиты» («Ring») – режимов работы процессора. Чем ниже номер текущего режима, тем больше возможностей доступно исполняемому коду. Самым ограниченным «кольцом» является «Ring 3», самым привилегированным – «Ring -2» (режим SMM). Исторически сложилось, что все пользовательские программы работают в режиме «Ring 3», а ядро ОС – в «Ring 0»:

Режимы работы x86 процессора

Режимы работы x86 процессора

В «Ring 3» программам запрещены потенциально опасные действия, такие как доступ к I/O портам и физической памяти. По логике разработчиков, настолько низкоуровневый доступ обычным программам не нужен. Доступ к этим возможностям имеют только операционная система и её компоненты (службы и драйверы). И всё бы ничего, но однажды я наткнулся на программу RW Everything:

RW Everything действительно читает и пишет практически всё

RW Everything действительно читает и пишет практически всё

Эта программа была буквально напичкана именно теми функциями, которые обычно запрещаются программам «Ring 3» - полный доступ к физической памяти, I/O портам, конфигурационному пространству PCI (и многое другое). Естественно, мне стало интересно, как это работает. И выяснилось, что RW Everything устанавливает в систему прокси-драйвер:

Смотрим последний установленный драйвер через OSR Driver Loader

Смотрим последний установленный драйвер через OSR Driver Loader

Прокси-драйвера

В итоге получается обходной манёвр – всё, что программе запрещено делать, разработчик вынес в драйвер, программа устанавливает драйвер в систему и уже через него программа делает, что хочет! Более того – выяснилось, что RW Everything далеко не единственная программа, которая так делает. Таких программ не просто много, они буквально повсюду. У меня возникло ощущение, что каждый уважающий себя производитель железа имеет подобный драйвер:

Софт для обновления BIOS (Asrock, Gigabyte, HP, Dell, AMI, Intel, Insyde…)

Софт для разгона и конфигурации железа (AMD, Intel, ASUS, ASRock, Gigabyte)

Софт для просмотра сведений о железе (CPU-Z, GPU-Z, AIDA64)

Софт для обновления PCI устройств (Nvidia, Asmedia)

Во многих из них практически та же самая модель поведения – драйвер получает команды по типу «считай-ка вот этот физический адрес», а основная логика – в пользовательском софте. Ниже в табличке я собрал некоторые прокси-драйвера и их возможности:

Результаты краткого анализа пары десятков драйверов. Могут быть ошибки!

Результаты краткого анализа пары десятков драйверов. Могут быть ошибки!

Mem – чтение / запись физической памяти

PCI – чтение / запись PCI Configuration Space

I/O – чтение / запись портов I/O

Alloc – аллокация и освобождение физической памяти

Map – прямая трансляция физического адреса в вирутальный

MSR – чтение / запись x86 MSR (Model Specific Register)

Жёлтым обозначены возможности, которых явно нет, но их можно использовать через другие (чтение или маппинг памяти). Мой фаворит из этого списка – AsrDrv101 от ASRock. Он устроен наиболее просто и обладает просто огромным списком возможностей, включая даже функцию поиска шаблона по физической памяти (!!)

Неполный перечень возможностей AsrDrv101

Чтение / запись RAM

Чтение / запись IO

Чтение / запись PCI Configuration Space

Чтение / запись MSR (Model-Specific Register)

Чтение / запись CR (Control Register)

Чтение TSC (Time Stamp Counter)

Чтение PMC (Performance Monitoring Counter)

Alloc / Free физической памяти

Поиск по физической памяти

Самое нехорошее в такой ситуации - если подобный драйвер остаётся запущенным на ПК пользователя, для обращения к нему не нужно даже прав администратора! То есть любая программа с правами пользователя сможет читать и писать физическую память - хоть пароли красть, хоть ядро пропатчить. Именно на это уже ругались другие исследователи. Представьте, что висящая в фоне софтина, красиво моргающая светодиодиками на матплате, открывает доступ ко всей вашей системе. Или вирусы намеренно ставят подобный драйвер, чтобы закрепиться в системе. Впрочем, любой мощный инструмент можно в нехороших целях использовать.

Через Python в дебри

Конечно же я захотел сделать свой небольшой "тулкит" для различных исследований и экспериментов на базе такого драйвера. Причём на Python, мне уж очень нравится, как просто выглядит реализация сложных вещей на этом языке.

Первым делом нужно установить драйвер в систему и запустить его. Делаем "как положено" и сначала кладём драйвер (нужной разрядности!) в System32:

Раньше в похожих ситуациях я извращался с папкой %WINDIR%\Sysnative, но почему-то на моей текущей системе такого алиаса не оказалось, хотя Python 32-битный. (по идее, на 64-битных системах обращения 32-битных программ к папке System32 перенаправляются в папку SysWOW64, и чтобы положить файлик именно в System32, нужно обращаться по имени Sysnative).

Затем регистрируем драйвер в системе и запускаем его:

А дальше запущенный драйвер создаёт виртуальный файл (кстати, та самая колонка "имя" в таблице с анализом дров), через запросы к которому и осуществляются дальнейшие действия:

И ещё одна полезная программа для ползания по системе, WinObj

И ещё одна полезная программа для ползания по системе, WinObj

Тоже ничего особенного, открываем файл и делаем ему IoCtl:

Вот здесь чутка подробнее. Я долго думал, как же обеспечить адекватную обработку ситуации, когда таких "скриптов" запущено несколько. Не останавливать драйвер при выходе нехорошо, в идеале нужно смотреть, не использует ли драйвер кто-то ещё и останавливать его только если наш скрипт "последний". Долгие упорные попытки получить количество открытых ссылок на виртуальный файл драйвера ни к чему не привели (я получал только количество ссылок в рамках своего процесса). Причём сама система точно умеет это делать - при остановке драйвера с открытым файлом, он остаётся висеть в "Pending Stop". Если у кого есть идеи - буду благодарен.

В конечном итоге я "подсмотрел", как это делают другие программы. Выяснилось, что большинство либо не заморачиваются, либо просто ищут запущенные процессы с тем же именем. Но одна из исследованных программ имела кардинально другой подход, который я себе и перенял. Вместо того, чтобы переживать по количеству ссылок на файл, просто на каждый запрос открываем и закрываем файл! А если файла нет, значит кто-то остановил драйвер и пытаемся его перезапустить:

А дальше просто реверсим драйвер и реализуем все нужные нам вызовы:

Легко и непринуждённо в пару команд читаем физическую память

Легко и непринуждённо в пару команд читаем физическую память

PCI Express Config Space

Немного отвлечёмся на один нюанс про PCIE Config Space. С этим адресным пространством не всё так просто - со времён шины PCI для доступа к её конфигурационному пространству используется метод с использованием I/O портов 0xCF8 / 0xCFC. Он применён и в нашем драйвере AsrDrv101:

Чтение и запись PCI Config Space

Чтение и запись PCI Config Space

Но через этот метод доступны только 0x100 байт конфигурационного пространства, в то время как в стандарте PCI Express размер Config Space у устройств может быть достигать 0x1000 байт! И полноценно вычитать их можно только обращением к PCI Extended Config Space, которая замаплена где-то в адресном пространстве, обычно чуть пониже BIOS:

Адресное пространство современного x86 компа, 0-4 ГБ

Адресное пространство современного x86 компа, 0-4 ГБ

На чипсетах Intel (ну, в их большинстве) указатель на эту область адресного пространства можно взять из конфига PCI устройства 0:0:0 по смещению 0x60, подробнее описано в даташитах:


У AMD я такого не нашёл (наверняка есть, плохо искал), но сам факт неуниверсальности пнул меня в сторону поиска другого решения. Погуглив стандарты, я обнаружил, что указатель на эту область передаётся системе через ACPI таблицу MCFG

А сами ACPI таблицы можно найти через запись RSDP, поискав её сигнатуру по адресам 0xE0000-0xFFFFF, а затем распарсив табличку RSDT. Отлично, здесь нам и пригодится функционал поиска по памяти. Получаем нечто такое:

На всякий случай оставляем вариант для чипсетов Intel

Всё, теперь осталось при необходимости заменить чтение PCI Express Config Space через драйвер на чтение через память. Теперь-то разгуляемся!

Читаем BIOS

В качестве примера применения нашего "тулкита", попробуем набросать скрипт чтения BIOS. Он должен быть "замаплен" где-то в конце 32-битного адресного пространства, потому что компьютер начинает его исполнение с адреса 0xFFFFFFF0. Обычно в ПК стоит флеш-память объёмом 4-16 МБ, поэтому будем "сканировать" адресное пространство с адреса 0xFF000000, как только найдём что-нибудь непустое, будем считать, что тут начался BIOS:

В результате получаем:

Вот так в 10 строчек мы считали BIOS

Вот так в 10 строчек мы считали BIOS

Но подождите-ка, получилось всего 6 мегабайт, а должно быть 4 или 8 что-то не сходится. А вот так, у чипсетов Intel в адресное пространство мапится не вся флешка BIOS, а только один её регион. И чтобы считать всё остальное, нужно уже использовать SPI интерфейс.

Не беда, лезем в даташит, выясняем, что SPI интерфейс висит на PCI Express:


И для его использования, нужно взаимодействовать с регистрами в BAR0 MMIO по алгоритму:

Задать адрес для чтения в BIOS_FADDR

Задать параметры команды в BIOS_HSFTS_CTL

Прочитать данные из BIOS_FDATA

Пилим новый скрипт для чтения через чипсет:

Исполняем и вуаля - в 20 строчек кода считаны все 8 МБ флешки BIOS! (нюанс - в зависимости от настроек, регион ME может быть недоступен для чтения).

Точно так же можно делать всё, что заблагорассудится - делать снифер USB пакетов, посылать произвольные ATA команды диску, повышать частоту процессора и переключать видеокарты. И это всё - с обычными правами администратора:

Немного помучившись, получаем ответ от SSD на команду идентификации

Немного помучившись, получаем ответ от SSD на команду идентификации

А если написать свой драйвер?

Некоторые из вас наверняка уже подумали - зачем так изворачиваться, реверсить чужие драйвера, если можно написать свой? И я о таком думал. Более того, есть Open-Source проект chipsec, в котором подобный драйвер уже разработан.

Зайдя на страницу с кодом драйвера, вы сразу наткнетесь на предупреждение:

В этом предупреждении как раз и описываются все опасности, о которых я рассказывал в начале статьи - инструмент мощный и опасный, следует использовать только в Windows режиме Test Mode, и ни в коем случае не подписывать. Да, без специальной подписи на обычной системе просто так запустить драйвер не получится. Поэтому в примере выше мы и использовали заранее подписанный драйвер от ASRock.

Если кто сильно захочет подписать собственный драйвер - понадобится регистрировать собственную компанию и платить Microsoft. Насколько я нагуглил, физическим лицам такое развлечение недоступно.

Точнее я так думал, до вот этой статьи, глаз зацепился за крайне интересный абзац:

У меня под рукой нет Windows DDK, так что я взял 64-битный vfd.sys , скомпилированный неким critical0, и попросил dartraiden подписать его «древне-китайским способом». Такой драйвер успешно загружается и работает, если vfdwin запущена с правами администратора

Драйвер из статьи действительно подписан, и действительно неким китайским ключом:

Как оказалось, сведения о подписи можно просто посмотреть в свойствах.. А я в HEX изучал

Как оказалось, сведения о подписи можно просто посмотреть в свойствах.. А я в HEX изучал

Немного поиска этого имени в гугле, и я натыкаюсь на вот эту ссылку, откуда узнаю, что:

есть давно утёкшие и отозванные ключи для подписи драйверов

если ими подписать драйвер - он прекрасно принимается системой

малварщики по всему миру используют это для создания вирусни

Основная загвоздка - заставить майкрософтский SignTool подписать драйвер истёкшим ключом, но для этого даже нашёлся проект на GitHub. Более того, я нашёл даже проект на GitHub для другой утилиты подписи драйверов от TrustAsia, с помощью которого можно подставить для подписи вообще любую дату.

Несколько минут мучений с гугл-переводчиком на телефоне, и мне удалось разобраться в этой утилите и подписать драйвер одним из утекших ключей (который довольно легко отыскался в китайском поисковике):

И в самом деле, китайская азбука

И в самом деле, китайская азбука

И точно так же, как и AsrDrv101, драйвер удалось без проблем запустить!

А вот и наш драйвер запустился

А вот и наш драйвер запустился

Из чего делаю вывод, что старая идея с написанием своего драйвера вполне себе годная. Как раз не хватает функции маппинга памяти. Но да ладно, оставлю как TODO.

Выводы?

Как видите, имея права администратора, можно делать с компьютером практически что угодно. Будьте внимательны - установка утилит от производителя вашего железа может обернуться дырой в системе. Ну а желающие поэкспериментировать со своим ПК - добро пожаловать на низкий уровень! Наработки выложил на GitHub. Осторожно, бездумное использование чревато BSODами.

В Windows есть фича "Изоляция ядра", которая включает I/O MMU, защищает от DMA атак и так далее (кстати об этом - в следующих сериях)


Так вот, при включении этой опции, некоторые драйвера (в том числе RW Everything и китайско-подписанный chipsec_hlpr) перестают запускаться:


Любой программист знает, что теоретически он может внести свой посильный вклад в развитие Linux ядра. С другой стороны, подавляющее большинство уверено, что занимаются этим исключительно небожители, а процесс контрибьюта в ядро настолько сложен и запутан, что обычному человеку разобраться в нём нет никакой возможности. А значит, и надобности.
Сегодня мы попробуем развеять эту легенду и покажем, как абсолютно любой инженер при наличии достойной идеи, воплощённой в коде, может предложить ее на рассмотрение Linux community для включения в ядро.

0. Подготовка

Как и перед любой инженерной операцией, всё начинается с подготовки своего рабочего места. И первейшее здесь действие — это завести себе аккаунт с адекватным именем. В идеальном мире это будет просто транскрипция имени и фамилии. Если за учётку вроде MamkinC0d$r или Developer31337 в других местах пальцем в вас тыкать не будут, то правила LKC (Linux kernel community) такое прямо запрещают — инкогнито контрибьютить в ядро не принято.

Далее вам понадобится место на локальной машине. Сама папка Linux со скачанными исходниками весит чуть меньше 3-х гигов. Но если ядро пробовать собирать, то вместе с модулями займёт все 30 GB.

Захотелось собрать несколько веток? Умножаем 30 на число веток.
И помним — скорость сборки прямо связана с количеством доступных ядер! Больше ядер — быстрее соберётся. Так что не стесняйтесь выделять под это самую мощную машину.

1. Mail

Вокруг необходимости делать всё через плейнтекст в почте есть масса споров. Недавно в сети была очередная громкая статья на эту тему. Суть материала: письма — это, конечно, здорово, но пихать туда всё, включая куски кода — это вам (т.е. LKC) популярности не добавляет и даже наоборот, отпугивает новичков. С одной стороны вроде и да, если ты не можешь спокойно и структурировано изложить свои мысли в голом тексте, то в низкоуровневой разработке ловить будет особо нечего. С другой стороны, слать в письмах сорсы патчей — это даже архаизмом назвать уже сложно.

Но, как принято в уютном мирке ядра, Линус хлопнул кулаком по столу — и все пишут письма. Возможно, буквально завтра это изменится, но на момент выхода статьи это письма и только письма.

Какой email-client выбрать — есть рекомендации. Самым рекомендуемым почтовым агентом для LKC остаётся mutt. Да, тот самый текстовый почтовый клиент, от которого сводит олдскулы. Для начала mutt нужно поставить (я думаю, со своим пакетным менеджером вы и сами справитесь), а потом задать параметры в файле

Но почты недостаточно. Без Git никуда.

2. Git

Прежде чем что-то делать с исходниками ядра, нужно настроить Git. Можно конфигурировать файлы напрямую, но есть упрощающая жизнь утилита git config, через которую можно регулировать все аспекты работы Git'a.

Внутри есть три уровня настроек: общие для всех пользователей системы и для всех репозиториев (git config --system), общие для всех репозиториев конкретного пользователя (git config --global), отдельные для каждого репозитория (git config --local).

Глобальные настройки хранятся в /etc/gitconfig, настройки пользователя в

/.config/git/config, а настройки отдельных репозиториев хранятся в файле config в каталоге .git/config.

В общем случае будет достаточно законфигурировать файл для пользователя

/.gitconfig . Основная идея: при отправке коммитов должно отображаться ваше корректное имя.

signOff обязателен, чтоб в коммитах была информация об авторе. По идее, надо бы, чтобы коммиты подписывались. Была тут недавно статья на эту тему.

Отправка патча выполняется командой git send-email. У git send-email есть несколько параметров с участием smtp, которые можно (и нужно) переопределить.

Можно задавать пароль к почте через параметр --smtp-pass=p4ssw0rd или вообще захардкорить в конфиге, но это это для тех, кому терять нечего. Но если каждый раз вводить пароль лень, то есть некий хак: если username был задан (через --smtp-user или sendmail.smtpUser), а пароль не указан, тогда пароль получается через git-credential.

Итак, окно в большой мир прорубили. Можно переходить к воплощению своей грандиозной идеи в коде.

3. Coding

Итак, мы готовы сделать первый шаг непосредственно в разработке — склонировать к себе репозиторий. Советую делать это сразу с указанием ветки, которая будет создана. Также отмечу, что работать лучше не над текущим состоянием в master, а над стабильной версией или кандидатом на релиз. Так вы будете более уверены, что ядро соберётся и будет как-то работать, не вызовет неожиданных конфликтов из-за изменений в других подсистемах. Поэтому всегда внимательно смотрите тэги.

И — опять же — имя своей ветке постарайтесь дать чёткое и лаконичное. В идеальном мире оно даже может отображать суть вносимых изменений. Если вы исправляете известный баг, то хорошим тоном считается включить в название ветки номер issue.

Операция довольно долгая, так что смело можно идти за кофе или на обед. А если попробовать ускорить процесс, отказавшись от истории, то работать с "этим" будет невозможно.

Итак, мы получили ветку, в которой можно начинать свою разработку. Здесь всё очевидно: пишем код, собираем, тестируем, исправляем баги — и так до получения нужного результата. О том, как собирать ядро и проводить отладку, информации в сети море, так что подробно описывать весь процесс я не буду. Лишь вкратце пробежимся по нему чуть позже. Единственный нюанс, который добавлю от себя прямо сейчас: перед сборкой проверьте наличие всех необходимых программ из этого списка и их минимальные версии.

Если бродить вслепую по гуглу не хочется, то вся максимально полезная информация по ядру сконцентрирована тут. Прочитать стоит действительно всё. Особенно правильно будет начать с How To о том, как правильно коммуницировать. Потому что мейнтейнеры, как правило, люди весьма занятые, и вникать в невнятно составленные письма им никакого интереса. Да и вам будет обидно, если из-за плохого описание ваше детище не примут в апстрим.

И вот свой небольшой и эффективный код вы написали, отладили, всё протестировали и готовы отправлять на рассмотрение. Но не спешите этого делать. Для начала обязательно проверьтесь на code style. В этом вам поможет ./script/checkpatch.pl . Для этого сделаем патч и отправим его на проверку.

После того, как пройдёт первое удивление и вы доустановите необходимые компоненты для python2 типа ply и git (который у меня так и не установился), наступит чудесное время исправления ошибок и ворнингов. По результатам которых вы а) поймёте, что красивый код писать вы не умеете б) потеряете всякое желание что-то куда-то отправлять. Ведь даже если отбросить все шутки, ещё можно как-то смириться с тем, что длина строк ограничена 100 символами (это начиная с версии 5.7, раньше так было вообще 80). Но вот такие места оставляют неизгладимое впечатление:

Для .h файлов строка с информацией о лицензии должна быть в ремарках / * */, а для *.c файлов должна быть в ремарках //. Такое запросто выбьет кого угодно из душевного равновесия. Вопрос: "Зачем?!" до сих пор болтается в моей голове, хотя есть вера в то, что это не просто ошибка в скриптах.

Кстати, чтобы просто проверить один файл достаточно вызвать

Можно прикрутить этот вызов к git, чтобы автоматически запускался этот скрипт при попытке что-то зачекинить.

Ещё важное замечание: clang-format добрался и до ядра Linux. Файл .clang-format расположился в корне ядра в кучке с другими конфигами. Но я не советую добавлять его в хук для git. Лучше всего корректно настроить среду разработки и запомнить code style. Лично мне не понравилось как он делает переносы длинных строк. Если вдруг строка оказалась длиннее допустимой, то скорее всего функция, в которой эта строка расположилась, является кандидатом на рефакторинг, и лучше его не откладывать. С другой стороны, если у вас много уже готового кода который нужно адаптировать для ядра — clang-format может сильно облегчить вам задачу.

4. Kernel build

Несмотря на то, что процесс описан в других статьях тут и тут, я все же повторюсь.

По шагам процесс сборки ядра довольно прост, если не вдаваться в детали. Для начала ставим необходимые пакеты (использовался Debian 10):

Это без компилятора и обычного для С/С++ разработчика набора программ.
Запускаем конфигурацию:

Тут есть интересный аспект: в качестве шаблона будет браться config ядра от вашего боевого ядра, которое, скорее всего, подготовлено дистрибьютером. Для Debian 10 сборка проходит успешно, если в конфиге потереть информацию о встраиваемых в ядро сертификатах.

Перед попыткой собрать проверьте, что нужные программы уже установлены. Список тут. Чтобы собрать само ядро:

Этого достаточно для проверки собираемости, но недостаточно для запуска ядра в системе, так как без модулей ядро на реальной системе практически беспомощно.

Если какой-то модуль не собирается, просто вырубите его в ближайшем Makefile-е (если 100% уверены, что не пытались в нём что-то улучшить). Наверняка он вам не пригодится, и тратить время на исправления смысла нет.

Теперь можно деплоить то, что получилось, на эту же систему.

Хотя, конечно, экспериментировать с ядром на той же машине, где ведётся разработка — дело рискованное.

Поэтому как минимум нужно снять снапшот, сделать резервную копию или лучше вообще выполнять отладку на другой (лучше виртуальной) машине. Но как это делать, я пока не разбирался. Если у кого есть такой опыт — пишите в комменты, добавлю в статью.

На моей системе загрузчик после установки ядра автоматически обновился. Если у вас этого не произошло, то это делается это на Debian-подобных системах командой:

Update: Как верно заметил gavk, ядро давно уже умеет собирать пакеты, причём как для deb, так и для rpm.
Команда

выводит весь ассортимент. Так что команда

должна собрать пакет с ядром.

5. Patches

Вот теперь мы действительно подготовили код для отправки. Лучше всего, чтобы это был единственный коммит. Так проще делать ревью и так быстрее вам ответят. Всё проверив, наконец-то делаем коммит.

Ещё можно комментарии к коммиту дополнить в человеческом текстовом редакторе.

И теперь его можно оформить в виде того самого письма. Правила хорошего тона, или best practice, если угодно — это 75 символов на строку.

В результате получите два файла. В первом 000-cover-letter.patch нужно указать заголовок письма "Subject" и основное описание патча. В описании патча пишем, для чего он создавался, кому он сделает жизнь на нашей планете лучше и каким образом. Только не словоблудим про космические корабли в Большом театре, а пишем лаконично и по делу. И не в коем случае не пишите корпоративную лабуду а-ля "Без этого патча мой бизнес встанет, меня уволят, а дети мои умрут от голода". Нет, строго по существу: "Увидел вот такую проблему вот тут, починить решил вот таким образом, исходники патча прилагаю". Всё, вы восхитительны! А если не превысили 75 символов на строку, то восхитительны в квадрате.

А ещё один волшебный скриптик ./scripts/getmaintainers.pl <patch file> позволит узнать, кому письмо отправлять.

И вот он, момент отправления письма, ради которого всё и затевалось:

После того, как ваш патч был принят, крайне желательно удалить свою ветку.

6. Debuging

И чуть-чуть про отладку. Бонус "на сладкое" для начинающих разработчиков ядра, так сказать.

Как правило, при ошибке вы получаете лог с calltrace-ом. Там указываются имена функций и смещения. Примерно вот так:

Так вот, чтобы понять, в каком месте функции произошла ошибка, достаточно запустить дебагер с подгруженным в него модулем:

Важно, чтобы в модуле сохранились символы (stripped модуль вам тут не поможет).

Выполнив команду list

вы увидите строку кода, приведшую к ошибке. В случае передачи управления по неверному адресу, вы увидите следующую за ошибкой строку.

For information about programming interfaces that your driver can implement or call, see the Kernel-Mode Driver Reference.

This section includes general concepts to help you understand kernel-mode programming and describes specific techniques of kernel programming. For a general overview of Windows Drivers, see Getting Started with Windows Drivers, which provides a general overview of Windows components, lists the types of device drivers used in Windows, discusses the goals of Windows device drivers, and discusses generic sample device drivers included in the kit.

This section contains conceptual information that describes and helps you build kernel-mode drivers.

An Overview containing:

Kernel-Mode Components describes the primary kernel-mode managers and components of the Windows operating system.

Writing WDM Drivers and Introduction to WDM provide information needed to write drivers using the Windows Driver Model (WDM).

Device Objects and the other topics in Device Objects and Device Stacks describe how the operating system represents devices by device objects.

Memory Management for Windows Drivers illustrates how kernel-mode drivers allocate memory for purposes such as storing internal data, buffering data during I/O operations, and sharing memory with other kernel-mode and user-mode components.

Security From Controlling Device Access and Privileges to SDDL for Device objects, ensure that your drivers are as secure as possible.

Handling IRPs describes how kernel-mode drivers handle I/O request packets (IRPs).

DMA Direct Memory Access (DMA) is a critical aspect of driver development, and the topics in this node cover DMA from A to Z.

Controller Objects represent a physical device controller with attached devices.

Interrupt Service Routines (ISRs) handle interrupts for drivers of a physical device that receives interrupts.

Message-Signaled Interrupts trigger an interrupt by writing a value to a particular memory address.

Deferred Procedure Calls (DPC Objects) can be queued from ISRs and are executed at a later time and at a lower IRQL than the ISR.

Plug and Play (PnP) focuses on the system software support for PnP and how drivers use that support to implement PnP.

Power Management describes the architecture that provides a comprehensive approach to system and device power management.

Windows Management Instrumentation (WMI) are extensions to your kernel-mode driver, which enable your driver to become a WMI provider. A WMI provider makes measurement and instrumentation data available to WMI consumers, such as user-mode applications.

Driver Programming Techniques Programming drivers in the kernel mode of Windows requires techniques that sometimes differ significantly from those of ordinary user-mode programming.

Читайте также: