2012-10-07 8 views
3

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

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

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

Я ожидаю уточнения по моему до сих пор понимания.

EDIT

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

ответ

6

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

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

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

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

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

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

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

+0

спасибо за ответ, но у меня мало сомнений в этом ............ 1. Что означает отображение здесь точно? 2. В I/O с отображением памяти, где происходит чтение и запись, то есть в кеше страницы или в адресном пространстве процесса? –

0

Для ясного объяснения того, как открывать и читать работу в Linux, вы можете прочитать this. Фрагменты кода относятся к более ранней версии ядра, но теория по-прежнему сохраняется.

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

2

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

Kernel проверяет предоставленные аргументы и разрешения доступа и т. Д., А затем либо возвращает ошибку, либо вызывает фактический системный вызов, который в этом случае равен vfs_open(). vfs_open() проверяет наличие дескриптора файла в массиве fd и выделяет файл структуры. Количество ссылок на доступ к файлам увеличивается, и fd возвращается в пользовательскую программу. Это завершает работу открытых и большинства системных вызовов в целом.

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