2010-05-05 2 views
8

В Linux, когда вы делаете блокирующий вызов ввода-вывода как чтение или принятие, что на самом деле происходит?Как работает Linux-блокировка ввода-вывода?

Мои мысли: процесс вынимается из очереди выполнения, помещается в ожидающее или блокирующее состояние в очереди ожидания. Затем, когда выполняется tcp-соединение (для принятия) или жесткий диск готов или что-то для чтения файла, возникает аппаратное прерывание, которое позволяет тем процессам, которые ожидают пробуждения и запуска (в случае чтения файла, как это сделать Linux знает, какие процессы нужно пробуждать, так как может быть много процессов, ожидающих в разных файлах?). Или, возможно, вместо аппаратных прерываний, сам процесс сам опроса проверяет наличие. Не уверен, помощь?

+0

Вы в значительной степени ударил гвоздь на голове (за последнее замечание, за исключением, нет опроса, по большей части). Множественное мультиплексирование между mulitiple официантами и файлами выполняется ядром, которое является невидимым процессом, который координирует такие вещи от имени всех других процессов. –

ответ

0

Прочитайте это: http://www.minix3.org/doc/

Это очень, понятно, очень легко понять объяснение. Обычно это относится и к Linux.

0

Effectivly метод будет возвращает только тогда, когда файл будет готов для чтения, когда данные на сокет, когда соединение прибыло ...

Чтобы убедиться, что он может вернуться немедленно вы, вероятно, хотите использовать Select Системный вызов, чтобы найти готовый дескриптор файла.

11

Каждое устройство Linux, кажется, реализована несколько иначе, и предпочтительный способ, кажется, изменяется каждые несколько Linux выпускает по мере добавления безопаснее/быстрее функции ядра, но, как правило:

водитель
  1. Устройство создает чтения и пишите очереди ожидания для устройства.
  2. Любой процесс, который хочет подождать для ввода/вывода, помещается в соответствующую очередь ожидания . Когда происходит прерывание , обработчик просыпается один или несколько ожидающих потоков. (Очевидно, что потоки не запускаются немедленно, поскольку мы находимся в контексте прерывания , но добавлены в очередь планирования ядра ).
  3. Когда запланировано ядро, поток проверяет, соответствуют ли условия - если нет , он возвращается в очередь ожидания.

Типичный пример (слегка упрощенный):

В драйвере при инициализации:

init_waitqueue_head(&readers_wait_q); 

В функции считывания драйвера:

if (filp->f_flags & O_NONBLOCK) 
    { 
     return -EAGAIN; 
    } 
    if (wait_event_interruptible(&readers_wait_q, read_avail != 0)) 
    { 
     /* signal interrupted the wait, return */ 
     return -ERESTARTSYS; 
    } 
    to_copy = min(user_max_read, read_avail); 
    copy_to_user(user_buf, read_ptr, to_copy); 

то обработчик прерываний только вопросы:

wake_up_interruptible(&readers_wait_q); 

Обратите внимание, что wait_event_interruptible() - это макрос, который скрывает цикл, который проверяет условие - read_avail != 0 в этом случае - и повторно добавляет в очередь ожидания снова, если пробуждается, когда условие не является истинным.

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

См Linux Device Driver книга для более подробной информации - PDF доступны здесь: http://lwn.net/Kernel/LDD3

Смежные вопросы