Главная » Ядро Linux » Нахождение исполняемых образов с изменениями приводящими к ошибкам

0

Обычно полезно знать, в какой  версии  исходных  кодов  ядра  появился дефект. Если  известно, что дефект  появился в версии  2.4.18, но его не было в версии  2.4.17, то сразу появляется ясная  картина изменений, которые привели к появлению ошибки. Исправление ошибки сводится к обратным изменениям, или другим исправлениям измененного кода.

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

Для  того, чтобы  начать, необходима четко  повторяемая проблема. Желательно, чтобы  проблема проявлялась сразу  же после  загрузки  системы. Далее  необходимо гарантированно работающее ядро.  Вероятно, это  ядро  уже известно. Например, может  оказаться, что пару месяцев назад  ядро  работало  нормально, поэтому  стоит взять  ядро  того времени. Если  это не помогает, то можно  воспользоваться еще более старой  версией. Такой  поиск  ядра  без дефекта  должен  быть не сложным, если, конечно, дефект  не существовал всегда.

Далее, необходимо ядро, в котором гарантированно есть дефект.  Для  облегчения  поиска следует воспользоваться наиболее ранней версией ядра, в которой есть дефект.  После  этого  начинается поиск  исполняемого образа, в котором появилась ошибка. Рассмотрим пример. Допустим, что  последнее ядро, в котором не было ошибки—  2.4.11, а последнее с ошибкой— 2.4.20.  Начинаем с версии  ядра, которая находится посредине— 2.4.15.  Проверяем версию  2.4.15  на наличие ошибки. Если версия  2.4.15  работает, значит  ошибка появилась в более  поздней версии. Следует попробовать версию  между 2.4.15 и 2.4.20, скажем  версию  2.4.17.  С другой  стороны, если версия  2.4.15 не работает, то тогда ясно, что ошибка появилась в более  ранней версии, и следует попробовать версию, скажем  2-4.13.  И так далее.

В конце  концов проблема сужается  до двух ядер — одно  с дефектом, а другое —

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

Такой  подход  избавляет от необходимости проверять ядра  всех версий!

Если ничто не помогает — обратитесь к сообществу

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

Короткое, но достаточно детальное  описание проблемы вместе  с вашими находками, посланное в список рассылки разработчиков ядра по электронной почте, может помочь  отыскать решение. В конце  концов, дефектов никто  не любит.

Глава 20, "Заплаты, разработка и сообщество" специально посвящена сообществу разработчиков ядра и его основному форуму — списку  рассылки разработчиков ядра Linux  (Linux  Kernel  Mail List, LKML).

Переносимость

inux — переносимая операционная  система, которая поддерживает большое количество различных компьютерных аппаратных платформ.  Переносимость—  это свойство,  которое указывает,  насколько  легко  можно   перенести код,  который выполнялся на  одной   аппаратной платформе,  для  выполнения на  другой  аппаратной платформе (если  вообще  это  возможно). Известно, что ОС  Linux является переносимой  операционной системой,  поскольку ее уже  перенесли  (портировали)  па  большое количество  различных аппаратных платформ.  Тем  не  менее  переносимость не  возникает сама  по  себе, для  выполнения она  требует  большого количества  проектных решений.  Сегодня процесс перенесения  ОС  Linux  на  другую  аппаратную платформу достаточно прост  (в относительном смысле, конечно). В этой  главе  рассказывается о том, как  писать  переносимый код, — вопрос, о котором всегда  необходимо помнить

при  написании нового   кода  ядра  или  драйверов устройств.

Некоторые  операционные  системы специально  разрабатываются с учетом  требований  переносимости как  главного свойства. По  возможности минимальное количество  кода  выполняется зависимым от  аппаратуры.  Разработка на  языке   ассемблера сводится к минимуму, а интерфейсы и  свойства выполняются принципиально общими  и  абстрактными,  чтобы  иметь  возможность работать  на  различных аппаратных платформах.  Очевидным  преимуществом  в  этом  случае  является легкость   поддержки  новой  аппаратной платформы. В некоторых случаях  простые операционные  системы   с  высокой  переносимостью  могут  быть  нормированы  на  новую  аппаратную платформу только   путем  изменения  нескольких сотен   строк  специфичного  кода. Недостаток  такого   подхода   состоит   в  том,  что  не  используются  специфические свойства аппаратной платформы  и  код  не  может  быть  в  ручную  оптимизирован под конкретную  машину.  Переносимость ставится выше  оптимальности. Примером операционных систем  с  высокой переносимостью могут  быть  Minix, OpenBSD и многие исследовательские  системы.

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

Операционная  система   Linux  в  плане   переносимости  занимает  промежуточное положение. Насколько это  целесообразно из  практических соображений, интерфейсы  и  код  сохраняются независимыми  от  аппаратной платформы и  пишутся на  языке С.  Однако функции ядра, которые критичны к производительности, выполняются зависимыми от аппаратной платформы. Например, низкоуровневый код и код, который  должен  выполняться очень  быстро,  разрабатывается зависимым  от  аппаратной платформы и  обычно на  языке  ассемблера. Такой  подход  позволяет сохранить переносимость ОС   Linux  и при  этом  воспользоваться оптимизациями.

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

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

Хороший пример — планртровщик. Большая часть планировщика-написана независимым  от аппаратной платформы образом на  языке  С.  Реализация  находится в файле  kernel/sched.с .  Некоторые из  функций  планировщика,  такие  как  переключение  состояния процессора или  переключение адресного пространства,  очень  сильно зависят от аппаратной  платформы.  Следовательно,  функция  context_switc h () , которая  переключает выполнение  от  одного  процесса к  другому  и  написана на  языке С,  вызывает функции  switch_t o  ()   и  Kwitch_ram ()   для  переключения состояния процессора и  переключения  адресного пространства соответственно.

Код  функций  switch_t o () и switch_m m ()   выполнен  отдельно для  каждой   аппаратной  платформы,  которую   поддерживает операционная  система   Linux.   Когда операционная система   Linux  портируется на  новую  аппаратную платформу,  то  для новой  аппаратной платформы просто  необходимо реализовать эти  функции.

Файлы,  которые относятся к  определенной  аппаратной платформе,  находятся в каталоге   arch/<аппаратна я  платформа>/  и  include/asm-<aппapaтнa я  платформа>/, где  <апппаратна я   платформа> — это  короткое имя,  которое представляет аппаратную  платформу,  поддерживаемую ядром   Linux.   Например,  аппаратной платформе Intel  х8б  присвоено имя  i386 .  Для  этого  типа  машин  файлы  находятся в  каталогах arch/i38 6  и   include/asm-i386 .  Ядра  серии   2.6  поддерживают  следующие  аппаратные   платформы:  alpha , arm, cris , h8300 ,  i38, ia64 , m68k, m68knommu, mips , mips64 , parisc , ppc , ppc64 ,  s390, sh,  spare ,  sparc64 ,  um, v850  и  х8б-б4 .  Более полное описание приведено в табл.  19.1.

Источник: Лав,  Роберт. Разработка ядра  Linux, 2-е  издание. : Пер.  с англ.  — М.  : ООО  «И.Д.  Вильяме» 2006. — 448 с. : ил. — Парал. тит. англ.

По теме:

  • Комментарии