Чтение онлайн

на главную

Жанры

Разработка ядра Linux
Шрифт:

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

С чего необходимо начать

Итак, готовы ли вы начать охоту за ошибками? Этот путь может оказаться длинным и полным разочарований. Некоторые ошибки ставили в тупик все сообщество разработчиков ядра на несколько месяцев. К счастью, на каждую из таких злостных ошибок находятся простые, которые легко исправить.

Если вам повезет, то все проблемы, с которыми вы столкнетесь, будут простыми и тривиальными. Однако чтобы это проверить, необходимо начать исследования. Для этого понадобится следующее.

• Сама проблема. Может звучать глупо, но дефект должен быть конкретным и хорошо определенным. Очень помогает, если его хотя бы кто-нибудь может устойчиво воспроизвести. Однако, к сожалению, дефекты обычно ведут себя не так хорошо, как хотелось бы, и не всегда могут быть хорошо определены.

• Версия ядра, в которой существует дефект (обычно это последняя версия, хотя кто может это гарантировать?). Еще лучше, если известна версия ядра, в которой проблема впервые появилась. Мы рассмотрим, как это установить, если нет такой информации.

• Немного удачи, опыта и их комбинации.

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

Может также показаться странным, что существуют дефекты, которые кто-то не может воспроизвести. Дело в том, что в пользовательских программах дефекты чаще всего проявляются очень просто, например вызов функции

foo
приводит к созданию файла
core
. В ядре все совсем по-другому. Взаимодействия между ядром, пространством пользователя и аппаратурой могут быть достаточно тонкими. Состояния конкуренции за ресурсы могут возникать с вероятностью одно на миллион итераций алгоритма. Плохо спроектированный или даже не правильно скомпилированный код может обеспечивать удовлетворительную производительность на одной системе, но неудовлетворительную на другой, Очень часто происходит так, что на какой-то случайной машине, при очень специфическом характере загрузке, начинают проявляться дефекты, которые больше нигде не проявляются. Чем больше доступно дополнительной информации при локализации дефекта, тем лучше. Во многих случаях, как только удалось устойчиво воспроизвести проблему, можно считать, что большая половина работы сделана.

Дефекты ядра

Дефекты в ядре могут быть такими же разнообразными, как и дефекты в пользовательских программах. Они возникают по различным причинам и проявляются в разнообразных формах. Дефекты занимают диапазон от явно неправильного кода (например, запись правильного значения в неправильное место) до ошибок синхронизации (например, если не правильно блокируется совместно используемая переменная). Эти дефекты проявляются в любой форме; от плохой производительности до неправильного функционирования и даже до потери данных.

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

Спустя некоторое время второй процесс может обратиться к этим данным, что в свою очередь может привести к попытке разыменования указателя со значением
NULL
, если будут считаны случайные данные ("мусор"), или вообще не привести ни к чему плохому (если данные в соответствующей области памяти еще не были перезаписаны). Разыменование указателя со значением
NULL
приводит к выводу сообщения
"oops"
, в то время, как случайный "мусор" может привести к потере данных (и соответственно к неправильному функционированию, или опять же к выводу сообщения
"oops"
, но уже по другом поводу). Пользователь же заметит только неправильное функционирование или сообщение
"oops"
. Разработчик ядра при этом должен пойти но обратному пути: исходя из ошибки определить, что к данным было обращение после того, как память с этими данными была освобождена, что это произошло в результате возникновения конкуренции за ресурс и исправить ошибку путем правильного учета количества ссылок на совместно используемую структуру данных. Для этого также вероятно потребуется применение блокировок.

Отладка ядра может показаться сложным делом, тем не менее, ядро не особо отличается от других больших программных проектов. У ядра есть свои уникальные особенности, такие как ограничения связанные со временем выполнения участков кода, возможности возникновения состояний конкуренции (race) — как результат параллельного выполнения множества потоков в ядре. Можно дать стопроцентную гарантию, что если приложить некоторые усилия и понимание, то проблемы ядра можно с успехом находить и решать (и даже, возможно, получать удовольствие от успешного преодоления трудностей).

Функция

printk

Функция форматированного вывода сообщений

printk
работает аналогично библиотечной функции
printf
языка С. Действительно в этой книге до этого момента мы не видели никаких существенных отличий в ее использовании. Для большинства задач это именно так: функция
printk
— это просто функция ядра, выполняющая форматированный вывод сообщений. Однако, некоторые различия все же имеются.

Устойчивость функции

printk

Одно из проверенных и часто используемых свойств функции

printk
— это ее устойчивость. Функцию
printk
можно вызывать практически в любое время и в любом месте ядра. Её можно вызывать из контекста прерывания и из контекста процесса. Её можно вызывать во время удержания блокировки. Её можно вызывать одновременно на нескольких процессорах и она не требует при этом удерживать какие-нибудь блокировки.

Эта функция очень устойчива, и это очень важно, потому что полезность функции

printk
базируется на том факте, что она всегда доступна и всегда работает.

Неустойчивость функции
printk

Слабое место у функции

printk
в плане устойчивости все же существует. Её нельзя использовать до некоторого момента при загрузки ядра, пока консоль еще не инициализирована. Действительно, если нет консоли, то куда будут выводится сообщения?

Обычно это не проблема, если не нужно выполнять отладку кода, который выполняется на очень ранних стадиях процесса загрузки (например, функции

setup_arch
, которая выполняет инициализацию специфичную для аппаратной платформы). Отладка такого рода — настоящая задача: отсутствие каких-либо способов вывода сообщений, а только проблема в полном составе.

Поделиться:
Популярные книги

Прометей: повелитель стали

Рави Ивар
3. Прометей
Фантастика:
фэнтези
7.05
рейтинг книги
Прометей: повелитель стали

Гром над Академией Часть 3

Машуков Тимур
4. Гром над миром
Фантастика:
фэнтези
5.25
рейтинг книги
Гром над Академией Часть 3

Уязвимость

Рам Янка
Любовные романы:
современные любовные романы
7.44
рейтинг книги
Уязвимость

Войны Наследников

Тарс Элиан
9. Десять Принцев Российской Империи
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Войны Наследников

Законы рода

Flow Ascold
1. Граф Берестьев
Фантастика:
фэнтези
боевая фантастика
аниме
5.00
рейтинг книги
Законы рода

«Три звезды» миллиардера. Отель для новобрачных

Тоцка Тала
2. Три звезды
Любовные романы:
современные любовные романы
7.50
рейтинг книги
«Три звезды» миллиардера. Отель для новобрачных

Мимик нового Мира 13

Северный Лис
12. Мимик!
Фантастика:
боевая фантастика
юмористическая фантастика
рпг
5.00
рейтинг книги
Мимик нового Мира 13

Месть за измену

Кофф Натализа
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Месть за измену

Мастер 3

Чащин Валерий
3. Мастер
Фантастика:
героическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Мастер 3

Не грози Дубровскому! Том 11

Панарин Антон
11. РОС: Не грози Дубровскому!
Фантастика:
фэнтези
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Не грози Дубровскому! Том 11

Наваждение генерала драконов

Лунёва Мария
3. Генералы драконов
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Наваждение генерала драконов

Огненный князь 4

Машуков Тимур
4. Багряный восход
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Огненный князь 4

Мужчина не моей мечты

Ардова Алиса
1. Мужчина не моей мечты
Любовные романы:
любовно-фантастические романы
8.30
рейтинг книги
Мужчина не моей мечты

Золушка по имени Грейс

Ром Полина
Фантастика:
фэнтези
8.63
рейтинг книги
Золушка по имени Грейс