/ / Правилен начин за заключване на опашката в блокиран драйвер на устройство по време на обслужване на заявки - linux, linux-kernel, linux-device-driver

Правилен начин за заключване на опашката в драйвер за блоково устройство, докато се изпълняват заявки - linux, linux-kernel, linux-device-driver

Опитвам се да напиша драйвер на устройство за свързан към мрежата твърд диск. и се чудя какъв е правилният начин за заключване / отключване на опашката на заявките и къде?

Да се ​​изяснят:

  1. Създадох опашка с помощта на blk_init_queue и предадох на тази функция функцията за обработка на заявки и заключване (т.е. семафор), което създадох.
  2. Моята функция за обработка на заявки изглежда така:

    struct request *req;
    int ret;
    while ((req = blk_fetch_request(q)) != NULL) {
    ret = rb_transfer(req);
    }
    
  3. мой rb_transfer стартира нова нишка на ядрото за обработка на заявката.

  4. След като заявката бъде обработена и трансферът на данни е завършен, 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.