Операционная система: не является ли неправильной практикой переключаться на другой процесс с заблокированным прерыванием? - PullRequest
0 голосов
/ 31 января 2020

Я видел этот фрагмент кода на диске, читаемый в Linux 0,11 ядре:

static inline void lock_buffer(struct buffer_head * bh)
{
    cli();
    while (bh->b_lock)
        sleep_on(&bh->b_wait);
    bh->b_lock=1;
    sti();
}

IIU C, cli() будет блокировать прерывание (не блокируя все, как описано здесь: https://c9x.me/x86/html/file_module_x86_id_31.html, но, тем не менее, блокирует некоторые прерывания, что означает, что он меняет поведение по умолчанию).

И sleep_on вызовет schedule, что передаст поток управления другому процессу.

Однако меня смущает то, что здесь мы переключимся на другой процесс с заблокированными прерываниями, который кажется подверженным ошибкам, потому что другой процесс должен ожидать поведение по умолчанию. Так это правильно написанный фрагмент кода (если так, почему?) Или это просто неправильно написанный код, который вызовет неожиданное поведение?

Ответы [ 2 ]

1 голос
/ 31 января 2020

Я предполагаю, что обработчик прерываний на диске будет активен (& bh-> b_wait), что может привести к пропущенному пробуждению, если прерывания не были отключены в процессе, ожидающем этот блок.

Помните, что условные переменные (sleep_on, wakeup) не имеют памяти: sleep_on будет приостанавливаться до вызова wakeup; не имеет значения, вызывается ли wakeup непосредственно перед sleep_on.

С момента тестирования bh-> b_lock вызывающая сторона работает с обработчиком прерываний; таким образом cli (или, более типично unix splbio ()) блокирует обработчик прерываний, предотвращая гонку.

Так как ядро ​​сохраняет состояние прерывания (маска, приоритет, ...) с состоянием процесса, когда sleep_on вызывает перепланирование, наиболее вероятно, что прерывания будут повторно разрешены; или хотя бы со временем будет. Прерывание диска будет в конечном счете выполнено, пробуждая этот процесс.

Когда этот процесс перепланирован, его сохраненное состояние прерывания (отключено) будет восстановлено, так что проверка и назначение b_lock также предотвратят помехи от обработчик прерываний диска.

0 голосов
/ 31 января 2020

Думал об этом снова. Я думаю, что это предполагаемое поведение. Это означает, что до окончания чтения с диска (вызывается unlock_buffer) все последующие выполнения будут в режиме бесперебойного режима (прерывание заблокировано). Когда буфер разблокирован и заголовок очереди проснулся, будет выполнено

while (bh->b_lock)
  sleep_on(&bh->b_wait);
bh->b_lock=1;
sti();

, а поскольку мы находимся в режиме бесперебойного режима, он будет выполняться до sti() без переключения на другой процесс. Таким образом, другие процессы, ожидающие того же сигнала, снова будут находиться в режиме ожидания (bh->b_lock равно 1), когда запланировано, и только 1 процесс продолжит свое выполнение.

...