Работа открытого системного вызова

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

Итак, вот мой вопрос как работает системный вызов open?

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

Я ожидаю разъяснений по моему до сих пор пониманию.

ИЗМЕНИТЬ

Мое предыдущее понимание, написанное выше, почти неверно, для правильного объяснения обратитесь к принятому ответу Павла.


person Akashdeep Saluja    schedule 07.10.2012    source источник


Ответы (3)


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

На самом деле системный вызов open() только создает файловый дескриптор, который затем может использоваться как mmap() или read().

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

Стандартный подход ввода-вывода (с использованием write() и read()) включает выполнение системного вызова, который затем копирует данные из (или, если вы пишете) кэша страниц в буфер, выбранный приложением. В дополнение к этому непоследовательный доступ требует другого системного вызова lseek(). Системные вызовы дороги, как и копирование данных.

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

EDIT: я вижу, что мне также нужно объяснить пейджинг памяти. В большинстве современных архитектур есть физическая память, которая является реальной частью оборудования, и виртуальная память, которая создает адресные пространства для процессов. Ядро решает, как адреса в виртуальной памяти сопоставляются с адресами в физической памяти. Наименьшая единица — это страница памяти (обычно, но не всегда 4К). Это не обязательно должно быть сопоставление 1:1, например, все страницы виртуальной памяти могут быть сопоставлены с одним и тем же физическим адресом.

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

person Paweł Dziepak    schedule 07.10.2012
comment
спасибо за ответ, но у меня мало сомнений в этом ............ 1. что именно здесь означает отображение? 2. В отображенном на память вводе-выводе, где происходит чтение и запись, т. е. в кэше страниц или в адресном пространстве процесса? - person Akashdeep Saluja; 07.10.2012

Павел прекрасно объяснил, как выполняется чтение/запись. Позвольте мне объяснить первоначальный вопрос: как работает fopen(3): когда процесс пользовательского пространства встречает fopen (определенный в libc или любой другой библиотеке пользовательского пространства), он переводит его в системный вызов open(2). Во-первых, он берет аргументы из fopen, записывает их в регистры, специфичные для архитектуры, вместе с номером системного вызова open(). Этот номер сообщает ядру, какую программу пользовательского пространства системного вызова хочет запустить. После загрузки этих регистров процесс пользовательского пространства прерывает ядро ​​(через softirq, традиционно INT 80H на x86) и блокируется.

Ядро проверяет предоставленные аргументы, права доступа и т. д., а затем либо возвращает ошибку, либо вызывает фактический системный вызов, который в данном случае vfs_open(). vfs_open() проверяет доступный дескриптор файла в массиве fd и выделяет файл структуры. Счетчик ссылок файла, к которому осуществляется доступ, увеличивается, и fd возвращается в программу пользователя. На этом работа open и большинства системных вызовов в целом завершена.

open() вместе с read()/write(), за которым следует close(), несомненно, гораздо более длительный процесс, чем наличие файла с отображением памяти в буферном кеше.

person Vishal Sahu    schedule 26.02.2016

Для ясного объяснения того, как открыты и читаются в Linux, вы можете прочитать это. Фрагменты кода взяты из более старой версии ядра, но теория все еще верна.

Вам по-прежнему нужно будет использовать системный вызов open(), чтобы получить действительный файловый дескриптор, который вы передадите в mmap(). Что касается того, почему mmaped IO быстрее, это потому, что нет копии данных из (в) пространства пользователя в (из) буферов пространства ядра, что происходит с системными вызовами чтения и записи.

person itisravi    schedule 07.10.2012