Команды , например sed
, являются программами, а программы - это кодированная логика внутри файла, и эти файлы находятся где-то на жестком диске. Однако, когда команды выполняются, копия их файлов с жесткого диска помещается в оперативную память , где они оживают и могут что-то делать и называются процессами .
Процессы могут использовать другие файлы, читать или записывать их, и если они это делают, эти файлы называются открытыми файлами. Существует команда , чтобы получить список всех открытых файлов всех запущенных процессов: lsof
.
Итак, что меня интересует, так это то, что двойная жизнь команды, одна на жестком диске, другая в ОЗУ, также справедлива для других типов файлов, например для тех, у которых нет запрограммированной логики, но они просто контейнеры для данные.
Я предполагаю, что файлы, открытые процессами, также загружаются в оперативную память. Я не знаю, правда ли это, это просто интуиция.
Пожалуйста, кто-нибудь может понять это?
Ответы:
Это неправильно (в общем). Когда программа выполняется (через execve (2) ...), процесс (выполняющий эту программу) меняет свое виртуальное адресное пространство, и ядро реконфигурирует MMU для этой цели. Читайте также о виртуальной памяти . Обратите внимание, что прикладные программы могут изменять свое виртуальное адресное пространство с помощью mmap (2) &
munmap
& mprotect (2) , также используемого динамическим компоновщиком (см. Ld-linux (8) ). Смотрите также madvise (2) и posix_fadvise (2) & mlock (2) .Будущие ошибки страниц будут обрабатываться ядром для загрузки (лениво) страниц из исполняемого файла. Читайте также о побеждении .
Ядро поддерживает большой кеш страниц . Читайте также о копировании при записи . Смотрите также readahead (2) .
Для системных вызовов, таких как read (2) и write (2), также используется кеш страниц. Если данные для чтения находятся в нем, дисковый ввод-вывод не будет выполнен. Если требуется дисковый ввод-вывод, считанные данные, скорее всего, будут помещены в кеш страниц. Таким образом, на практике, если вы выполняете одну и ту же команду дважды, может случиться, что во второй раз на диск не будет выполнен физический ввод-вывод (если у вас старый вращающийся жесткий диск - не SSD - вы можете услышать это; или внимательно наблюдайте за светодиодом вашего жесткого диска).
Я рекомендую прочитать книгу « Операционные системы: три простых компонента» (бесплатно скачивается, один файл PDF на главу), которая объясняет все это.
Смотрите также Linux Ate My RAM команды и работать , как
xosview
,top
,htop
илиcat /proc/self/maps
илиcat /proc/$$/maps
(см прок (5) ).PS. Я сосредоточен на Linux, но другие ОС также имеют виртуальную память и кеш страниц.
источник
Нет, файл не будет автоматически считан в память при его открытии. Это было бы ужасно неэффективно.
sed
Например, он читает строку ввода построчно, как и многие другие инструменты Unix. Он редко должен хранить в памяти больше текущей строки.С
awk
этим же. Он читает запись за раз, которая по умолчанию является строкой. Если вы храните части входных данных в переменных, это, конечно, будет лишним 1 .Некоторые люди имеют привычку делать такие вещи, как
Поскольку оболочке придется полностью развернуть
$(cat file)
подстановку команд перед запуском даже первой итерацииfor
цикла, все это будет считаноfile
в память (в память, используемую оболочкой, выполняющейfor
цикл). Это немного глупо, а также не элегантно. Вместо этого нужно сделатьЭто будет обрабатывать
file
построчно (но прочитайте Understanding "IFS = read -r line" ).Обработка файлов строка за строкой в оболочке требуется редко, так как большинство утилит в любом случае ориентированы на строки (см. Почему использование цикла оболочки для обработки текста считается плохой практикой? ).
Я работаю в области биоинформатики, и при обработке огромных объемов геномных данных я не смог бы многое сделать, если бы не хранил в памяти только те части данных, которые были абсолютно необходимы. Например, когда мне нужно отбросить биты данных, которые могут быть использованы для идентификации лиц из набора данных объемом 1 терабайт, содержащего варианты ДНК в файле VCF (поскольку данные этого типа не могут быть обнародованы), я делаю построчно обработка с помощью простой
awk
программы (это возможно, поскольку формат VCF ориентирован на строки). Я не читаю файл в память, обрабатываю его там и снова записываю! Если файл был сжат, я бы передал его черезzcat
илиgzip -d -c
, который, посколькуgzip
выполняет потоковую обработку данных, также не прочитал бы весь файл в память.Даже с форматами файлов, которые не ориентированы на строки, такими как JSON или XML, существуют потоковые парсеры, которые позволяют обрабатывать огромные файлы, не сохраняя их все в оперативной памяти.
С исполняемыми файлами это немного сложнее, поскольку разделяемые библиотеки могут быть загружены по требованию и / или могут быть разделены между процессами (см. , Например, Загрузка разделяемых библиотек и использование ОЗУ ).
Кеширование - это то, о чем я здесь не упоминал Это действие использования оперативной памяти для хранения часто используемых фрагментов данных. Меньшие файлы (например, исполняемые файлы) могут кэшироваться ОС в надежде, что пользователь сделает много ссылок на них. Помимо первого чтения файла, последующие обращения будут осуществляться к ОЗУ, а не к диску. Кэширование, подобно буферизации ввода и вывода, обычно в значительной степени прозрачно для пользователя, и объем памяти, используемой для кэширования, может динамически изменяться в зависимости от объема ОЗУ, выделенного приложениями и т. Д.
1 Технически, большинство программ, вероятно, считывают порцию входных данных за раз, либо используя явную буферизацию, либо неявно через буферизацию, как это делают стандартные библиотеки ввода / вывода, а затем последовательно представляют эту порцию в коде пользователя. Гораздо эффективнее читать кратные размеры блока диска, чем, например, символ за раз. Этот размер куска редко будет больше, чем несколько килобайт.
источник
awk
,{ a[i++] = $0 }
добавил бы все строки входного файла в массивa
. Вы также можете поискать функцию Cmmap()
, но ее использование может быть немного не по теме.sed
,awk
и другие линейно-ориентированные программы не читают строки в памяти за раз, потому что простые текстовые файлы не содержат строкового индекса, а API файловой системы и низкоуровневое оборудование для хранения считывают один или несколько «секторов» (обычно 512 или 1024 байта) за один раз. Я был бы удивлен, если бы операционная система считала в память менее 8 КБ до обработки первой строки.sed
будет считывать в память только одну строку за раз, стоит упомянуть, что операционная система будет использовать свободный оперативный памяти для кэширования файлов, чтобы к ним можно было быстро получить доступ. Если вы работаетеsed
с меньшим файлом, вполне возможно, что ОС будет кэшировать весь файл в памяти, и операция будет выполнена полностью в оперативной памяти. Смотрите: en.wikipedia.org/wiki/Page_cacheНет. Хотя в наши дни концерты ОЗУ фантастические, было время, когда ОЗУ было очень ограниченным ресурсом (я изучал программирование на VAX 11/750 с 2 МБ ОЗУ), и единственной вещью в ОЗУ были активные исполняемые файлы и страницы данных. активных процессов и файлов данных, которые были в буферном кеше.
Буферный кеш был очищен, а страницы данных были заменены. И часто в разы. Исполняемые страницы только для чтения были перезаписаны, а таблицы страниц помечены так, что, если программа снова коснется этих страниц, они будут выгружены из файловой системы. Данные были выгружены из свопинга. Как отмечалось выше, библиотека STDIO собирала данные в блоках и получала их программой по мере необходимости: fgetc, fgets, fread и т. Д. С помощью mmap файл может быть отображен в адресное пространство процесса, как это делается с помощью объекты общей библиотеки или даже обычные файлы. Да, вы можете иметь некоторую степень контроля, если он находится в оперативной памяти или нет (mlock), но это только так далеко (см. Раздел кода ошибки mlock).
источник