Второе издание
Скачать 3.09 Mb.
|
Рис. 17.2. Содержимое части каталога /sys Каждый из каталогов в свою очередь содержит подкаталоги, соответствующие разделам блочного устройства. Каталог bus позволяет просматривать информа- цию о системных шинах. В каталоге class представлена информация о системных устройствах, которая организована в соответствии с высокоуровневыми функциями этих устройств. Каталог devices содержит информацию о топологии устройств в системе. Она отображается непосредственно на иерархию структур устройств ядра. Каталог firmware содержит специфичное для данной системы дерево низкоуровне- вых подсистем, таких как ACPI, EDD, EFT и т.д. В каталоге power содержатся данные по управлению электропитанием всех устройств системы. Наиболее важным является каталог d e v i c e s , который экспортирует модель устройств ядра во внешний мир. Структура каталога соответствует топологии устройств в системе. Большинство информации, которая содержится в других ка- талогах, — это просто другое представление данных каталога devices. Например, в каталоге /sys/class/net/ информация представлена в соответствии с высоко- уровневым представлением зарегистрированных сетевых устройств. В этом каталоге может содержаться подкаталог eth0, который содержит символьную ссылку device на соответствующее устройство каталога devices. Посмотрите на содержимое каталога /sys той системы Linux, к которой вы имеете доступ. Такое представление системных устройств является очень четким и ясным. Оно показывает взаимосвязь между высокоуровневым представлением ин- формации в каталоге class, низкоуровневым представлением в каталоге devices 364 Глава 17 и драйверами устройств — в каталоге bus. Такое представление взаимосвязи между устройствами очень информативно. Оно становится еще более ценным, если осо- знать, что все эти данные свободно доступны и описывают все то, что происходит внутри ядра 1 Добавление и удаление объектов на файловой системе sysfs Инициализированные объекты kobject автоматически не экспортируются через файловую систему sysfs. Для того чтобы сделать объект видимым через sysfs, необхо- димо использовать функцию kobject_add(). int kobject_add(struct kobject *kobj); Положение объекта на файловой системе sysfs зависит от его положения в объ- ектной иерархии. Если установлен указатель p a r e n t объекта, то объект будет ото- бражен внутри каталога, соответствующего объекту, на который указывает указатель parent. Если указатель parent не установлен, то объект будет отображен в каталоге, соответствующем значению переменной kset->kobj. Если для некоторого объекта не установлены ни значение поля parent, ни значение поля kset, то считается, что данный объект не имеет родительского и будет отображаться в корневом каталоге файловой системы sysfs. Такое поведение практически всегда соответствует тому, что нужно. Поэтому одно из полей p a r e n t или k s e t (или оба) должно быть установ- лено правильным образом перед вызовом функции kobject_add () . Имя каталога, который представляет объект kobject в файловой системе sysfs, будет определяться значением поля kobj->name. Вместо того чтобы последовательно вызывать функции k o b j e c t _ i n i t () и kobject_add(), можно вызвать функцию k o b j e c t _ r e g i s t e r (). int kobject_register(struct kobject *kobj); Удаление объекта из файловой системы sysfs выполняется с помощью функции k o b j e c t _ d e l ( ) . void kobject_del(struct kobject *kobj); Функция kob j е c t u n r e g i s t er () сочетает в себе выполнение функций kobject_del() и kobject_put(). void kobject_unregister(struct kobject * kobj); Все эти четыре функции определены в файле l i b / k o b j e c t . с и объявлены в файле 1 Если вас заинтересовала информация о файловой системе sysfs, то, вероятно, вам будет интересно также ознакомиться с HAL, hardware abstraction layer (уровень абстракции аппаратного обеспече- ния), информация о котором доступна по адресу h t t p : / / h a l . f r e e d e s k t o p . o r g / . Подсистема HAL позволяет создать в оперативной памяти базу данных на основании информации файловой системы sysfs, объединяя вместе понятия классов, устройств и драйверов. На основании этих дан- ных уровень HAL предоставляет API, которое позволяет разрабатывать более интеллектуальные программы. Объекты kobject и файловая система sysfs 365 Добавление файлов на файловой системе sysfs Объекты kobject отображаются на каталоги, и такое отображение выполняется естественным образом. А как насчет создания файлов? Файловая система sysfs — это не что иное, как дерево каталогов без файлов. Атрибуты, используемые по умолчанию Набор файлов, которые создаются в каталоге по умолчанию, определяется с по- мощью поля ktype объектов kobject и множеств kset. Следовательно, все объекты kobject одного типа имеют один и тот же набор файлов в каталогах, которые этим объектам соответствуют. Структура kobject_type содержит поле d e f a u l t _ a t t r s , которое представляет собой массив структур a t t r i b u t e . Атрибуты отображают дан- ные ядра на файлы в файловой системе sysfs. Структура a t t r i b u t e s определена в файле /* структура a t t r i b u t e - атрибуты позволяют отобразить данные ядра на файлы файловой системы sysfs */ struct attribute { char *name; /* имя атрибута */ struct module *owner; /* модуль, если есть, которому принадлежат данные */ mode_t mode; /* права доступа к файлу */ }; Поле name содержит имя атрибута. Такое же имя будет иметь и соответствующий файл на файловой системе sysfs. Поле owner — это указатель на структуру module, которая представляет загружаемый модуль, содержащий соответствующие данные. Если такого модуля не существует, то значение поля равно NULL. Поле mode имеет тип mode_t и указывает права доступа к файлу на файловой системе sysfs. Если атри- бут предназначен для чтения всеми, то флаг прав доступа доллсен быть установлен в значение S_IRUGO, если атрибут имеет право на чтение только для владельца, то права доступа устанавливаются в значение S_IRUSR. Атрибуты с правом на запись, скорее всего, будут иметь права доступа S_IRUGO | S_IWUSR. Все файлы и каталоги на файловой системе sysfs принадлежат пользователю с идентификаторами пользова- теля и группы равными нулю. Структура a t t r i b u t e используется для представления атрибутов, а структура sysfs_ops описывает, как эти атрибуты использовать. Поле sysfs_ops — это ука- затель на одноименную структуру, которая определена в файле < l i n u x / s y s f s . h > следующим образом. struct sysfs_ops { /* метод вызывается при чтении файла на файловой системе sysfs */ ssize_t (*show) (struct kobject *kobj, struct attribute *attr, char *buffer); /* метод вызывается при записи файла на файловой системе sysfs */ ssize_t (*store) (struct kobject *kobj, struct attribute *attr, const char *buffer, size_t size); }; 366 Глава 17 Метод show() вызывается при чтении файла. Он должен выполнить копирова- ние значения атрибута, который передается в качестве параметра a t t r , в буфер, на который указывает параметр buffer. Размер буфера равен PAGE_SIZE байт. Для ап- паратной платформы значение PAGE_SIZE равно 4096 байтов. Функция должна воз- вратить количество байтов данных, которые записаны в буфер в случае успешного завершения, и отрицательный код ошибки, если такая ошибка возникает. Метод s t o r e ( ) вызывается при записи. Он должен скопировать s i z e байт дан- ных из буфера buffer в атрибут a t t r . Размер буфера всегда равен PAGE_SIZE или меньше. Функция должна возвратить количество байтов данных, которые прочита- ны из буфера при успешном выполнении, и отрицательный код ошибки в случае не- удачного завершения. Так как этот набор функций должен выполнять операции ввода-вывода для всех атрибутов, то необходимо выполнить некоторые дополнительные действия, чтобы вызвать обработчик, специфичный для каждого атрибута. Создание нового атрибута Обычно атрибутов, которые используются по умолчанию и предоставляются ти- пом ktype, связанным с объектом kobject, оказывается достаточно. Действительно, все объекты k o b j e c t одного типа должны быть чём-то похожи друг на друга или даже быть идентичными по своей природе. Например, для всех разделов жестких дисков один и тот же набор атрибутов должен подходить для всех объектов kobject. Это не просто упрощает жизнь, но и позволяет упорядочить код и получить одина- ковый способ доступа ко всем каталогам файловой системы sysfs, связанным с род- ственными объектами. Тем не менее иногда требуется, чтобы определенный экземпляр объекта kobject имел некоторые специфические свойства. Для таких объектоп может оказаться же- лательным (или необходимым) создать атрибут, которого нет у общего типа данного объекта. Для такого случая ядро предоставляет функцию sysf s _ c r e a t e _ f i l e () для добавления атрибута к существующему объекту. int sysfs_create_file(struct kobject *kobj, const struct attribute *attr); Эта функция позволяет привязать структуру a t t r i b u t e , на которую указывает параметр a t t r , к объекту k o b j e c t , на который указывает параметр kobj. Перед тем как вызвать эту функцию, необходимо установить значение атрибута (заполнить поля структуры). Эта функция возвращает значение нуль в случае успеха и отрица- тельное значение в случае ошибки. Обратите внимание, что для обработки указанного атрибута используется струк- тура sysfs_ops, соответствующая типу ktype объекта. Иными словами, существую- щие функции show () и s t o r e {), которые используются для объекта по умолчанию, должны иметь возможность обработать вновь созданный атрибут. Кроме того, существует возможность создавать символьные ссылки. Создать сим- вольную ссылку на файловой системе sysfs можно с помощью вызова следующей функции. int sysfs_create_link(struct kobject *kobj, struct kobject *target, char *name); Объекты kobject и файловая система sysfs 367 Эта функция создает символьную ссылку с именем name в каталоге объекта, соот- ветствующего параметру kobj, на каталог, соответствующий параметру t a r g e t . Эта функция возвращает нулевое значение в случае успеха и отрицательный код ошибки в противном случае. Удаление созданного атрибута Удаляется атрибут с помощью вызова функции sysfs_remove_f i l e (). void sysfs_remove_file(struct kobject *kobj, const struct attribute *attr); После возврата из этой функции указанный атрибут больше не отображается в каталоге объекта. Символьная ссылка, созданная с помощью функции sysfs_create_link (), мо- жет быть удалена с помощью функции sysfs_remove_link(). void sysfs_remove_link (struct kobject *kobj, char *name) ; После возврата из функции символьная ссылка с именем name удаляется из ката- лога, на который отображается объект kobj. Все эти четыре функции объявлены в файле < l i n u x / k o b j e c t . h > . Функции sysfs_create_file() и sysfs_remove_file() определены в файле fs/sysfs/ f i l e . с , а функции s y s f s _ c r e a t e _ l i n k ( ) и sysfs_remove_link() — в файле fs/sysfs/symlink.c. Соглашения по файловой системе sysfs Файловая система sysfs — это место, где должна реализовываться функциональ- ность, для которой раньше использовался системный вызов i o c t l ( ) для специ- альных файлов устройств, или файловая система procfs. Сегодня модно выполнять такие вещи через атрибуты файловой системы sysfs в соответствующем каталоге. Например, вместо того чтобы реализовать новую директиву i o c t l ( ) для специаль- ного файла устройства, лучше добавить соответствующий атрибут в каталоге файло- вой системы sysfs, который относится к этому устройству. Такой подход позволяет избежать использования небезопасных, из-за отсутствия проверки типов аргументов, директив i o c t l (), а также файловой системы / р r о с с ее бессистемным расположе- нием файлов и каталогов. Однако чтобы файловая система sysfs оставалась четко организованной и интуи- тивно понятной, разработчики должны придерживаться определенных соглашений. Во-первых, каждый атрибут sysfs должен экспортировать значение одной пере- менной на файл. Значения должны быть в текстовом формате и соответствовать простым типам языка программирования С. Целью такого представления являет- ся необходимость избежать чрезвычайно запутанного и плохо структурированного представления информации, которое мы сегодня имеем на файловой системе /ргос. Использование одной переменной на файл позволяет легко считывать и записывать данные из командной строки, а также просто работать через файловую систему sysfs с данными ядра в программах, написанных на языке С. В случаях, когда одно значе- ние на файл приводит к неэффективному представлению информации, допустимо использование файлов, в которых хранится несколько значений одного типа. Эти данные необходимо четко разделять. Наиболее предпочтительным разделителем яв- ляется символ пробела. При разработке кода ядра необходимо всегда помнить, что 368 Глава 17 файлы файловой системы sysfs являются представлениями переменных ядра, и ори- ентироваться на доступ к ним из пространства пользователя, в частности из команд- ной строки. Во-вторых, данные файловой системы sysfs должны быть организованы в виде четкой иерархии. Для этого необходимо правильно разрабатывать связи "родитель- потомок" объектов kobject. Связывать атрибуты с объектами kobject необходимо с учетом того, что эта иерархия объектов существует не только в ядре, но и экспор- тируется в пространство пользователя. Структуру файловой системы sysfs необходи- мо поддерживать в четком виде! Наконец, необходимо помнить, что файловая система sysfs является службой ядра и в некотором роде интерфейсом ядра к прикладным программам (Application Binary Interface, ABT). Пользовательские программы должны разрабатываться в соот- ветствии с наличием, положением, содержимым и поведением каталогов и файлов на файловой системе sysfs. Изменение положения существующих файлов крайне не рекомендуется, а изменение поведения атрибутов, без изменения их имени или по- ложения, может привести к серьезным проблемам. Эти простые соглашения позволяют с помощью файловой системы sysfs обеспе- чить в пространстве пользователя интерфейс ядра с широкими возможностями. При правильном использовании файловой системы sysfs разработчики прикладных про- грамм не будут вас ругать и будут вам благодарны за хороший код. Уровень событий ядра Уровень событий ядра (kernel event layer) — это подсистема, которая позволяет передавать информацию о различных событиях из ядра в пространство пользовате- ля и реализована, как вы уже, наверное, догадываетесь, на базе объектов kobject. После выпуска ядра версии 2.6.0 стало ясно, что необходим механизм для отправле- ния сообщений из ядра в пространство пользователя, в частности для настольных рабочих компьютеров, что позволит сделать такие системы более функциональны- ми, а также лучше использовать асинхронную обработку. Идея состояла в том, что ядро будет помещать возникающие события в стек. Например, "Жесткий диск пере- полнен!", "Процессор перегрелся!", "Раздел диска смонтирован!", "На горизонте по- явился пиратский корабль!" (последнее, конечно, шутка). Первые реализации подсистемы событий ядра появились незадолго до того, как эта подсистема стала тесно связанной с объектами kobject и файловой системой sy- sfs. В результате такой связи реализация получилась достаточно красивой. В модели уровня событий ядра, события представляются в виде сигналов, которые посылают- ся объектами, в частности объектами типа kobject. Так как объекты отображаются на элементы каталогов файловой системы sysfs, то источниками событий являются определенные элементы пути на файловой системе sysfs. Например, если поступив- шее событие связано с первым жестким диском, то адресом источника события яв- ляется каталог /sys/block/hda. Внутри же ядра источником события является со- ответствующий объект kobject. Каждому событию присваивается определенная строка символов, которая пред- ставляет сигнал и называется командой (verb) или действием (action). Эта строка симво- лов содержит в себе информацию о том, что именно произошло, например изменение (modified) или размонтирование (unmounted). Объекты kobject и файловая система sysfs 369 Каждое событие может нести в себе некоторую дополнительную информацию (дополнительную нагрузку, payload). Вместо того чтобы передавать в пространство пользователя строку, которая содержит эту полезную информацию, данная дополни- тельная информация представляется с помощью атрибутов, отображаемых на фай- ловой системе sysfs. События ядра поступают из пространства ядра в пространство пользователя че- рез интерфейс n e t l i n k . Интерфейс n e t l i n k - это специальный тип высокоско- ростного сетевого сокета групповой передачи (multicast), который используется для передачи сообщений, связанных с сетевой подсистемой. Использование интерфейса n e t l i n k позволяет выполнить обработку событий ядра с помощью простых блоки- рующих вызовов функций для чтения информации из сокетов. Задача пространства пользователя— реализовать системный процесс-демон, который выполняет прослу- шивание сокета, считывает информацию о всех приходящих событиях, обрабатыва- ет их и отправляет полученные сообщения в системный стек пространства пользо- вателя. Одна из возможных реализаций такого демона, работающего в пространстве пользователя, — это D-BUS 2 . который также реализует и системную шину сообщений. Таким образом, ядро может подавать сигналы так же, как это делают все остальные компоненты системы. Для отправки события в пространство пользователя код ядра должен вызвать функцию kobject_uevent(). int kobject_uevent(struct kobject *kobj, enurn kobject_action action, struct attribute *attr); Первый параметр указывает объект kobject, который является источником сиг- нала. Соответствующее событие ядра будет содержать элемент пути на файловой си- стеме sysfs, связанный с объектом, сгенерировавшим сигнал. Второй параметр позволяет указать команду или событие, которое описывает сиг- нал. Сгенерированное событие ядра будет содержать строку, которая соответству- ет номеру, передаваемому в качестве значения параметра enurn k o b j e c t _ a c t i o n . Вместо того чтобы непосредственно передать строку, здесь используется ее номер, который имеет тип перечисления (enum). Это дает возможность более строго выпол- нить проверку типов, изменить соответствие между номером строки и самой строкой в будущем, а также уменьшить количество ошибок и опечаток. Перечисления опре- делены в файле На момент написания книги были определены следующие события: KOBJ_MOUNT, KOBJ_UNMOUNT, KOBJ_ADD, KOBJ_REMOVE и КОВJ_CHANGE. Эти значения отобража- ются на строки "mount" (монтирование), "unmount" (размонтироваыие), "add" (до- бавление), "remove" (удаление) и "change" (изменение) соответственно. Допускается добавление новых значений событий, если существующих значений недостаточно. Последний параметр — опциональный указатель на структуру a t t r i b u t e . Этот параметр можно трактовать как дополнительную информацию (payload) о событии. Если только одного значения события недостаточно, то событие может предоста- вить информацию о том, в каком файле файловой системы sysfs содержатся допол- нительные данные. 2 Более подробную информацию о демоне D-BUS можно найти на сайте h t t p : / / d b u s . f r e e d e s k t o p . o r g / . 370 Глава 17 Рассмотренная функция использует динамическое выделение памяти и поэтому может переходить в состояние ожидания. Существует атомарная версия рассмотрен- ной функции, которая идентична ей по всем, кроме того что при выделении исполь- зует флаг GFP_ATOMIC. int kobject_uevent_atomic (struct kobject *kobj, enum kobject_action action, struct attribute *attr); По возможности необходимо использовать стандартный интерфейс без атомар- ного выделения памяти. Параметры этих функций и их смысл — идентичны. Использование объектов kobject и их атрибутов не только дают возможность опи- сать события в терминах файловой системы sysfs, но и стимулируют создание новых объектов и их атрибутов, которые еще не представлены через файловую систему sysfs. Обе рассмотренные функции определены в файле l i b / k o b j e c t _ u e v e n t . с и объявлены в файле Кратко об объектах k o b j e c t и файловой системе sysfs В этой главе рассматривается модель представления устройств, файловая си- стема sysfs, объекты kobject и уровень событий ядра. Описание материала главы было бы невозможно без рассмотрения родственных вещей: были также описаны множества kset, подсистемы, атрибуты, типы ktype и счетчики ссылок kref. Эти структуры предназначены для использования разными людьми в разных местах. Разработчикам драйверов необходимо только ознакомление с внешними интерфей- сами. Большинство подсистем драйверов эффективно скрывают внутренние механиз- мы использования объектов kobject и других, близких к ним структур. Понимание основных принципов работы и знание основного назначения интерфейсов, таких как s y s f s _ c r e a t e _ f i l e ( ) , является достаточным для разработчиков драйверов. Однако для разработчиков, которые занимаются разработкой основного кода ядра, может потребоваться более детальное понимание принципов функционирования объектов kobject. Объекты kobject могут оказаться еще более важными, так как их могут использовать и те разработчики, которые вообще не занимаются разработ- кой подсистем драйверов!!! Эта глава — последняя из тех, которые посвящены подсистемам ядра. В следую- щих главах будут рассмотрены некоторые общие вопросы, которые также могут ока- заться важными для разработчиков ядра. Например, основные рекомендации по от- ладке кода! Объекты kobject и файловая система sysfs 371 |