Как делает Linux, блокирующий ввод-вывод, на самом деле работают?

В Linux, когда Вы делаете блокирование i/o вызовом как чтение или принимаете, что на самом деле происходит?

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

8
задан caf 6 May 2010 в 02:51
поделиться

3 ответа

Фактически метод вернется только тогда, когда файл будет готов к чтению, когда данные находятся в сокете, когда установлено соединение ...

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

0
ответ дан 5 December 2019 в 14:01
поделиться

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

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

-1
ответ дан 5 December 2019 в 14:01
поделиться

Каждое устройство 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 в данном случае - и повторно добавляет в очередь ожидания, если разбужен, когда условие не истинно.

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

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

13
ответ дан 5 December 2019 в 14:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: