[МУЗЫКА] [МУЗЫКА] [МУЗЫКА] Теперь мы поговорим о таком интересном понятии, как виртуальная память. Virtualis — по-латыни означает объект, который не существует, но может возникнуть. И вообще, virtual — это что-то выдуманное. Так вот, представьте себе, что у вас есть память, ну скажем, 1 мегабайт. Я буду говорить в примерах, которые мне привычны, в старые времена. А вам хочется программировать, естественно, в большей памяти, скажем, в 100 мегабайт. Так вот, можно придумать систему, которая будет в каком-то смысле вас обманывать, создавать у вас иллюзию, что у вас есть 100 мегабайт. И вот это и называется виртуальная память. Давайте разберемся, как это делается. Память делится на страницы фиксированного размера. Принято 2 или 4 килобайта. И дальше вы работаете только с математическими адресами. Математический адрес — это пара. Номер страницы и смещение на три страницы. Никаких прямых физических адресов нет. Каждый раз, когда вам нужно обратиться к объекту, вы пользуетесь математическим адресом и начинаете с того, что по номеру страницы операционная система лезет в так называемую таблицу страниц. Есть такой объект в операционной системе — таблица страниц. В этой таблице по номеру страницы можно определить, находится ли страница в оперативной памяти, и если находится, то прямо в таблице адрес ее начала. Или если она не находится, то где ее найти на диске? То есть вся идея в том, что у вас есть, если вы помните, 1 мегабайт оперативной памяти, сколько-то страниц у вас там помещается, а все остальные страницы хранятся на диске. И вот вы по номеру страницы полезли в таблицу страниц, определили, что нужная страница находится в памяти, получили ее адрес начала и прибавляете к нему смещение. Тем самым вы получаете настоящий физический адрес, по которому вы начинаете писать. Ежели страницы в памяти нет, то возникает прерывание операционной системы, и она своими способами там на диске ищет нужный адрес, считает нужную страницу в память, и дальше все, как раньше мы говорили. Адрес в начало, плюс смещение — вот ваш физический адрес. Заметьте, что это процесс такой сложный, и если у вас страницы не оказалось в памяти, и вам надо подкачать ее с диска, то, возможно, вам какие-то страницы придется выгнать из оперативной памяти на диск, выгрузить. Так что ни о какой скорости там даже говорить вообще не приходится. То есть давайте повторим главный принцип виртуальной памяти: виртуальная память запрещает использование прямых физических адресов, только математические. Заметьте, они относительные такие — номер страницы и смещение в эту страницу. Итак, математический адрес — это пара: номер страницы и смещение, а физический адрес — это адрес нормальной оперативной памяти. Так вот, перед каждым использованием математического адреса, его надо преобразовать в физический адрес. Если страницы нет в оперативной памяти, то говорить о скорости тут вообще не приходится. То есть это будет тысячи больших, тысячи команд. Если находится, то прибавляется смещение. Причем это тоже некоторое замедление, и нельзя сказать, что это хорошо. Но я же вам в самом начале сказал, что вас обманывают, вам говорят, что у вас есть 100 мегабайтов, хотя реально есть только один мегабайт. Но зато программировать удобнее. Просто программировать в большой памяти, и все программисты это понимают, намного легче, чем программировать в маленькой, ограниченной памяти. Поэтому за такой обман приходится платить. И люди обычно на это идут. То есть в наше время стоимость труда программиста много дороже, чем стоимость машины. Слушайте, вот тут, поскольку я старый программист, не могу не сказать, что когда-то машины стоили миллионы (в советское время — миллионы рублей), а зарплата программиста была 100–200 рублей. И тогда надо было экономить машинное время, и, в общем, некоторые усилия предпринимались, чтобы как-то сэкономить использование машины. А с течением времени, сегодня вот компьютер можно купить тысяч за 30–40, а зарплата программиста, как минимум, в два раза больше. То есть сегодня все происходит наоборот — компьютеры дешевые (все относительно, но, тем не менее, я настаиваю на этом), а рабочая сила программистов — дорогая. Поэтому надо экономить усилия программистов. И в этом смысле виртуальная память — отличный пример, что вы экономите усилия программистов, расплачиваясь за это некоторым понижением эффективности использования компьютера. Черт с ним, зато программисты работают в более комфортных условиях, и это для нас важно. Тем не менее, можно бороться с виртуальной памятью, и ее тоже ускорять. Во-первых, оказалось, что есть такое понятие — рабочее множество страниц. То есть в любой программе всегда есть какой-то процент, 5–10 страниц, в которых происходит 90–95 % обращений. То есть далеко не все страницы программы и их данные используются равномерно. Так вот, такое множество страниц, которое в основном работает, называется рабочим множеством страниц. И современная операционная система умеет их выделять и сохранять в основную оперативную память. Поэтому чаще всего, когда вы работаете с виртуальной памятью, в 90 % случаев страница в памяти находится. Хотя, конечно, преобразование, обратиться к таблице страниц, прибавить смещение, все равно занимает какое-то время. Но уже это исчезающе мало, по сравнению с поиском страницы на диске. Чтобы сэкономить время в работе с этой таблицей страниц, придумали специальный механизм TLB (Translation lookaside buffer). Это тоже кэш-память, о которой мы уже говорили, только очень специализированная. В этой кэш-памяти, в этой TLB, оседают адреса начала страниц, которые чаще всего используются. И поскольку TLB хранится в быстрой кэш-памяти, то преобразование происходит быстрее. Таким образом, происходит экономия на времени чтения адреса начала страницы. Теперь поговорим об обработке ошибок. При работе с памятью регулярно возникают ошибки. Вы знаете, я не большой специалист в физике, но инженеры говорят, что прилетит какая-то альфа-частица и может исказить какой-то вид в памяти. Я не ручаюсь, что так это или не так, но меня так учили. Ну и теперь я так учу. Во всяком случае, даже сегодня (хотя сегодня электроника стала намного более надежной, чем, скажем, 20 лет назад), тем не менее, память бывает сбоит. Как с этим бороться? Опять-таки инженеры знают, что надежность — это избыточность. Есть такая знаменитая теорема, по-моему, теорема Котельникова, что можно сделать сколько угодно надежное устройство из скольки угодно ненадежных элементов. Вот вслушайтесь: элементы сколько угодно ненадежны, но можно даже из них сделать сколь угодно надежные устройства. То есть понятно за счет чего? За счет избыточности. Все блоки повторять, дублировать, троировать, учетверять и так далее, делать специальные схемы сравнения — и можно добиться надежности. Но с точки зрения работы с памятью, все относительно проще, а именно, проще всего к каждому байту добавить девятый бит — бит четности называется. То есть складываете все разряды этого байта и контрольный бит тоже, как договоримся. Если получается 0 — то значит, все в порядке. А если 1, то значит, какой-то бит исказился. То есть в правильно записанном байте сумма всех битов должна быть равна нулю. Поскольку бит четности определяет ошибку, но не позволяет исправить ошибку, были придуманы более сложные коды. Самый популярный из них — это код Хэмминга. Я не хочу влезать в технические детали, но можно на 16 разрядов добавить 5 контрольных разрядов, в которых будут храниться контрольные суммы побитовые по 1-й, по 2-й, по 4-й, по 8-й позициям. И вот наличие вот этих пяти дополнительных битов позволяет а) обнаружить ошибку, если какая-то позиция испортилась; б) исправить ее. На самом деле, существуют и более сложные коды. Это вообще тема отдельного курса — теория кодирования. И надо сказать, что эта теория кодирования на Западе приписывается Клоду Шеннону, а у нас Котельникову и его школе. Был такой академик Котельников. Есть такая теорема кодирования Шеннона, которая на Западе все вот именно так производит, так вот я утверждаю, что ровно эта теорема была опубликована еще в конце 30-х годов в докладах Академии наук, которые переводились на английский, на французский, на немецкий языки. Ну так часто бывало и раньше, к сожалению, это бывает и сейчас. Тем не менее, мне важно сказать вот что: есть специальные системы кодирования, которые позволяют не только находить ошибки, но и исправлять их. Но еще раз повторю, что это тема отдельного курса.