LXF73:Вскрываем ядро

Материал из Linuxformat.

Перейти к: навигация, поиск

Содержание

Вскрываем ЯДРО

Знаток ядра Грег Кроа-Хартман (Greg Kroah-Hartman) заглянул внутрь последнего ядра, чтобы показать вам, что заставит ваш ПК работать на полную мощность.

«С технической точки зрения, я верю, что ядро будет сохранять те же черты, а всё действительно интересное будут происходить в пространстве пользователя» Линус Торвальдс (Linux Torvalds), 2001 год.

Несмотря на то, о что думает доброжелательный «хранитель сообщества», ядро Linux демонстрирует, что оно является очень интересной и важной частью системы. На самом нижнем уровне, ядро отвечает за нормальную работу аппаратного обеспечения (того, на что вы, обычно, тратите много денег). Это позволяет вам запускать ваш любимый web-браузер, клиент электронной почты, программу IRC, трехмерную «стрелялку» и т. д., одновременно. Без него не было бы Linux.

С появлением ядер серии 2.6 в конце 2003 года, разработчики ядра предоставили миру предельно стабильную, поддерживающую многопроцессорность операционную систему, работающую быстрее любой другой ОС на широком спектре типов процессоров. Какая еще операционная система может масштабироваться для использования что в крохотном MP3-плеере или встроенном в робота контроллере, что в крупнейших суперкомпьютерах (некоторые с более чем 512 процессорами)? Все это возможно только благодаря самому ядру: остальные компоненты, работающие на более высоких уровнях — лишь надстройки над ним.

«Продвинутые» особенности ядра

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

Ядро 2.6.13 было выпущено 28 августа 2005 года. В него было добавлено около 200 000 новых строк кода, и столько же строк было модифицировано. большинство изменений направлено на исправление ошибок и повышение стабильности; но 2.6.13 также содержит несколько новых и интересных функций, которые могут сделать использование ПК под управлением Linux заметно лучше, причем для каждого.

для разработчиков

Inotify

для такой простой концепции (позволить пользователю знать обо всех изменениях, которые выполняются в файлах), Inotify было уделено достаточно большое внимание. Все сводится к одному инструменту — Beagle. Beagle — это приложение Gnome, которое позволяет вам искать на вашем компьютере практически всё — независимо от типа файла, в любом месте вашей системы. С Beagle вы можете легко находить документы, письма, историю браузера, диалоги IRC и многое другое (см. http://beaglewiki.org).

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

Kexec и Kdump

Функции Kexec и Kdump уже продолжительное время включаются в ядра дистрибутивов, но только сейчас они нашли место в основной ветви ядра. Kexec позволяет пользователям загружать и запускать другое ядро Linux, не требуя перезагрузки работающего ядра в BIOS — благодаря этому экономится много времени при рестарте. Kdump использует эту особенность, чтобы снимать дампы ядра системы в случае краха, позволяя разработчикам потом проводить анализ системы.

Пользователи, которые хотят минимизировать перерыв в работе при обновлении ядра (никто не хочет ждать и изучать сообщения BIOS о повторной проверке шины SCSI) могут использовать Kexec, чтобы свести время простоя к минимуму.

для пользователей

bind и unbind

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

Версия 2.6.13 дает пользователю возможность связывать (bind) отдельные устройства с определенным драйвером и освобождать (unbind) их. Это позволяет администраторам больших систем блокировать отдельные устройства, загрузить новый драйвер и затем связать его с этим устройством, без отсоединения других устройств, которые управляются первоначальным драйвером. Просто представьте себе всю суету, присущую обновлению большой дисковой системы, и вы поймете, что это Вещь с большой буквы.

Devfs мертва

Файловая система devfs отключена с версии 2.6.13. Это было сделано для того, чтобы перед полным удалением devfs дать пользователям, которые все еще используют ее, некоторый «переходный период». Тем, кто до сих пор использует devfs, следует перейти на udev. Может показаться странным, что мы считаем удаление старой неиспользуемой системы шагом вперед, однако правда заключается в том, что devfs довольно отвратительна. Она чрезвычайно раздута, затрудняет чтение кода ядра, и чем раньше мы от нее избавимся, тем лучше.

Улучшенные очереди ввода-вывода

Планировщик ввода-вывода, реализующий алгоритм «Completely Fair Queuing» (полностью справедливая очередь) и являющийся, возможно, лучшим на сегодняшний день, был усовершенствован, чтобы обеспечить более эффективное управление интервалами времени (timeslices). Также в этой области были добавлены два новых системных вызова, позволяющие пользовательским программам изменять приоритеты ввода-вывода различных процессов в системе. Это позволит администраторам более легко подстраивать производительность различных программ.

для встроенных систем

Xtensa

В ядро 2.6.13 была добавлена полностью новая архитектура ЦПУ: Xtensa. Xtensa — это встраиваемый 32-битный процессор, который может быть размещен в SoC-системах с широким спектром встроенных функций - телефоны, PDA, TV-приемники (set-top boxes), MP3-плееры, и прочие подобные устройства.

С этой новой архитектурой Linux теперь поддерживает 24 основных типа процессоров, и еще большее число подтипов. Хорошая новость для встроенных устройств. На заметку тем, кто любит хвастаться - Linux поддерживает больше различных процессоров, чем любая другая операционная система (пожалуй, NetBSD может составить ему конкуренцию в этой области, — прим. ред.). добавьте этот факт к тому, что Linux поддерживает больше внешних устройств, чем любая другая ОС, и станет понятно, почему Linux считается наиболее гибким и мощным ядром.

Выполнить «на месте»

Файловая система ext2 теперь позволяет программам исполняться «на месте» (inplace) вместо предварительной загрузки в оперативную память. Это очень полезно на встроенных системах, которые имеют ограниченный объем ОЗУ, но большой объем ПЗУ или Flash-памяти — таких как мобильные телефоны.

Регулируемая частота

Мы установили частоту прерываний ядра 2.6 на уровне 1000 Гц, что порождало некоторые жалобы от пользователей. Теперь эта частота может быть установлена на этапе компиляции в три различных значения, в зависимости от того, как именно будет использоваться компьютер:

  • 100 Гц. Это лучшее решение для маломощных устройств.
  • 200 Гц. Идеально для серверов.
  • 1000 Гц. Оптимально для настольных систем, или других систем, требующих быстрой, интерактивной реакции на события.
«Добровольно-вытесняющая» многозадачность

Те пользователи, кто чувствовал себя некомфортно с ядром, реализующим вытесняющую многозадачность (full pre-emption), теперь получили другую опцию: «добровольно-вытесняющую» многозадачность (voluntary pre-emption). Она позволяет ядру прерывать процессы в ряде известных «точек явного прерывания» (explicit preemption points), которые выбираются таким образом, чтобы уменьшить латентность перепланировки различных программ. Приложения получают более низкое время отклика, хотя это достигается за счет некоторого снижения производительности.

а что Же 2.6.14 ?

Последняя версия ядра – 2.6.14, выпущенная в конце октября этого года, содержит ряд интересных функций, как то:

  • relayfs

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

Relayfs была разработана, чтобы решить эту проблему, и ряд внешних проектов пользуется ею в течение продолжительного времени, чтобы по возможности решить проблемы передачи данных. Один из них – Linux Trace Toolkit, и теперь, когда эта функция добавлена в основное дерево ядра, LTT станет немного ближе к признанию.

  • Драйвера ipw2100 и ipw2200

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

  • Сетевой протокол DCCP

Несмотря на то, что Linux уже поддерживает достаточное количество сетевых протоколов, в него был добавлен еще один. Этот протокол настолько новый, что 2.6.14 – это первое ядро, которое действительно будет использоваться для его тестирования в реальных условиях. DCCP расшифровывается как Datagram Congestion Control Protocol – протокол управления массивами датаграмм, и он во многом похож на существующий протокол UDP, но имеет несколько важных отличий. Подробности о нем смотрите на странице http://www.icir.org/kohler/dcp/draft-ietfdccp-spec-11.txt.

  • Удаление базы данных идентификаторов PCI

В предыдущих выпусках каждое ядро содержало список строк, описывающих все возможные устройства PCI, которые существуют в мире. Это делалось лишь для того, чтобы некоторые файлы в директории /proc выглядели красиво, но эта красота отнимала много места. Этот файл был удален, так что память ядра, которую он занимал, теперь можно использовать с большей пользой. для тех пользователей, кто действительно хочет иметь красивые имена, эта таблица доступна через lspci.

  • Система защиты жесткого диска для ThinkPad

Новые ноутбуки ThinkPad от IBM/Lenovo содержат детектор малых перемещений, который может определить, когда ноутбук соскользнет со стола и близок к тому, чтобы упасть на землю. если устройство обнаружит, что ноутбук падает, оно быстро выключает диск, чтобы помочь предотвратить любые неприятности, связанные с потерей данных.

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

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

  • FUSE

Наконец, теперь возможно создавать файловую систему в пространстве пользователя, используя любой язык программирования на ваш вкус (кто-нибудь хочет сделать это на Python?). Fuse позволяет экспортировать внутреннюю виртуальную файловую систему ядра в пространство пользователя, чтобы каждый мог работать с ней. С использованием Fuse уже написан ряд файловых систем, работающих в пользовательском пространстве, включая системы SSH и tar. Посетите основную страницу разработки Fuse http://fuse.sourceforge.net

как и в случае со всеми новыми функциями, предоставляемыми очередными версиями ядра, вам нужно активировать эту функцию и пересобрать ваше ядро, чтобы все работало как нужно. Получить дополнительную информацию о компиляции, установке и загрузке нового ядра вы сможете на странице с прекрасным руководством HOWTO по сборке ядра: http://www.digitalherait.com/linux/Kernel-Build-hOWTO.html.

Начнем, пожалуй

Вашим программистским пальцам не терпится начать? Углубимся в новое ядро и рассмотрим две самые замечательные функции.

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

Ну что ж, начнем: если вы хотя бы в общих чертах разбираетесь в языке C, вы можете «сразиться» с Inotify, изучив новые функции ядра для добавления и удаления точек слежения (watches) за файлами.

Если же вы не настолько бесстрашны, читайте врезку «Привязка драйверов вручную», чтобы узнать, как можно настроить драйвер, чтобы он автоматически подгружался при подключении устройств типа USB Flash.

Привязка драйверов вручную – использование функций bind и unbind

Приведем пример того, как использовать новые функции bind и unbind ядра 2.6.13. Вам потребуется flash-диск USB, или любое другое устройство, управляемое драйвером usb-storage. Прежде всего, пересоберите ядро (см. ссылку в конце предыдущей страницы) с поддержкой драйверов CONFIG_BLK_DEV_UB и CONFIG_USB_STORAGE (вы можете собрать их оба как модули, а можете включить в основную часть ядра).

Когда вы загрузите новое ядро, подключите ваш flash-диск USB. Поскольку драйвер ub будет найден первым в пути загрузки ядра, он будет связан с вашим устройством. Это можно увидеть в каталоге /sys/bus/usb/drivers/ub:

$ tree /sys/bus/usb/drivers/ub//sys/bus/usb/drivers/ub/
|-- 1-1:1.0 -> ../../../../devices/pci0000:00/
0000:00:1d.7/usb1/1-1/1-1:1.0
|-- bind
|-- module -> ../../../../module/ub
`-- unbind

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

echo -n "1-1:1.0" > /sys/bus/usb/drivers/ub/unbind

Устройство больше не связано с драйвером.

$ tree /sys/bus/usb/drivers/ub/
/sys/bus/usb/drivers/ub/
|-- bind
|-- module -> ../../../../module/ub
`-- unbind

Чтобы связать это устройство с другим драйвером, сначала убедитесь, что оно не управляется чем-либо еще. Чтобы проверить это, поищите символическую ссылку на драйвер в каталоге устройства:

$ tree /sys/bus/usb/devices/1-1:1.0
/sys/bus/usb/devices/1-1:1.0
|-- bAlternateSetting
|-- bInterfaceClass
|-- bInterface Protocol
|-- bInterfaceSubClass
|-- bNumEndpoints
|-- bus -> ../../../../../../bus/usb
|-- modalias
`-- power
  `-- state

Затем просто запишите идентификатор шины (bus ID) устройства, которое вы хотите связать, в файл bind для нужного драйвера:

echo -n "1-1:1.0" > /sys/bus/usb/drivers/usbstorage/bind

И проверьте, что привязка прошла успешно:

$ tree /sys/bus/usb/devices/1-1:1.0
/sys/bus/usb/devices/1-1:1.0
|-- bAlternateSetting
|-- bInterfaceClass
|-- bInterfaceNumber
|-- bInterfaceProtocol
|-- bInterfaceSubClass
|-- bNumberEndpoints
|-- bus -> ../../../../../../../bus/usb
|-- driver -> ../../../../../../bus/usb/drivers/usb-storage
|-- host2
| `-- power
|   `-- state
|-- modalias
`-- power
  `-- state

Чтобы успешно связать некоторое устройство с драйвером, последний должен распознавать данное устройство. Поэтому вы не можете просто произвольно связать любой драйвер с любым устройством. Чтобы было проще добавлять поддержку нового устройства в драйвер уже после его сборки, система PCI предлагает файл dynamic_id в sysfs, так что идентификатор нового устройства, к которому следует привязать тот или иной драйвер, можно задать из пространства пользователя.

Внутри Inotify

Функция Inotify добавляет три новых системных вызова:

int inotify_init(void);
int inotify_add_watch(int fd, const char
*path, __u32 mask);
int inotify_rm_watch(int fd, __u32 mask);

Выступая как замена для Dnotify, Inotify работает с сущностями, называемыми точками слежения (watch). Watch — это пара «объект-маска», которая описывает событие, о наступлении которого пользователь хотел бы получать уведомления. Объект — это файл или каталог (представлен дескриптором открытого файла), а маска — битовое описание событий. Р азличные типы событий, которые можно отслеживать, приведены ниже:

  • IN_ACCESS: к файлу был доступ;
  • IN_MODIFY: файл был изменен;
  • IN_ATTRIB: были изменены метаданные файла;
  • IN_CLOSE_WRITE: файл был закрыт с записью всех изменений;
  • IN_CLOSE_NOWRITE: файл был закрыт без записи изменений;
  • IN_OPEN: файл был открыт;
  • IN_MOVED_FROM: файл был перемещен из положения X;
  • IN_MOVED_TO: файл был перемещен в положение Y;
  • IN_CREATE: файл в каталоге был создан;
  • IN_DELETE: файл в каталоге был удален;
  • IN_DELETE_SELF: объект наблюдения был удален.

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

Чтобы создать точку слежения и зарегистрировать ее в ядре, нужно получить дескриптор с помощью вызова функции inotify_init(), например, так:

int fd = inotify_init();

Затем, используя этот новый файловый дескриптор, вы можете добавить watch к нему, используя функцию inotify_add_watch():

int wd = inotify_add_watch(fd, path, mask);

где fd — дескриптор, возвращенный функцией inotify_init(); path — путь к файлу или каталогу, за которым вы хотели бы наблюдать; и mask — тип события, которое вы будете отслеживать.

Функция inotify_add_watch() возвращает указатель на дескриптор watch, который должен быть сохранен, чтобы правильно выполнить очистку.

Чтобы удалить точку слежения, которая уже создана, используйте функцию inotify_rm_watch():

int retval = inotify_rm_watch(fd, wd);

где fd — первоначальный файловый дескриптор, возвращенный inotify_init(), и wd — дескриптор watch, возвращенный при вызове inotify_add_watch().

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

Структура данных, которые могут быть получены от ядра, описывается следующим кодом на C:

struct inotify_event {
__s32 wd; /* дескриптор точки слежения */
__u32 mask; /* маска */
__u32 cookie; /* cookie для синхронизации событий */
__u32 len; /* длинна имени (с завершающим нулем) */
char name[0]; /* место для размещения имени */
};
за кадром

Чтобы узнать больше о решениях по структуре ядра, через которые прошли разработчики Inotify, создавая эту систему, смотрите документацию по Inotify в файле Documentation/filesystems/inotify.txt.

Названия полей говорят сами за себя, за исключением поля cookie. если это поле имеет ненулевое значение, это значит, что для данного объекта возникло несколько событий одновременно. В качестве примера можно привести переименование файла. если мы будем наблюдать за каталогом, в котором будет переименован файл (mv foo baz), произойдут два события: IN_MOVE_FROM и IN_MOVE_TO. Оба они будут иметь одинаковое значение cookie, что позволит пользовательской программе скоординировать эти события.

Файловый дескриптор, возвращаемый inotify_init(), позволяет использовать вызовы select() и poll(), так что блокирующий вызов read() не является необходимым.

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

В качестве очень простого примера программы, который показывает, как регистрировать события и читать их по мере наступления, посмотрите пакет inotify-utils, который можно найти на странице http://www.kernel.org/pub/linux/kernel/people/rml/inotify/utils.

Поиски стабильности

Лоскутные заплатки, «горячие» исправления, два дерева становятся одним… Как процесс разработки ядра изменился в лучшую сторону за последние пять лет.

«Проблема, существующая в настоящее время, заключается в том, я думаю, что качество ядра не настолько высоко, как должно быть. В каждом очередной версии мы довольно часто откатываемся назад из-за новых ошибок». Эндрю Мортон (Andrew Morton), OSDL, август 2005 г.

До того, как было выпущено ядро 2.6, было достаточно легко определить, какая ветвь разработки ядра была стабильной, а какая — экспериментальной: вторая цифра в номере версии говорила обо всем. Четные номера были стабильными, нечетные — экспериментальными, то есть ветви 2.0, 2.2 и 2.4 были стабильными, а 2.1, 2.3 и 2.5 — для разработчиков. Каждая ветвь имела свои индивидуальные выпуски: например, 2.4.12 и 2.4.13 — это различные выпуски в рамках ветви 2.4.

Все это изменилось: теперь есть только одна ветвь — ветвь 2.6.

Путаница с обратным портированием

Раньше, в процессе разработки ветки 2.5 (с конца 2001 до 2003 года), в экспериментальное ядро был добавлен ряд важных изменений. Эти изменения были столь хороши, что как пользователи, так и дистрибьюторы в равной степени хотели их использовать, даже учитывая, что ядро было все еще нестабильно (то есть имело нечетный номер 2.5).

Крупные поставщики дистрибутивов поручили своим инженерам портировать эти функции в свои, основанные на ветви 2.4, ядра. Поставщикам приложений нужно было теперь определять, какие новые особенности стали доступны в этих «самописных» ядрах.

Проблема возникла, когда пользователи этих дистрибутивов оказались вынуждены доверять своим дистрибьюторам поддержку «лоскутных» ядер, поскольку сообщество разработчиков не желало ничего делать с ними. Спустя некоторое время такая поддержка стала очень сложной задачей и превратилась в настоящий инженерный кошмар (просто сравните деревья исходных кодов ядер Red Hat Enterprise Linux 3 и SUSE Linux Enterprise Server 8 с деревом kernel.org, на котором они основаны).

Спустя почти год с момента разработки серии ядер 2.6, разработчики ядра Linux встретились, чтобы обсудить, что они хотели бы сделать для следующей экспериментальной серии (2.7).

Оказывается, все разработчики в действительности хотели бы оставить все как есть, и не желали столкнуться с такой же проблемой, как путаница с обратным портированием в ядре 2.4, которая, между прочим, «помогла» растянуть цикл разработки 2.6 более чем на два года.

Когда они собрались за круглым столом и посмотрели, как работает ядро 2.6, они решили оставить его единственной ветвью и объявить, что это будет одновременно и стабильное, и экспериментальное ядро.

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

Девять правил разработки стабильного ядра

Правила, принятые для стабильной ветки ядра, совершенно просты:

  1. Изменение должно быть, очевидным, корректным и протестированным.
  2. Изменение не должно занимать более 100 строк, включая контекст.
  3. Изменение должно исправлять лишь что-то одно.
  4. Изменение должно исправлять реальную ошибку, которая беспокоит людей (а не потенциальную ошибку, которая пока еще никому не мешала).
  5. Изменение должно исправлять проблему, которая вызывает ошибку компиляции, зависание, повреждение данных, реальные проблемы безопасности или проблемы из разряда «о, это совсем нехорошо». К ороче, это должно быть что-то критическое.
  6. Не нужно исправлять проблемы типа «теоретическое состояние гонки (race condition)» до тех пор, пока не будет объяснения, как гонка может возникнуть.
  7. Изменение не должно содержать тривиальных исправлений (исправление орфографии, удаление пробелов и т.д.).
  8. Изменение должно быть принято старшим разработчиком соответствующей подсистемы.
  9. Изменение должно следовать нормальным правилам, по которым исправления вносятся в ядро (как это описано в файле Documentation/SubmittingPatches в дереве исходного кода ядра).

Стабильное (-stable) дерево ядра также проходит цикл публичного просмотра, который начинается, когда разработчики решат, что для новой версии накопилось уже достаточно исправлений. Все потенциальные изменения публикуются в списке рассылки, посвященном ядру Linux, и отправляются отдельным разработчикам ядра, ответственным за область, которую это изменение затрагивает. Должно пройти, по крайней мере, 48 часов, чтобы любой разработчик мог обжаловать любое отдельное изменение. Как только это время истечет, и никто не подаст возражений, новое стабильное ядро выпускается.

устаревшие…

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

Чтобы обойти эту проблему, была создана «стабильная» (-stable) ветвь версий ядра со следующей идеей: двое разработчиков каждые две недели (или около того) подготавливают небольшой выпуск ядра и ничего не добавляют, кроме очевидных исправлений ошибок и проблем безопасности. Эти выпуски маркировались четвертым символом в номере версии, которые теперь имели формат «2.6.X.Y», где Y — номер стабильной версии ядра. Например, ядро 2.6.13.1 — это первый «стабильный» выпуск на ветви 2.6.13.

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

Все это было замечательно, но промежуток между стабильными версиями ядра, казалось, все возрастал. Потребовался один месяц, чтобы пройти путь от 2.6.1 до 2.6.2, но теперь мы должны ждать почти четыре месяца между версиями. кроме того, не похоже, чтобы кто-то действительно тестировал промежуточные версии «кандидатов в релиз» (release candidate), которые выпускались между основными выпусками.

кое-что изменилось. Вот как выглядит этот процесс сейчас: в первую неделю после выхода ядра все ответственные разработчики различных подсистем подают свои основные изменения для объединения. Это могут быть новые функции, исправления ошибок или переписанные секции кода. После этого выпускается настоящий «release candidate», и все разработчики усаживаются и работают над приданием выпуску стабильности. Ошибки отслеживаются на сайте http://bugzilla.kernel.org, а разработчикам временно запрещается добавлять новые функции. В течение следующих нескольких недель ядро становится достаточно стабильным, чтобы выпустить его в свет, и весь цикл начинается сначала. По идее, это должно сохранять короткий цикл разработки и обеспечивать лучшее выявление любых возможных ошибок.

ПроЩаЙ, BITKEEPEr! доброе утро, gIT!

Во время создания ядра 2.5 разработчики выбрали инструмент управления исходным кодом, называемый BitKeeper. Эта программа предоставляла распределенный способ обработки изменений и дерева ядра, присущий традиционным системам контроля версий (подобным CVS или Subversion) и была создана специально для нужд разработчиков ядра.

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

Прежде ядро совершенствовалось путем отправки отдельных изменений по электронной почте Линусу Торвальдсу (Linus Torvalds), главному идеологу и разработчику. Он применял некоторые из них к своей копии ядра, и каждую пару недель (или около того) публиковал экспериментальную версию. Это означало, что отдельные разработчики должны были ждать относительно долгое время, чтобы увидеть, были ли приняты их наработки, и какие еще изменения произошли за это время.

Этот механизм работал достаточно хорошо первые десять лет, но по мере разрастания ядра обнаружил определенные проблемы. когда BitKeeper начал использоваться некоторыми разработчиками ядра, произошло два важных события: 1) появились моментальные снимки (snapshots) состояния ядра Торвальдса, и 2) каждое индивидуальное изменение отправлялось в список рассылки, включая описание причин, по которым это изменение было сделано.

Подобное изменение не было чем-то новым для многих других открытых проектов, которые использовали CVS («добро пожаловать в девяностые!»), но для ядра это было радикальное новшество. В вопросе соблюдения соответствующих правил, по которым изменения должны приниматься, Торвальдс больше не просматривал каждое отдельное изменение, а положился на разработчиков, руководивших развитием отдельных подсистем ядра.

Отказ от BitKeeper

В конечном счете, все люди, жаловавшиеся на то, что BitKeeper являлся закрытой программой, оказались правы, когда BitMover – компания, стоящая за BitKeeper – решила остановить его бесплатное использование разработчиками. Те прекратили вообще всю работу, и искали инструмент, который мог бы удовлетворить их потребности. Они не нашли ничего подходящего, так что Торвальдс решил написать собственный инструмент, который он назвал Git. Git – это система управления распределенным исходным кодом, которая работает подобно BitKeeper, но ориентирована в точности на процесс разработки ядра Linux. Она имеет следующие характеристики:

  • Обеспечивает полностью распределенную разработку (нет центрального сервера, как в CVS или Subversion).
  • Может применять изменения более быстро.
  • Способна выдержать большой объем дерева исходного кода ядра и количество изменений (вопреки другим крупным open-source проектам, темп разработки ядра Linux растет по мере увеличения кодовой базы).

Поскольку Git имел несколько загадочный интерфейс командной строки, появился ряд программ-оболочек, призванных помочь в использовании Git (например, Gogito). Со времени выпуска ядра 2.6.12-rc2, разработчики ядра используют Git без каких-либо претензий. более подробную информацию о том, как получить и использовать Git, вы найдете на http://www.kernel.org/git.

Взгляд в будущее

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

Раньше разработчики ядра Linux искали обходной путь, когда создавались модули с недоступным для них исходным кодом. Но в последние годы все изменилось. Теперь существует три способа, которыми разработчики ядра разрешают такие ситуации.

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

Почти все новые функции ядра явно помечаются компилятором как доступные только из открытого GPL-кода. Этот подход запрещает любому модулю с закрытым кодом использовать их интерфейсы, и постепенно будет «душить» все их функциональные возможности. Хороший пример этого - базовые интерфейсы для драйверов и sysfs, которые недоступны для модулей с закрытым кодом.

буква закона

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

Теперь перейдем к третьему средству сдерживания. Основные претензии по поводу процесса разработки ядра предъявлялись производителями драйверов, являвшимися внешними по отношению к дереву исходного кода ядра и содержащими проприетарные наработки — такими, например, как NVIDIA.

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

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

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

Чтобы узнать подробное описание причин, по которым Linux не может сохранять стабильный интерфейс ядра, прочитайте документ http://lxr.linux.no/source/Documentation/stable_api_nonsense.txt.

Появится ли когда-либо 2.7?

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

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

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

ПрисоединяЙтесь!

Вы хотите помочь в разработке ядра, но не знаете, с чего начать? если вы хорошо понимаете язык C и знаете, как собирать и устанавливать собственное ядро, попробуйте посмотреть проект Kernel Janitors на http://janitor.kernelnewbies.org. Он содержит список простых проектов для начинающих разработчиков, которые только осваивают работу с ядром. Список рассылки проекта поможет вам выяснить соответствующую процедуру и формат для создания изменений и отправки их на включение в ядро.

для разработчиков, которым нужен “легкий толчок” в правильном направлении, существует проект Kernel Mentor (http://selenic.com/mailman/listinfo/kernel-mentors). Он поможет разработчикам изучить соответствующие «правила движения», которые нужно соблюдать для «заливки» изменений в основное дерево кода ядра.

И если вы непременно желаете делать все самостоятельно, вам следует начать с чтения руководства по коду ядра Linux на http://lxr.linux.no/source/Documentation/CodingStyle... Затем посмотрите ссылки о том, как отправляются отдельные изменения (http://lxr.linux.no/source/Documentation/SubmittingPatches) и целые новые драйвера (http://lxr.linux.no/source/Documentation/SubmittingDrivers).

Личные инструменты
  • Купить электронную версию
  • Подписаться на бумажную версию