Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология
Образование Политология Производство Психология Стандартизация Технологии


Добавление вашего кода в ядро



В этой главе:

? 10.1 Обход исходников

? 10.2 Написание кода

? 10.3 Сборка и отладка

? Резюме

? Упражнения



Глава 10 • Добавление вашего кода в ядро


В

этой главе можно выделить две главные части: «Обход исходников» и «Написа­ние кода».

«Обход исходников» посвящен обзору драйвера устройства /dev/random, ко­торый является общим для всех систем Linux, и демонстрирует, как с ним связано ядро. Во время обзора мы вспомним некоторые особенности внутренней работы ядра, рассмотренные ранее, и осветим их с практической точки зрения.

«Написание кода» - это руководство по написанию драйвера и затрагивает рас­пространенные ситуации, с которыми сталкивается разработчик драйверов.

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

Обход исходников

Этот раздел включает представление концепции системных вызовов и драйверов (также известных как модули) в Linux. Системные вызовы используются пользовательскими программами для общения с операционной системой для запроса служб. Добавление сис­темного вызова - это один из способов создания новой службы ядра. Гл. 3, «Процессы: принципиальная модель выполнения», описывает внутреннюю реализацию системного вызова. Эта глава описывает практические аспекты встраивания вашего системного вы­зова в ядро Linux.

Драйвер устройства представляет собой интерфейс, используемый ядром Linux для того, чтобы разрешать программисту управлять системным вводом-выводом устройств. Эта глава подробно разъясняет все тонкости. В этом разделе мы проследим работу драй­вера с его представления в файловой системе и вплоть до контролирующего его кода ядра. В следующем разделе мы покажем, как использовать то, что мы изучили в первой части разработки функционального символьного устройства. Заключительная часть гл. 10 опи­сывает, как писать системные вызовы и собирать ядро. Мы начнем с рассмотрения файло­вой системы и покажем, как эти файлы связаны с ядром.

Познакомимся с файловой системой

Устройства в Linux доступны через /dev. Например, -1 /dev/random выдает сле­дующее:

crw-rw-rw- 1 root root 1, 8 Oct 2 08: 08 /dev/random

Первая «с» означает, что устройство является символьным; «Ь» означает блочное устройство. После владельца и колонок группы идут два числа, разделенные запятыми (в данном случае 1, 8). Первое число - это старший номер драйвера, а второе число - млад­ший номер. Когда драйвер устройства регистрируется в ядре, он регистрирует старший номер. Когда данное устройство открывается, ядро использует старший номер устройства


10.1 Обход исходников



для нахождения драйвера, зарегистрированного для этого старшего номера1. Младший номер передается через ядро в сам драйвер устройства, так как один драйвер может управ­лять несколькими устройствами. Например, /dev/urandom имеет старший номер 1 и младший номер 9. Это значит, что драйвер устройства зарегистрирован со старшим но­мером 1, обрабатывающим как /dev/random, так и /dev/urandom.

Для генерации случайного числа мы просто выполняем чтение из /dev/random. Следующим способом можно считать 4 байта случайных данных2:

lkp@lkp: ~$ head -c4 /dev/urandom | od -x

0000000 823а ЗЬе5

Если вы повторите эту команду, вы увидите что 4 байта [823а ЗЬе5] продолжают из­меняться. Для демонстрации того, как ядро Linux использует драйверы устройств, мы проследим по шагам, что делает ядро, когда пользователь получает доступ к /dev/ random.

Мы знаем, что файл устройства /dev/random имеет старший номер 1; мы можем определить, какой драйвер контролирует этот узел через /proc/devices:

lkp@lkp: ~$ less /proc/devices Character devices: 1 mem

Давайте рассмотрим драйвер устройства mem и поищем вхождение «random»;


653 static int memory_open(struct inode * inode, struct file * filp)

654 {

655 switch (iminor(inode)) {

656 case 1:

& random_fops; & urandom_fops;

676 case 8:

677 filp-> f_op

678 break;

679 case 9:

680 filp-> f_op

681 break;

1 mknod создает файлы блочных и символьных устройств.

2 head -с4 берет первые 4 байта, a od -x форматирует их в шестнадцатеричный вид.



Глава 10 • Добавление вашего кода в ядро


Строки 655-681

Конструкция switch инициализирует поддержку драйверов на основе младшего номера устройства, с которым мы работаем. Точнее говоря, устанавливаются f ilp и fops.

Возникает вопрос, что такое f ilp и что такое fop?

FilpsnFops

f ilp - это просто указатель на файловую структуру, a fop - это указатель на структуру f i 1 е_орerations. Ядро использует структуру f ile_operations для определения того, какую функцию при работе с данным файлом вызывать. Здесь выбирается раздел структур, используемых в драйвере устройства random.

556 struct file {

557 struct list_head f_list;

558 struct dentry *f_dentry;

559 struct vfsmount *f_vfsmnt;

560 struct file_operations *f__op;

561 atomic_t f_count;

562 unsigned int f_flags;

581 struct address_space *f_mapping;

582 };

863 struct file_operations {

864 struct module *owner;

865 loff_t (*llseek) (struct file *, loff_t, int);

866 ssize_t (*read) (struct file *, char __ user *, size_t, loff_t *);

867 ssize_t (*aio_read) (struct kiocb *, char user *, size_t, loff_t);

868 ssize_t (*write) (struct file *, const char ___ user *, size__t, loff_t *);

869 ssize_t (*aio_write)(struct kiocb *, const char __ user *,

size_t, loff_t);

870 int (*readdir) (struct file *, void *, filldir__t);

871 unsigned int (*poll) (struct file *, struct poll_table__struct *);

872 int (*ioctl) (struct inode *, struct file *, unsigned int,

unsigned long);

888 };

Драйвер устройства random определяет, какую операцию производить следующим образом: функции, реализованные в драйвере, должны соответствовать прототипам, перечисленным в структуре f ile_operations:


Обход исходников



1824 struct file_operations random_fops = {

1825.read = random_read/

1826.write = random_write/

1827.poll = random_poll,

1828.ioctl = random_ioctl,

1829 };
1830

1831 struct file_operations urandom_fops = {

1832.read = urandom_read/

1833.write = random_write/

1834.ioctl = random_ioctl/

1835 };

Строки 1824-1829

Устройство random реализует операции read, write, poll и ioctl.

Строки 1831-1835

Устройство urandom реализует операции read, write и ioctl.

Операция poll позволяет программисту выполнять проверку перед выполнением операции для проверки блокировки. Существует соглашение, что /dev/random бло­кируется, если затребовано больше байтов, чем находится в пуле энтропии1; /dev/ urandom не блокируется, но может вернуть не полностью случайные данные, если пул энтропии слишком мал. (Более подробную информацию см. в man pages, особенно в man 4 random.)

По мере углубления в код обратите внимание, что, когда с /dev/random выпол­няются операции чтения, ядро передает управление в функцию random_read () (см. строку 1825); random_rand() определен следующим образом:

drivers/char/random.с

1588 static ssize_t

1589 random_read(struct file * file, char _ user * buf, size_t

nbytes, loff_t *ppos)

У этой функции следующие параметры:

• file. Указывает на структуру устройства.

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

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



Глава 10 • Добавление вашего кода в ядро


• nbytes. Размер требуемых данных.

• ppos. Указывает на позицию в файле, к которой получает доступ пользователь.

Получается интересный результат: если драйвер выполняется в пространстве ядра, но буфер находится в пользовательском пространстве, как мы можем безопасно получить доступ к данным в buf? Следующий подраздел объясняет процесс перемещения данных между пользовательской памятью и памятью ядра.


Поделиться:



Популярное:

Последнее изменение этой страницы: 2016-03-25; Просмотров: 773; Нарушение авторского права страницы


lektsia.com 2007 - 2024 год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! (0.033 с.)
Главная | Случайная страница | Обратная связь