Готовый перевод Linux Device Drivers 3 / Драйверы устройств Линукс (третье издание): Глава 1. Драйвера устройств - введение

Внимание! Этот перевод, возможно, ещё не готов, так как модераторы установили для него статус «перевод редактируется»

Драйверы устройств - вводная глава

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

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

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

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

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

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

Роль драйверов устройств

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

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

На пример, управление Unix графическим дисплеем разделяются между Х-сервером, который знаком с аппаратным обеспечением и поддерживает единый интерфейс пользователя программ, а также окна и менеджеры сессий, которые осуществляют особенную политику не зная ничего о аппаратном обеспечении. Люди могут использовать один и тот же оконный менеджер на разном аппаратном обеспечении, и различные пользователи могут запускать различные конфигурации на одной и той же рабочей станции. Даже совершенно разное рабочее окружение, такие как KDE и GNOME, могут сосуществовать в одной и той же системе. Другой пример — структурная расслоение сетевого протокола TCP/IP: операционная система предлагает сокетную абстракцию, которая выполняет без установки рассмотрение переданных данных, в то время как различные серверы управляют сервисами (и их ассоциированными политиками). Более того, сервер такой как ftpd обеспечивает механизм перемещения файлов, тогда когда пользователь может использовать все что предпочтут его клиенты, и командная строка и графический клиенты сосуществуют и любой может написать новый интерфейс для перемещения файлов.

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

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

На драйвер можно смотреть с разных точек зрения: это слой программного обеспечения который лежит между приложениями и подлинным устройством. Эта преимущественная роль драйверов позволяет программистам выбирать как устройство будет представлено: различные драйвера могут предложить различные возможности, даже для одного и того же устройства. Целью современного драйвера должен быть баланс между многими различными точками зрения. Для примера, отдельное устройство может быть использовано совместно различными программами и программисты драйверов имеют полную свободу определяя как поддерживать эти соглашения. Вы можете осуществлять отображение памяти на устройстве независимо от возможностей аппаратного обеспечения или можете обеспечивать пользовательскую библиотеку для помощи программистам приложений осуществляя новые политики на вершине доступных примитивов и так далее и тому подобное. Одно из главных соображений при продаже драйвера: приходится выбирать между сильным желанием представить пользователю как можно больше возможностей, и временем отведенным на его написание, также требуется сохранить простоту чтобы не запутать пользователя.

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

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

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

Внутреннее устройство ядра

В Unix системе, несколько действующих одновременно процессов обслуживающих различные задачи. Каждый процесс запрашивает ресурсы системы, будь то управление компьютером, памяти, сетевых соединений или некоторые другие ресурсы. Ядро это большой кусок выполняемого кода обеспечивающих все эти запросы. Хотя различие между различными задачами ядра не всегда ясно выражены, роль ядра, тем не менее, их можно разделить на следующие части: (смотрите на рисунок 1-1)

Управление процессами.

Ядро отвечает за создание и уничтожение процессов и управляет их соединением со внешним миром (ввод и вывод). Связь между различными процессами (через сигналы, «радиаторы — pipes- пипес» или межпроцессорные связывающие примитивы) - основа полнофункциональной системы, также управляется ядром. В дополнение, список, который контролирует какому процессу будет доступен процессор, часть управления процессов. В более широком смысле, управление процессами ядра активно осуществляется абстракцией о нескольких процессах которые обращаются к процессору или нескольким.

Управление памятью.

Компьютерная память главный ресурс и используемая политика её распределения критическая проблема выполняемая системой. Ядро построено на виртуальном адресном пространстве для любого и всех процессов на пике проблема ограничения доступный ресурсов. Различные части ядра взаимодействуют с подсистемой управления памятью посредством функциональных вызовов, классификация из простых «занято\свободно» пары в комплексе намного более функциональны.

Файловые системы.

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

Контроль устройств.

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

Сетевая работа.

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

Загружаемые модули.

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

Каждый кусок кода, который добавляется во время работы ядра, называется модулем. Ядро Линукс предлагает поддержку для достаточно немногих различных типов (или классов) модулей, включая, но не ограничивая, драйверы устройств. Каждый модуль переделывает объект кода (не связанные в полностью исполняемый комплекс ) это может быть динамичное связывание во время работы ядра «внутреннего модуля (insmod)» программы и могут быть не связанные «удаленного модуля (rmmod)???» программы.

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

Классы устройств и модулей.

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

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

Символьное устройство может быть доступно как поток байтов (такие как файлы); символьный драйвер заведует выполнением этой работы. Так драйвер обычно выполняет как минимум открытие, закрытие, чтение и запись системных вызовов. Текстовая консоль (/dev/console) и последовательный порт (/dev/ttySO и друзья) пример символьных устройств, хорошо объясняют абстракцию потока. Символьное устройство доступно через узел файловой системы, такие как /dev/tty1 и /dev/lp0. Есть только одно различие между файлом и символьным устройством; в файле как правило данные перемещаются в двух направлениях: ввод — запись и вывод — чтение, в символьном устройстве как правило направление одно: поток ввода. Тем не менее, вне всякого сомнения, символьные устройства могут перемещать данные в двух направлениях, например, при сооружении граббера, где приложениям будут доступны все купленные изображения посредством утилит mmap или lseek.

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

Как и символьные устройства, блочные доступны через узел в файловой системе в /dev директории. Блочные устройства это устройства (такие как диски) которые могут содержатся в файловой системе. В большинстве Unix системах, блочные устройства, могут только руководить операциями ввода\вывод которые перемещать один или больше целых блоков, размер которых обычно 512 байтов (или еще больше в зависимости от возможностей в каждом отдельном случае) в длину. Линукс, вместо того чтобы, разрешать приложениям чтение и запись как в случае блочного устройства у символьных он просто пропускает любое количества байтов за раз (время). В результате, блочные и символьные устройства различаются только в направлении куда перемещаются данные под внутренним управлением ядра и также программным интерфейсом ядро\драйвер. Как и символьное устройство, каждое блочное устройство доступно через узел файловой системы и различия между ними в явно пользователь. Блочный драйвер полностью отличается от символьного интерфейсом взаимодействующим с ядром.

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

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

Не будучи потоково ориентированным устройством, сетевой интерфейс не проще(?) отображен как узле в файловой системе, как /dev/tty1. Unix обеспечивает доступ к интерфейсу назначая постоянное и уникальное имя для него (на пример eth0), но это имя не соответствует узлу в файловой системе (/dev/tty02). Связь между ядром и драйвером сетевого устройства полностью отличается от того как это осуществляется в символьных и блочных драйверах. Вместо чтения и записи, ядро вызывает функционально связанную передачу пакета.

С другой стороны классификация модулей драйверов противоположность в основном типам устройств. Обычно, несколько типов драйверов работают с добавлением слоев функций поддержки ядра, которые дают типы устройств. На пример, один может переговариваться с универсальной последовательной шиной (USB), модули последовательного порта, SCSI модули и так далее. Каждое USB устройство управляется модулем который работает с подсистемой USB, но устройство представлено в системе как символьное устройство (последовательный порт USB микрофон), блочное устройство (USB картридер), или сетевое устройство (USB сетевой интерфейс).

Другие классы драйверов устройств добавляются в ядро в последний момент, включая FireWire и I2O драйвера. В тоже время они управляют USB и SCSI драйверами, разработчики ядра собрали широкий класс особенностей и экспортировали их в инструментарий драйверов во избежание двойной работы и ошибок, эта упрощает и делает более строгим процесс написания таких драйверов.

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

Если вы поймете как строго Unix система зависит от основной файловой системой, вы поймете какая программная концепция жизненно важна для этой операционной системы. Способность декодировать информации в файловой системе на самом низком уровне ядра иерархически и предельно важно, даже если вы пишите блочный драйвер для вашего нового CD-ROMa это бесполезно если вы не сможете запустить ls и cp для данных этих хостов. Линукс поддерживает концепцию модулей файловой системы, этот программный интерфейс объявляет различные операции которые могут быть сделаны узды, директории, файлы и суперблоки файловой системы. Это достаточно необычно для программиста фактически необходимо писать модули файловой системы, потому что официальное ядро уже включает код для большинства типов файловых систем.

Вопросы безопасности

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

Любая проверка безопасности в системе вынуждается кодом ядра. Если в ядре есть «уязвимость» в безопасности, тогда и система в целом «уязвимая». В официальном дистрибутиве ядра, только авторизированный пользователь может загрузить модуль, системный вызов init_module проверяется если вызываемый процесс идентифицирован в системе тогда модуль загружается в ядро. Так когда запускается служебное ядро, только суперпользователь или человек который сменил при входе свои права, может взяться за управление привилегированного кода.

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

[1] Технически, только кто-то с правами доступа CAP_SYS_MODULE может выполнять эту операцию. Права доступа мы рассмотрим в шестой главе.

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

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

Есть несколько других подходов, которых стоит придерживаться. Любой полученный ввод информации от процесса пользователя должен быть обработан с огромным подозрением, ни когда не надейтесь на него пока не проверите все. Будьте внимательны с не инициированной памятью, любая память достигает ядра должна быть обнулена или другим образом про инициирована до того как будет доступна для пользовательского процесса или устройства. Иначе, результатом может быть оказаться утечка информации (обнаружение информации, паролей и т.д.). Если ваше устройство интерпретирует отправку данных к ядру, вы должны быть уверены что пользователь не может послать ничего что может причинить вред системе. Наконец, подумайте о возможных результатах от операций устройства; если есть какие-то особенные операции (на пример, перезагрузка фирменного программного обеспечения на соединительном устройстве или форматирование диска) которые могут воздействовать на систему, то они должны непременно ограничиваться правами пользователя.

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

Помните что ядро Линукс может быть откомпилированы без поддержки модуля, так закрытие любого связанного модуля может оказаться «уязвимостью» в безопасности. В этом дело, конечно, все необходимые драйвера должны бить построены прямо в ядре. Это тоже возможно, с ядром 2.2 и более поздних издательствах ядра, запрещая загрузку модулей ядра, после того как система загрузится через возможный механизм.

Нумерация версий

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

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

Запускайте примеры которые мы вводим во время обсуждения, вам не понадобится какая-то особенная версия для каждого инструмента , кроме тех что требует ядро 2.6. Мы не рассматриваем детально особенности запросов, потому что файл Documentation/Changes в ваших исходниках ядра, при возникновении любой проблемы, лучший источник информации такой информации.

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

Эта книга описывает версию ядра 2.6. Мы фокусируемся на показе всех особенностей доступных для авторов драйверов устройств версии 2.6.10, текущая версия в то время как мы писали эту книгу. Это издательство не покрывает прежние версии ядра. Для тех кто интересуется ними есть второе издательство которое покрывает версии 2.0 до 2.4 в деталях. Это издательство ядра постоянно доступно в сети по адресу: http://lwn.net/Kernel/LDD2/.

Программисты ядра, должны знать как изменился процесс разработки в ядре 2.6. Изменения, которые были внесены в версию 2.6, которые предварительно рассматриваются слишком большие для «стабильного» ядра. Между тем, это значит что программирование внутренних интерфейсов ядра могут измениться, по этой причине некоторые части книги могут оказаться устаревшими, примеры кода сопровождающий текст работают с ядром 2.6.10, и некоторые модули не компилировались под более ранними версиями. Программисты которые захотят внести программные изменения в ядро, будут взбодрены увидев списки рассылки и использовав веб сайты список которых также есть в библиографии. Мы также поддерживаем веб страницу http://lwn.net/Articles/2.6-kernel-api/, которая содержит информацию об изменениях в API которые произошли с момента издательства книги.

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

Другая особенность Линукс, что это платформо независимая операционная среда, а не только «клон unix для клонов PC» и больше ничего: на текущий момент он (Линукс) поддерживает более двадцати архитектур. Эта книга независит от платформы настолько насколько это возможно, и все примеры кода прошли тест на последних х86 и х86-64 платформах. Потому что примеры кода прошли тест и на 32-битных и 64-битных процессорах, и могут быть откомпилированы и запущены на других платформах. Как вы можете подумать, примеры кода действительно не работают с некоторыми частными устройствами на всех поддерживаемых платформах, но это проблема всегда начинается с исходного кода.

Лицензионные термины

Линукс лицензирован под Второй версией ГНУ (GNU) Общей публичной лицензией (GPL), документ был задуман для ГНУ проекта Фонда Свободного Программного Обеспечения. GPL лицензия позволяет любому перераспределять и даже продавать, продукт под лицензией GPL, до тех пор пока получатель имеет доступ и исходным кодам, и разрешено использовать на тех же правах. Дополнительно, любой программный продукт полученный из продукта под лицензией GPL должен, если перераспределен во всем, должен выпускаться под лицензией GPL.

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

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

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

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

Насколько я знаю эту книгу, большинство кода распространяется свободно, или исходные или бинарные файлы и никто из издательства не удерживает ни каких прав ни на какую полученную работу. Все программы доступны по адресу: ftp://ftp.ora.com/pub/examples/linux/drivers/, и правильная лицензия установлена в файле LICENSE в текущей директории.

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

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

Главное место встречи разработчиков ядра Линукс список рассылки linux-kernel. Все главные разработчики ядра, следом за Линусом Торвалдсом, подписаны в этом листе. Пожалуйста помните, что лист рассылки не для слабых сердец: трафик записей может бежать более 200 сообщений за день или больше. Тем не менее, этот лист ценен для тех кто интересуется разработкой ядра, а также может быть высококачественным ресурсом для тех кто нуждается в помощи в разработке ядра.

Чтобы вступить в список linux-kernel, следуйте инструкциям, которые найдете в FAQ списка рассылки linux-kernel: http://www.tux.org/ikml

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

Обзор книги

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

Техники отладки - эти жизненно важные инструменты для программиста представлены в Главе 4. В равной степени важно, для тех кто исследует согласованность управления современных ядер и пути улучшения. Глава 5 касается сама по себе с изложенными проблемами совместного доступа к ресурсам и вводит в механизмы Линукс по контролю совместимости.

Получив навыки отладки и управления совместимости мы переходим продвинутым возможностям символьных устройств, таким как блокирующие операции, использование системного вызова select, и важного ioctl вызова, эти темы предмет рассмотрения Главы 6.

Прежде чем вести дело с управлением аппаратного обеспечения мы анализируем немного больше программных интерфейсов ядра: Глава 7 показывает как время управляет ядром и Глава 8 объясняет распределение памяти.

Далее мы с фокусируемся над аппаратным обеспечением. Глава 9 описывает управление портами ввода\вывода и буферов памяти которые существуют в устройстве, после этого мы подходим к управлению прерываниями, в Главе 10. К сожалению, не каждый сможет запустить примеры кода в этой главе, потому что поддержка некоторого аппаратного обеспечения действительно необходимо для тестирования интерфейса прерываний. Мы попытались свести к минимуму поддержку аппаратного обеспечения, тем не менее вам понадобится простое аппаратное обеспечение, такое как стандартный параллельный порт, для работы с примером кода в этих главах.

Глава 11 включает использование типов данных в ядре и написание переносимого кода.

Вторая часть книги посвящена более развернутым темам. Мы начинаем глубже изучать внутренности ядра, в частности, особенные функциональные возможности периферийных шин. Глава 12 описывает в подробности написание драйверов для PCI устройств, и в главе 13 рассматриваем API для работы с USB устройствами.

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

В главе 15, мы отвлекаемся на управление памятью в Линукс. Эта глава показывает как распределять память ядра в пользовательском пространстве (системный вызов mmap), распределение пользовательской памяти, в пространстве ядра (с get_user_pages) и также как распределять ту или иную разновидность памяти внутри пространства устройства (выполнять операции прямого управления доступом к памяти [DMA] ).

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

Внимание! Этот перевод, возможно, ещё не готов.
Его статус: перевод редактируется

Переведено на Нотабеноиде
http://notabenoid.org/book/11832/37931

Переводчики: ximen, hardorsoft, allez, JoUki

Настройки

Готово:

100.00% КП = 1.1