модуль ядра блочного устройства

Вопросы программного кода и архитектуры Linux

Модератор: Olej

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: модуль ядра блочного устройства

Непрочитанное сообщение Olej » 09 ноя 2012, 22:23

Olej писал(а): Повозившись этот пример можно трансформировать в работающий (со свежим ядром), ... но только он тогда превращается практически в пример из (отличаясь только именами переменных ;-) ):
Ну вот, следующий пример, он объединяет оба варианта (очень сильно изменённые). Они насколько свелись почти к одинаковости, что используют просто общие включаемые файлы в оба дерева проектов, а сами включающие файлы содержат только инициализацию и завершение, которые два автора видят чуть по-разному.

Теперь это выглядит так:

Код: Выделить всё

[root@notebook block_mod.LDD_35]# insmod block_mod_c.ko
[root@notebook block_mod.ELDD_14]# insmod block_mod_e.ko
[root@notebook block_mod.ELDD_14]# lsmod | grep ^block
block_mod_e            12728  0
block_mod_c            12709  0
block_mod_c - ... Jerry Cooperstein
block_mod_e - «Essential Linux Device Drivers»

И поехали ... так теперь переименованы дисковые устройства (чтоб похожи были):

Код: Выделить всё

[root@notebook block_mod.ELDD_14]# ls -l /dev/x*
brw-rw---- 1 root disk 252, 0 нояб.  9 20:06 /dev/xbc
brw-rw---- 1 root disk 251, 0 нояб.  9 20:06 /dev/xbe
Расформатировал как дискету на 16 Mb (без разделов), для разнообразия:

Код: Выделить всё

[root@notebook block_mod.ELDD_14]# mkfs.ext2 /dev/xbc
...
[root@notebook block_mod.ELDD_14]# mkfs.ext2 /dev/xbe
...
[root@notebook block_mod.ELDD_14]# mkdir /mnt/dskc
[root@notebook block_mod.ELDD_14]# mkdir /mnt/dske
[root@notebook block_mod.ELDD_14]# mount /dev/xbc /mnt/dskc
[root@notebook block_mod.ELDD_14]# mount /dev/xbe /mnt/dske
[root@notebook block_mod.ELDD_14]# tree /mnt
/mnt
├── dskc
│   └── lost+found
├── dske
│   └── lost+found
├── efi
└── iso

6 directories, 0 files
[root@notebook block_mod.ELDD_14]# fdisk -l /dev/xbe

Диск /dev/xbe: 16 МБ, 16777216 байт
255 heads, 63 sectors/track, 2 cylinders, всего 32768 секторов
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Ну вот, собственно, и всё ;-) :

Код: Выделить всё

[root@notebook block_mod.ELDD_14]# echo qwertyuiop[] >> /mnt/dskc/f
[root@notebook block_mod.ELDD_14]# ls -l /mnt/dskc/
итого 13
-rw-r--r-- 1 root root    13 нояб.  9 20:36 f
drwx------ 2 root root 12288 нояб.  9 20:25 lost+found
[root@notebook block_mod.ELDD_14]# cp /mnt/dskc/f /mnt/dske/f
[root@notebook block_mod.ELDD_14]# ls -l /mnt/dske/
итого 13
-rw-r--r-- 1 root root    13 нояб.  9 20:37 f
drwx------ 2 root root 12288 нояб.  9 20:26 lost+found
[root@notebook block_mod.ELDD_14]# cat /mnt/dske/f
qwertyuiop[]
Там же (для /dev/xbc) есть тест прямой записи-чтения:

Код: Выделить всё

[root@notebook block_mod.LDD_35]# ./block_test
**** return code from write = 8488
**** retrun code from lseek(1000) = 1000
**** retrun code from read vec[250] = 4, vec[250] = 250
После чего структура диска, естественно, развалилась ;-) :

Код: Выделить всё

[root@notebook block_mod.LDD_35]# ls -l /mnt/dskc
итого 10331131637612
b--sr-srwt 11785 959711591 151652963 56, 52 нояб. 17  1999 lost+found
Но можно использовать для клонирования диска со всей его структурой и содержимым.
Вложения
blkdev.tgz
(7.02 КБ) 400 скачиваний

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: модуль ядра блочного устройства

Непрочитанное сообщение Olej » 10 ноя 2012, 04:35

Olej писал(а): Пример их sbull не компилируется с чудовищным числом (в 2 экрана термина) сообщений об ошибках.
Этот пример тоже довёл до ума, и увязал в общую иерархию каталогов (чтобы не плодить дубликаты кода). Я архив приложу, но там пока совершенно черновой вариант, но работающий, весь почёрканый закомментированными кусками - это только для тех, кто хотел бы покопаться с кодом.

Работа (там есть файл *.hist - это протокол выполнения, по нему всё понятно что там делать):

Код: Выделить всё

[root@notebook block_mod.LDD3]# insmod block_mod_s.ko
[root@notebook block_mod.LDD3]# lsmod | head -n3
Module                  Size  Used by
block_mod_s            13041  0
tcp_lp                 12583  0
[root@notebook block_mod.LDD3]# ls -l /dev/x*
brw-rw---- 1 root disk 252, 16 нояб. 10 03:21 /dev/xbsa
brw-rw---- 1 root disk 252, 17 нояб. 10 03:21 /dev/xbsb
brw-rw---- 1 root disk 252, 18 нояб. 10 03:21 /dev/xbsc
brw-rw---- 1 root disk 252, 19 нояб. 10 03:21 /dev/xbsd
Дисковых устройств в этом варианте - 4 (или определяйте параметром запуска).

Код: Выделить всё

[root@notebook block_mod.LDD3]# mkfs.ext2 /dev/xbsa
mke2fs 1.42.3 (14-May-2012)
...
[root@notebook block_mod.LDD3]# fdisk -l /dev/xbsa
Диск /dev/xbsa: 4 МБ, 4194304 байт
255 heads, 63 sectors/track, 0 cylinders, всего 8192 секторов
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
[root@notebook block_mod.LDD3]# mount /dev/xbsa /mnt/dske
[root@notebook block_mod.LDD3]# echo ======================================================== > /mnt/dske/f
[root@notebook block_mod.LDD3]# ls -l /mnt/dske
итого 13
-rw-r--r-- 1 root root    57 нояб. 10 03:00 f
drwx------ 2 root root 12288 нояб. 10 02:56 lost+found
[root@notebook block_mod.LDD3]# df | grep /mnt
/dev/xbsa             3963           30     3729            1% /mnt/dske
[root@notebook block_mod.LDD3]# umount /dev/xbsa
[root@notebook block_mod.LDD3]# rmmod block_mod_s
[root@notebook block_mod.LDD3]# ls -l /dev/x*
ls: невозможно получить доступ к /dev/x*: Нет такого файла или каталога


Всё. ... пока ;-)
Вложения
blkdev.tgz
(10.41 КБ) 395 скачиваний

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: модуль ядра блочного устройства

Непрочитанное сообщение Olej » 11 ноя 2012, 00:45

Olej писал(а): Этот пример тоже довёл до ума, и увязал в общую иерархию каталогов
Следующий вариант ;-). Что добавилось:

- обработку чтения-записи блочного устройства можно теперь производить не только традиционно, в очередь запросов (опция по умолчанию mode=0 - так как это делается для механических HDD), но и напрямую минуя очередь (опция по умолчанию mode=2 - так как это целесообразно делать для RAM-дисков ... и, наверное, для USB флешек);

- радикально (дотла) переделан тест (block-test) записи - чтения - сверки для созданных блочных устройств;

И вот что теперь получается:

Код: Выделить всё

[root@notebook block_mod.LDD3]# insmod block_mod_s.ko

[root@notebook block_mod.LDD3]# hdparm -t /dev/xda
/dev/xda:
 Timing buffered disk reads:   4 MB in  0.01 seconds = 284.70 MB/sec

bash-4.2$ sudo ./block_test -v /dev/xda -l0
объём устройства 4194304 байт
записано 4194304 байт
ошибка чтения: No space left on device
считано 4194304 байт
считанное в точности соответствует записанному!
Это то как было.

Код: Выделить всё

[root@notebook block_mod.LDD3]# insmod block_mod_s.ko mode=2

[root@notebook block_mod.LDD3]# hdparm -t /dev/xda
/dev/xda:
 Timing buffered disk reads:   4 MB in  0.01 seconds = 354.20 MB/sec

bash-4.2$ sudo ./block_test -v /dev/xda -l0
объём устройства 4194304 байт
записано 4194304 байт
ошибка чтения: No space left on device
считано 4194304 байт
считанное в точности соответствует записанному!
Это то, как может быть.

Отчётливо видно, что скорость обмера при этом возрастает на хорошие 50%.
И 4Mb объёма /dev/xda прописываются побайтно (последовательно) - и всё потом считывается ОК.
Вложения
blkdev.tgz
(11.64 КБ) 397 скачиваний

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: модуль ядра блочного устройства

Непрочитанное сообщение Olej » 11 ноя 2012, 00:55

Olej писал(а): Отчётливо видно, что скорость обмера при этом возрастает на хорошие 50%.
Возвращаясь в начало:
Olej писал(а):Тема переплыла вот отсюда: проект книги: "Модули ядра Linux". В книге совсем опущен вопрос блочных устройств.
Сейчас уже отчётливо видно, что:
- отличия в технике написания блочных устройств от символьных навязаны, главным образом и единственно, погоней за высокой скоростью блочных устройств...
- теоретически можно было бы вполне поддержку блочных устройств сделать в точности так же, как символьных - через файловую таблицу операций;
- но в погоне за скоростью, разработчики ядра вынесли большую часть обработки внутрь ядра, в очереди запросов (которые обслуживаются ядром, а драйвер должен их только заполнять);
- и из-за этого техника написания блочных (дисковых) драйверов, если разобраться в их системе условностей, проще, чем техника написания символьных драйверов.

Вот такой вот парадокс ;-)

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: модуль ядра блочного устройства

Непрочитанное сообщение Olej » 11 ноя 2012, 14:27

Olej писал(а): Пример их sbull не компилируется с чудовищным числом (в 2 экрана термина) сообщений об ошибках. Это достаточно ожидаемый результат, так как писалась их книга (как мне помнится) для ядра 2.6.29 (максимум),
Вот здесь обнаружился справочник The Linux Kernel API, и, в частности раздел 14: Chapter 14. Block Devices.
Очень краткие справки, по типу man-ов ... но хоть что-то, потому, что большинство статей и книг - устаревшие.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: модуль ядра блочного устройства

Непрочитанное сообщение Olej » 11 ноя 2012, 21:09

Olej писал(а): Вот их пример для блочного устройства:
14.tgz
Ещё один (4-й) пример RAM-блочного устройства находим здесь же на сайте в переводах 2012 г.: Часть 15: Диск в оперативной памяти — экспериментируем с драйверами блочных устройств.
Там только 1, простейший, вариант - с очередью обслуживания, но + есть какие-то (мало внятные, всё же) объяснения относительно используемых API.

Только Makefile из их примера я предложил бы, не пробуя, сразу переписать:

Код: Выделить всё

CURRENT = $(shell uname -r)
KDIR = /lib/modules/$(CURRENT)/build
PWD = $(shell pwd)

obj-m := dor.o
dor-y := ram_block.o ram_device.o partition.o

default: module clean

module:
        $(MAKE) -C $(KDIR) M=$(PWD) modules

clean:
        @rm -f *.o .*.cmd .*.flags *.mod.c *.order
        @rm -f .*.*.cmd *.symvers *~ *.*~ TODO.*
        @rm -fR .tmp*
        @rm -rf .tmp_versions
В таком виде оно сразу же собирается.
И, наверное, работает.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: модуль ядра блочного устройства

Непрочитанное сообщение Olej » 12 ноя 2012, 03:13

Olej писал(а): Вот здесь обнаружился справочник The Linux Kernel API, и, в частности раздел 14: Chapter 14. Block Devices.
Очень краткие справки, по типу man-ов ... но хоть что-то, потому, что большинство статей и книг - устаревшие.
Вот с этим справочником (он далеко не полный) + пробы-ошибки - удалось "укатать" все 3 варианта организации обмена блочного драйвера.

1. простейший способ (mode=0 или по умолчанию) - передача всей работы I/O обработчику очереди запросов внутри ядра (такой способ прописывается в 3-х из 4-х обсуждаемых примерах кода):

Код: Выделить всё

[root@notebook block_mod.LDD3]# insmod block_mod_s.ko mode=0

[root@notebook block_mod.LDD3]# ../test_seq -v /dev/xda -l1000
объём устройства 4194304 байт
записано 1000 байт
считано 1000 байт
считанное в точности соответствует записанному!

[root@notebook block_mod.LDD3]# hdparm -t /dev/xda

/dev/xda:
 Timing buffered disk reads:   4 MB in  0.01 seconds = 318.32 MB/sec
2. способ полной обработки (mode=1) - все элементы вектора BIO внутри запроса из очереди обрабатываются внутри кода драйвера:

Код: Выделить всё

[root@notebook block_mod.LDD3]# insmod block_mod_s.ko mode=1

[root@notebook block_mod.LDD3]# ../test_seq -v /dev/xda -l1000
объём устройства 4194304 байт
записано 1000 байт
считано 1000 байт
считанное в точности соответствует записанному!

[root@notebook block_mod.LDD3]# hdparm -t /dev/xda

/dev/xda:
 Timing buffered disk reads:   4 MB in  0.03 seconds = 116.02 MB/sec
3. способ (mode=2) вообще не использования очереди (оптимизации) ядра:

Код: Выделить всё

[root@notebook block_mod.LDD3]# insmod block_mod_s.ko mode=2

[root@notebook block_mod.LDD3]# ../test_seq -v /dev/xda -l1000
объём устройства 4194304 байт
записано 1000 байт
считано 1000 байт
считанное в точности соответствует записанному!

[root@notebook block_mod.LDD3]# hdparm -t /dev/xda

/dev/xda:
 Timing buffered disk reads:   4 MB in  0.01 seconds = 371.92 MB/sec
В каждом случае показана работа тестовой программы (test_seq) проверки корректности записи-чтения (из прилагаемого архива).
Но самое интересное - это последний запуск стандартной утилиты GNU проверки производительности диска (hdparm). В 3-х случаях, в зависимости от того, как написан драйвер, этот показатель очень сильно изменяется.

На этом, думаю, написание примеров возможных драйверов для блочных устройств можно вести к завершению.
Вложения
blkdev.tgz
(12.36 КБ) 389 скачиваний

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: модуль ядра блочного устройства

Непрочитанное сообщение Olej » 12 ноя 2012, 03:17

Olej писал(а):Но самое интересное - это последний запуск стандартной утилиты GNU проверки производительности диска (hdparm).
Ещё интересно показать, как видится геометрия созданного диска (это работает операция ioctl устройства):

Код: Выделить всё

[root@notebook block_mod.LDD3]# hdparm -g /dev/xda 

/dev/xda:
 geometry      = 128/4/16, sectors = 8192, start = 16

Код: Выделить всё

[root@notebook block_mod.LDD3]# fdisk -l /dev/xda 

Диск /dev/xda: 4 МБ, 4194304 байт
4 heads, 16 sectors/track, 128 cylinders, всего 8192 секторов
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: модуль ядра блочного устройства

Непрочитанное сообщение Olej » 12 ноя 2012, 16:13

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

Код: Выделить всё

dev->gd = alloc_disk( DEV_MINORS );
т.е. так где для диска (не для раздела!) создаётся (ядром) структура struct gendisk.
Вот прототип:

Код: Выделить всё

struct gendisk *alloc_disk( int minors );
minors - это число слотов, создаваемых при диске, максимальное число (так пишут) разделов, которое на диске смогут создать fdisk, parted, gdisk, ...
Т.е. если задать:

Код: Выделить всё

dev->gd = alloc_disk( 1 );
- то у нас получится дискета (независимо от размера), на которой не может быть partition ...
- но которую можно расформатировать "цельно", например mkfs.ext2, и замечательно с ней работать.

Я так понимаю, что по alloc_disk(), помимо прочего, размещается minors объектов kobject для отображения (будущего) в /sys. А kobject структура немалая... А ещё скорее, ядро просто размещает minors + 1 структур struct gendisk : 1 для диска в целом, и minors для всех потенциально возможных partition на нём (а каждая struct gendisk со своим kobject внутри). Тогда тем более это может быть расточительное использование...

Здесь много путаницы (в том что пишут) и много нюансов (из "новых веяний"):
- это не число partition, а номер записи о partition (!)
- создать на диске можно сколько угодно partition - стандарт extended partition предполагает вложенные extended, и на такие цепочки не накладываются никакие ограничения...
- fdisk (parted?, gparted?) не умеют такого делать (цепочек), но это ничего не значит - это умеют делать "разбивщики" от сторонних производителей;
- создать то можно, но если в драйвере не предусмотрено, то больше minors не будут отображаться в /dev;
- если задать (что иногда можно видеть):

Код: Выделить всё

dev->gd = alloc_disk( 1 );
- то можно будет работать с 4-мя (теоретически возможный максимум!) primary partition ...
- но нельзя будет работать даже с одним логическим диском в extended partition, потому как ...
- вот разбивка:

Код: Выделить всё

# fdisk -l /dev/xda
...
Устр-во Загр     Начало       Конец       Блоки   Id  Система
/dev/xda1               1        4000        2000   83  Linux
/dev/xda2            4001        8191        2095+   5  Расширенный
/dev/xda5            4002        8191        2095   83  Linux
- а вот её отображение:

Код: Выделить всё

# ls -l /dev/xda*
brw-rw---- 1 root disk 252, 0 нояб. 12 10:44 /dev/xda
brw-rw---- 1 root disk 252, 1 нояб. 12 10:44 /dev/xda1
brw-rw---- 1 root disk 252, 2 нояб. 12 10:44 /dev/xda2
brw-rw---- 1 root disk 252, 5 нояб. 12 10:46 /dev/xda5
- и при mode=4 диск с номером записи /dev/xda5 виден не будет...

Так что "хорошим значением" будет, например, 16.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: модуль ядра блочного устройства

Непрочитанное сообщение Olej » 12 ноя 2012, 16:28

Olej писал(а):Так что "хорошим значением" будет, например, 16.
Но это так было "до поры до времени"...
При дисках MBR, с ихними primary, extended, logical... ;-)

А при теперешнем массовом переходе к дискам GPT (см. GPT диски):
- все разделы только primary;
- слотов в таблице разделов (а значит и разделов может быть) до 128;
- и раздел может быть 1, да номер у него может быть 128 :lol:
- я там (в теме про GPT) приводил реальный вывод, вот так, например:

Код: Выделить всё

bash-4.2$ sudo parted /dev/sdb 
GNU Parted 3.0
Используется /dev/sdb
Добро пожаловать в GNU Parted! Наберите 'help' для просмотра списка команд.
(parted) print                                                            
Модель: Ut163 USB2FlashStorage (scsi)
Диск /dev/sdb: 1011MB
Размер сектора (логич./физич.): 512B/512B
Таблица разделов: gpt
Disk Flags: 

Номер  Начало  Конец   Размер  Файловая система  Имя                   Флаги
1     1049kB  53,5MB  52,4MB  fat16             EFI System            загрузочный, legacy_boot
10     53,5MB  578MB   524MB   ntfs              Microsoft basic data
20     578MB   1011MB  433MB   ext4              Linux filesystem
Так что в хорошем драйвере должно резервироваться? :

Код: Выделить всё

dev->gd = alloc_disk( 128 );
Похоже так оно и есть, потому что в той же теме я показывал такое:

Код: Выделить всё

bash-4.2$ ls /dev/sdf*
/dev/sdf     /dev/sdf102  /dev/sdf104  /dev/sdf106  /dev/sdf108  /dev/sdf21  /dev/sdf23  /dev/sdf25  /dev/sdf27  /dev/sdf29
/dev/sdf101  /dev/sdf103  /dev/sdf105  /dev/sdf107  /dev/sdf109  /dev/sdf22  /dev/sdf24  /dev/sdf26  /dev/sdf28
Это Fedora 17, ядро 3.5, с её, соответственно модулем SCSI диска.

Ответить

Вернуться в «Linux изнутри»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 9 гостей