Откуда программа выделяет память?

Как программист на C и C++, я использовал malloc и new для выделения памяти. Мне просто интересно: как ОС распределяет память?

  1. Выделяет ли он из ОЗУ, или с жесткого диска, или откуда-то еще?

  2. Могу ли я заимствовать память с жесткого диска на всякий случай?


person samprat    schedule 04.09.2013    source источник
comment
дублируется stackoverflow.com/questions/2308751/what-is-a-memory-heap   -  person DGomez    schedule 05.09.2013
comment
en.wikipedia.org/wiki/Virtual_memory   -  person Carl Norum    schedule 05.09.2013
comment
Я думаю, вы только что изобрели виртуальную память.   -  person MK.    schedule 05.09.2013
comment
@DGomez: Ты меня обманул. Я провел тщательное голосование, прежде чем понял, что ни один из этих ответов даже близко не подходит к ответу на этот вопрос.   -  person Mooing Duck    schedule 05.09.2013
comment
Нет!!!! Виртуальная память, как и в компьютерной архитектуре, — это одно. управление памятью, как и в куче, стеке и статическом хранилище, — это совершенно разные вещи.   -  person paulsm4    schedule 05.09.2013
comment
Пожалуйста, укажите, какие предварительные исследования вы проводили. Таких вопросов должно быть две или три сотни уже только на SO.   -  person Lightness Races in Orbit    schedule 05.09.2013
comment
@paulsm4: А? Вопросы, которые задает ОП, в значительной степени охватываются типичной реализацией виртуальной памяти...   -  person Oliver Charlesworth    schedule 05.09.2013
comment
@Ligtnesss, я немного знал о памяти ОС, виртуальной памяти, куче или памяти для глобальных и статических переменных, но я не могу все связать.   -  person samprat    schedule 05.09.2013


Ответы (4)


На самом деле все гораздо сложнее, чем вы думаете. ОС все считает «страницами», она разбивает оперативную память на страницы, а жесткий диск на страницы. Когда ваша программа запускается, она проверяет, сколько памяти занимает ваш исполняемый файл, выбирает для него несколько страниц ОЗУ и назначает эти страницы вашей программе. Если в ОЗУ нет «полезных» страниц, некоторые страницы в ОЗУ берутся постарше и сохраняются на жестком диске где-то спрятанным, а затем отдаются вам.

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

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

Вот схема, которая не имеет смысла

C++ addresses           RAM         hard drive
+------------+    +------------+  +------------+  
| 0x00010000 |\ ->| 0x00010000 |  | 0x00010000 | 
+------------+ X  +------------+  +------------+
| 0x00020000 |/ ->| 0x00020000 |  | 0x00020000 |
+------------+    +------------+  +------------+
| 0x00030000 |-->?         /----->| 0x00030000 |
+------------+            /       +------------+
| 0x00040000 |-----------/        | 0x00040000 |
+------------+
|    etc     |

Итак, в этом коде ваш код имеет стековую память 0x00010000-0x0002FFFF, и вы выделили некоторую динамическую память, и это находится в 0x0004000. НАСКОЛЬКО ВЫ ЗНАЕТЕ! На самом деле, когда вы обращаетесь к адресу 0x0002000, операционная система говорит: «О, я сохранила эту вашу страницу по адресу ОЗУ 0x00010000» и считывает эти значения для вас. Вы давно не касались страницы 0x00040000, поэтому операционная система сохранила ее на жестком диске по адресу 0x00030000, но перенесет ее в оперативную память, если вы попытаетесь ее использовать. Операционная система еще не предоставила вам адрес 0x00030000, поэтому, если вы попытаетесь его использовать, операционная система сообщит вам, что адрес не имеет реальных страниц, и вы получите ошибку сегментации (segfault). Что делает это интересным, так это то, что когда вы запрашиваете большой непрерывный фрагмент, такой как вектор, операционная система может предоставить вам любые старые страницы, которые она находит, и ей не нужно беспокоиться, являются ли они смежными или нет. Они выглядят смежными с вашей программой, и это все, что имеет значение.

Это также позволяет операционной системе скрывать память одной программы от другой, что не позволяет им читать или изменять пространство памяти другой программы. Они в безопасности! За исключением... есть способы сказать операционной системе, чтобы она разделяла страницу между двумя программами (хотя они могут иметь разные адреса в каждой программе), позволяя им совместно использовать страницы. DLL делают это.

На самом деле все гораздо сложнее, чем это.

person Mooing Duck    schedule 04.09.2013

1) Он размещается из ОЗУ, с жесткого диска или откуда-то еще?

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

2) Могу ли я на всякий случай одолжить память с жесткого диска?

Операционная система, управляющая памятью, может заимствовать память с диска.

Вы также можете явно заимствовать память с диска, сохраняя данные в файле. Стандартные библиотеки C и C++ (stdio.h и fstream) позволяют работать с файлами.

person a.lasram    schedule 04.09.2013

Когда вы обращаетесь к памяти, выделенной malloc или оператором new, она находится в ОЗУ и имеет уникальный адрес. Работа операционной системы состоит в том, чтобы иметь этот блок памяти в ОЗУ при обращении к нему, но она может по своему усмотрению выгрузить его на диск. Поскольку подкачка выполняется медленно, ОС должна выяснить, как минимизировать подкачку.

Операционные системы, использующие «виртуальную память», позволяют вам установить, какой объем дискового пространства будет доступен диспетчеру виртуальной памяти.

Вам не нужно пытаться управлять этим самостоятельно, хотя вы можете подумать, не лучше ли использовать базу данных для управления данными, особенно если время жизни данных больше, чем один сеанс.

person Codie CodeMonkey    schedule 04.09.2013
comment
Фактически, он, вероятно, не находится ни в ОЗУ, ни на диске, пока не будет записан. - person Oliver Charlesworth; 05.09.2013

Этот ответ будет довольно ориентирован на Linux

Это намного сложнее, чем кажется. Когда вы выделяете блок памяти, может произойти одно из двух. Если в вашем процессе уже есть достаточно памяти, которая ранее была освобождена, но не возвращена ОС (распределители обычно этого не делают), эта память будет отмечена как выделенная в таблицах распределителей и будет возвращена. Когда у процесса еще нет памяти, распределитель запрашивает у ОС больше. В Linux это означает системные вызовы brk или sbrk. Я не знаю, что это значит в Windows или OSX.

Все современные распространенные ОС (Linux, Windows, OSX и их производные) используют виртуальную память, причем концепция адресов не обязательно указывает на реальную оперативную память. Пока вы что-то в него не поместите, выделенной вами памяти может вообще не существовать. Как только вы начнете его использовать, ОС необходимо освободить для него место в оперативной памяти. Для этого ОС будет хранить другие, неиспользуемые страницы (части памяти) в файле подкачки или разделе на диске, если он так настроен.

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


По сути, в современной ОС память может поступать из любого места по выбору ОС и может даже не существовать, когда вы ее выделили.


Примечание. Некоторые операционные системы, такие как Linux, в большинстве случаев даже позволяют вам выделять память, которую она вам не должна предоставлять. Это называется чрезмерным выделением памяти.

person Linuxios    schedule 04.09.2013