Приложният програмен интерфейс (API) на драйвера на блоково устройство се е променил няколко пъти от създаването на Linux, но днес изглежда по същество както следва.
Функцията за инициализация извиква blk_init_queue
, предавайки обратно извикване на заявка и незадължително заключване за тази опашка:
struct request_queue *q;
q = blk_init_queue(my_request_cb, &my_dev->lock);
my_request_cb
е обратно извикване, което ще обработва всички I/O за това блоково устройство. Заявките за вход/изход ще бъдат изпратени в тази опашка и my_request_cb
ще бъде извикан, за да ги обработва една след друга, когато нивото на драйвера на блока на ядрото реши. След това тази опашка се добавя към диска:
struct gendisk *disk;
disk->queue = q;
и след това дискът се добавя към системата:
add_disk(disk);
disk
има друга информация като главното число, първото второстепенно число и други файлови операции (open
, release
, ioctl
и други, но не и read
и write
, както се срещат в символните устройства).
Сега my_request_cb
може да бъде извикан по всяко време и не е задължително да бъде извикан от контекста на процеса, който е инициирал четене/запис на блоковото устройство. Това повикване е асинхронно от ядрото.
Тази функция се декларира по следния начин:
static void my_request_cb(struct request_queue *q);
Опашката q
съдържа подреден списък от заявки към това блокиращо устройство. След това функцията може да разгледа следващата заявка (blk_fetch_request(q)
). За да отбележи дадена заявка като изпълнена, тя ще извика blk_end_request_all
(съществуват и други варианти в зависимост от ситуацията).
И тук отговарям на въпроса ви: ядрото знае, че определена заявка за блокиращо устройство е направена, когато неговият драйвер извика blk_end_request_all
или подобна функция за тази заявка. Драйверът не трябва да прекрати заявка в рамките на my_request_cb
: той може например да започне DMA прехвърляне, да постави заявката отново в опашката, да игнорира други и само когато бъде заявено прекъсването за завършено DMA прехвърляне, да я прекрати, ефективно казвайки на ядрото че тази специфична операция за четене/запис е завършена.
LDD3/глава 16 може да помогне, но някои неща се промениха след 2.6.
person
eepp
schedule
11.09.2013