Разница между медленными системными вызовами и быстрыми системными вызовами

13

В чем разница между медленными системными вызовами и быстрыми системными вызовами? Я узнал, что медленный системный вызов может блокировать, если процесс ловит некоторые сигналы, потому что перехваченные сигналы могут пробудить заблокированный системный вызов, но я не могу точно понять этот механизм. Любые примеры будут оценены.

KayKay
источник

Ответы:

19

На самом деле в системных вызовах есть три градации.

  1. Некоторые системные вызовы возвращаются немедленно. «Немедленно» означает, что единственное, что им нужно, это немного процессорного времени. Нет жестких ограничений на то, сколько времени они могут занять (за исключением систем реального времени ), но эти вызовы возвращаются, как только они были запланированы достаточно долго.
    Эти вызовы обычно называют неблокирующими . Примерами неблокирующих вызовов являются вызовы , которые просто читают немного состояния системы, или сделать простое изменение в состоянии системы, такие как getpid, gettimeofday, getuidили setuid. Некоторые системные вызовы могут быть блокирующими или неблокирующими в зависимости от обстоятельств; например, readникогда не блокируется, если файл представляет собой канал или другой тип, который поддерживает неблокирующее чтение, и установлен O_NONBLOCKфлаг .
  2. Несколько системных вызовов могут занять некоторое время, но не навсегда. Типичный пример sleep.
  3. Некоторые системные вызовы не будут возвращаться, пока не произойдет какое-либо внешнее событие. Эти звонки считаются блокирующими . Например, readвызываемый в блокирующем файле дескриптор является блокирующим, и так оно и есть wait.

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

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

Жиль "ТАК - прекрати быть злым"
источник
спасибо большое! но если файл представляет собой канал, чтение файла неблокирует? посмотрите, что www2.hawaii.edu/~esb/2007spring.ics612/apr10.html
KayKay,
это означает «медленное чтение / запись (например, по
каналу
@KayKay: для канала вы можете использовать оба варианта, в зависимости от состояния O_NONBLOCKфлага. Если флаг установлен, системный вызов может завершиться без ожидания чего-либо еще, поэтому он не блокируется, и ядро ​​может рассматривать его как быстрый системный вызов.
Жиль "ТАК - перестань быть злым"
Вы имеете в виду, что это зависит от флага O_NONBLOCK!
KayKay
3

Медленный системный вызов - это что-то вроде TCP-сокета read () - если у вас не установлен O_ASYNC (или что-то еще), он может ждать вечно.

Быстрый системный вызов - это что-то вроде gettimeofday () или getpid (), которые возвращают информацию процессу, который ядро ​​сразу же доступно.

Дисковые чтения попадают в категорию медленных системных вызовов. Если процесс выполняет read () для истинного файла на диске, дескриптора файла, ядру, возможно, придется прочитать один или несколько дисковых блоков, чтобы удовлетворить чтение. В зависимости от структуры файловой системы на диске, это может означать чтение in-disk-inode для получения номера блока диска «косвенного блока», чтение косвенного блока для получения блока данных и последующее чтение самого блока данных. , Довольно много времени, по крайней мере, с точки зрения циклов ЦП на доступ к диску, вероятно, хуже сегодня, чем в старые добрые времена.

Я не видел этого годами, но «нижняя половина» старого кода драйвера дискового устройства Unix блокировала сигналы / прерывания, чтобы было проще поддерживать целостность файловой системы на диске. Иногда, глючный драйвер или сбойный диск никогда не доставят дисковый блок, о котором просил процесс, и процесс спит вечно. Даже убийство -9 ничего не сделало.

Брюс Эдигер
источник