системный вызов read() выполняет копирование данных вместо передачи ссылки

#c #linux #process #ipc

#c #linux #процесс #ipc

Вопрос:

read() Системный вызов заставляет ядро копировать данные вместо передачи буфера по ссылке. В интервью меня спросили о причине этого. Лучшее, что я мог придумать, это:

  1. Чтобы избежать одновременной записи в один и тот же буфер между несколькими процессами.
  2. Если процесс пользовательского уровня попытается получить доступ к буферу, сопоставленному области виртуальной памяти ядра, это приведет к сбою в сегменте.

Как оказалось, интервьюер не был полностью удовлетворен ни одним из этих ответов. Я был бы очень признателен, если бы кто-нибудь мог уточнить вышесказанное.

Ответ №1:

Реализация с нулевым копированием означала бы, что процессу пользовательского уровня должен быть предоставлен доступ к буферам, используемым внутренне ядром / драйвером для чтения. Пользователю пришлось бы выполнить явный вызов ядра, чтобы освободить буфер после того, как они с ним закончили.

В зависимости от типа считываемого устройства буферы могут представлять собой нечто большее, чем просто область памяти. (Например, некоторым устройствам может потребоваться, чтобы буферы находились в определенной области памяти. Или они могли бы поддерживать запись только в фиксированную область памяти, которая будет предоставлена им при запуске.) В этом случае неспособность пользовательской программы «освободить» эти буферы (чтобы устройство могло записать в них больше данных) может привести к тому, что устройство и / или его драйвер перестанут функционировать должным образом, чего пользовательская программа никогда не должна быть способна сделать.

Комментарии:

1. Обратите внимание, что, например, недавно в ядрах реализована поддержка ‘splice’, что означает, что для драйверов fuse теперь существуют пути с нулевым копированием

Ответ №2:

Буфер указан вызывающим объектом, поэтому единственный способ получить данные там — скопировать их. И API определен так, как он есть, по историческим причинам.

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

Комментарии:

1. С MAP_PRIVATE запись в map не изменяет файл.

Ответ №3:

Возможно, я был готов оспорить утверждение интервьюера. Буфер в read() вызове предоставляется пользовательским процессом и, следовательно, поступает из пользовательского адресного пространства. Также не гарантируется, что они будут выровнены каким-либо определенным образом по фреймам страницы. Это затрудняет выполнение того, что необходимо для выполнения ввода-вывода непосредственно в буфер ie. сопоставьте буфер с адресным пространством драйвера устройства или подключите его к DMA. Однако в ограниченных обстоятельствах это может быть возможно.

Кажется, я помню, что подсистема BSD, используемая Mac OS X для копирования данных между адресными пространствами, была оптимизирована в этом отношении, хотя я могу полностью ошибаться.