Опитвам се да напиша драйвер на устройство за свързан към мрежата твърд диск. и се чудя какъв е правилният начин за заключване / отключване на опашката на заявките и къде?
Да се изяснят:
- Създадох опашка с помощта на
blk_init_queue
и предадох на тази функция функцията за обработка на заявки и заключване (т.е. семафор), което създадох. Моята функция за обработка на заявки изглежда така:
struct request *req; int ret; while ((req = blk_fetch_request(q)) != NULL) { ret = rb_transfer(req); }
мой
rb_transfer
стартира нова нишка на ядрото за обработка на заявката.След като заявката бъде обработена и трансферът на данни е завършен,
blk_end_request_cur
се извиква по тази молба.
Сега въпросът ми е как да защитя достъпа до опашката за заявки в цикъла по-горе? и в драйвера като цяло?
Опитах нещо подобно:
struct request *req;
int ret;
while ((req = blk_fetch_request(q)) != NULL) {
spin_lock(&lock);
ret = rb_transfer(req);
spin_unlock(&lock);
}
Но това се провали и доведе до заключване на ядрото.
Всички други идеи?
Отговори:
2 за отговор № 1Най- request_fn
към която минаваш blk_init_queue
се извиква, като задържите spinlock
предаден като втори аргумент и прекъсвания деактивирани. Следователно можете спокойно да предположите, че не се изпълняват паралелни нишки, които изпълняват това request_fn
. Ако обаче създадете паралелна нишка, която обработва тази заявка, синхронизирането на достъпа до заявките в тези нишки е изцяло ваша отговорност.
Най- request_fn
се нарича от __blk_run_queue_uncond
което се нарича функция от функции __blk_run_queue
и blk_execute_rq_nowait
. Ако търсите за повикване на функции __blk_run_queue
в ядрото на Linux можете да видите, че всички те го правят, като държат q->queue_lock
което е спинклокът, предаден за функциониране blk_init_queue
.