Хотя за различными современными устройствами хранения скрываются действительно сложные технологии, обычному системному администратору не обязательно знать все детали. На самом деле системные администраторы должны всегда помнить только об одном:
Оперативной памяти никогда не бывает достаточно.
Хотя это утверждение может показаться шуткой, многие конструкторы операционных систем тратят очень много времени, стараясь уменьшить следствия этого вполне реального недостатка. Для этого они реализуют виртуальную память — способ объединить ОЗУ с более медленным хранилищем, чтобы это выглядело, как будто в компьютере установлено больше памяти.
4.3.1. Простое представление о виртуальной памяти
Давайте начнём с гипотетического приложения. Объём машинного кода этого приложения равен 10000 байт. Это приложение также требует 5000 байт для хранения данных и буферов ввода/вывода. Это значит, что для работы с этим приложением в памяти должно быть свободно 15000 байт, и если не хватит всего одного байта, приложение не сможет запуститься.
Это требование 15000 байт называется адресным пространством приложения. Это число уникальных адресов, необходимых для размещения приложения и данных. В первых компьютерах доступный объём ОЗУ должен был превышать объём адресного пространства самого большого запускаемого приложения, в противном случае приложение не запускалось и выдавало ошибку.
Затем появились так называемые оверлеи, когда программисты пытались решить проблему, определяя, какие части приложения должны находиться в памяти в данный момент времени. Таким образом, код, выполняемый только при инициализации, можно было переписать кодом, который будет использоваться в процессе работы. Хотя оверлеи помогли справиться с нехваткой памяти, этот подход был очень сложным и провоцировал ошибки. Оверлеи также не могли решить проблему нехватки памяти во время выполнения в масштабе системы. Другими словами, программа с оверлеями могла требовать для выполнения меньше памяти, чем программа без оверлеев, но если в системе для неё не хватало памяти, результат был прежним — возникала ошибка нехватки памяти.
С виртуальной памятью понятие адресного пространства приложения приобрело другой смысл. Вместо того чтобы определять, как много памяти нужно приложению, операционная система с виртуальной памятью постоянно пытается найти ответ на вопрос, «насколько мало памяти нужно приложению для работы?»
Хотя на первый взгляд кажется, что нашему гипотетическому приложению для работы нужны все 15000 байт, но давайте вернёмся к нашему разговору в разделе 4.1 Особенности доступа к хранилищу — обращения к памяти обычно имеют последовательный и локальный характер. Поэтому для работы приложения в любой момент времени требуется меньше 15000 байт (обычно намного меньше). Давайте посмотрим, какого рода обращения к памяти требуются для выполнения одной машинной инструкции:
Инструкция считывается из памяти.
Из памяти также считываются данные, требуемые для выполнения этой инструкции.
После выполнения инструкции, её результаты снова записываются в память.
Сколько именно байт требует каждое обращение к памяти, зависит от архитектуры процессора, самой инструкции и типа данных. Однако, даже если для каждого вида обращения к памяти требуется 100 байт памяти, необходимые 300 байт — это намного меньше, чем всё адресное пространство приложения (15000 байт). Если бы можно было найти способ следить за требованиями приложения к памяти в процессе его работы, можно было запускать приложение, выделяя ему меньше памяти, чем требуется для всего адресного пространства.
Но при этом возникает один вопрос:
Если в определённый момент времени в памяти находится только часть приложения, где же находится остальное?
4.3.2. Дополнительное хранилище — основополагающее понятие виртуальной памяти
Ответить на этот вопрос можно просто: остальная часть приложения находится на диске. Другими словами, диск служит своего рода дополнением оперативной памяти; большое хранилище в некотором роде «поддерживает» более быструю память меньшего объёма. На первый взгляд может показаться, что это создаёт большие проблемы производительности, ведь диски работают намного медленнее памяти.
Хотя это так, тем не менее, можно воспользоваться особенностями последовательного и локального доступа приложений и решить большую часть проблем производительности, возникающих при использовании диска для расширения ОЗУ. Для этого подсистема виртуальной памяти организована так, что она пытается оставить в памяти только те части приложения, которые нужны в данный момент (или, скорее всего, понадобятся в ближайшем будущем), и избавиться от них, как только они будут не нужны.
В этом смысле это похоже на кэш и память: быстрое хранилище небольшого объёма и большое медленное хранилище вместе становятся большим и одновременно быстрым хранилищем.
Осознав это, давайте перейдём к более глубокому изучению этого процесса.