Происходит ли переключение контекста, когда IOCTL выдается из пространства пользователя, когда модуль ядра удерживает спин-блокировку без отключения прерываний? - PullRequest
0 голосов
/ 06 февраля 2020

У меня есть критическая секция в модуле ядра, которая защищена под spin_lock(). Я использовал spin_lock() для захвата блокировки без отключения irq или softirqs. Как мы знаем, IOCTL - это системные вызовы, которые входят в ядро ​​через программное прерывание 128 (0x80). Следовательно, если IOCTL был выдан из пространства пользователя, когда мы находимся в середине критической секции, получая spin_lock(), происходит ли переключение контекста? Что, если тот же spin_lock() используется и на бэкэнде IOCTL? Приводит ли это к тупику?

1 Ответ

2 голосов
/ 06 февраля 2020

Я использовал spin_lock () для получения блокировки без отключения irq или softirqs

IRQ / SoftIRQ не имеет ничего общего с системными вызовами. Отключение IRQ или программных IRIR необходимо, когда защищенная структура данных потенциально может использоваться из контекста прерывания . Между прочим, существуют специальные spin_lock -API, такие как spin_lock_bh()/spin_unlock_bh(), spin_lock_irq() / spin_unlock_irq() и др. c. Вы должны прочитать это руководство .

происходит ли переключение контекста?

Я не вижу ничего, чтобы остановить это (если вы имеете в виду переключение контекста syscall). Когда происходит системный вызов, он входит в режим ядра (переключение контекста) в контексте пользователя (в контексте процесса - например, в контекст процесса, который вызвал системный вызов), а не в контекст прерывания или мягкого прерывания. Поэтому, если к вашей структуре данных можно получить доступ только из пользовательского контекста - вы должны использовать обычные API блокировки для пользовательского контекста.
Что касается переключения контекста в режиме ядра при удержании спин-блокировки - это не может произойти, потому что сама по себе спин-блокировка отключает preemption:

static inline void __raw_spin_lock(raw_spinlock_t *lock)
{
    preempt_disable();
    spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);
    LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock);
}

Тогда выгрузить может только код с более высоким приоритетом (IRQ, softIRQ), но ему нечего беспокоиться (с точки зрения взаимоблокировок), если этот код с более высоким приоритетом победил не пытайтесь получить блокировку, которую вы держите.

Что, если тот же spin_lock () будет использоваться и в бэкэнде IOCTL?

Это определенно будет "вращаться", пока вы не отпустите блокировку.

Приводит ли это к тупику?

В зависимости от того, как вы будет использовать его.

PS что не так с мьютексами?


Читайте также:

...