Хотя Дэвид Шварц уже ответил на поставленные вопросы, я хотел бы поговорить о базовой картине.Так что не считайте это ответом, а расширенным комментарием.
Проблема в том, что показанное изображение не является хорошим представлением адресного пространства, которое обычное приложение пользовательского пространства видит на современных компьютерах и операционных системах.
Каждый процесс имеет свое собственное адресное пространство.Это реализовано с использованием виртуальной памяти ;сопоставление виртуальных адресов с реальными доступами к оборудованию, которое для всех целей и задач невидимо для процесса пользовательского пространства.(Виртуальная память не является адресной, но использует небольшие блоки, называемые pages . На всех современных архитектурах каждая страница имеет размер двух байтов. 2 12 = 4096 обычно, но также используются другие размеры, такие как 2 16 = 65536 и 2 21 = 2097152.)
Даже если вы используете общую память, она может находиться в другой виртуальнойадреса для разных процессов.(Это также причина, по которой вы не можете использовать указатели в разделяемой памяти.)
Когда процесс выполняется с помощью fork (), виртуальная память клонируется.(На самом деле это не скопированное само по себе, так как это приведет к потере ресурсов. Обычно ядро ОС использует метод copy-on-write , так что фактическая физическая память ОЗУиспользуется для памяти, используемой обоими / всеми процессами, до тех пор, пока один из них не изменит свою «копию», после чего ядро ОС отсоединяет уязвимую страницу, дублируя ее содержимое, прежде чем продолжить изменение.)
Этоозначает, что после fork () родительский и дочерний процессы будут иметь свои стеки с одинаковыми виртуальными адресами.
Единственное ограничение - это объем доступной оперативной памяти.На самом деле ядро ОС также может перемещать неиспользуемые в настоящее время файлы в файл подкачки или файл подкачки ;но если эти страницы скоро понадобятся, это замедляет работу машины.В Linux, по крайней мере, двоичные файлы и библиотеки также напрямую сопоставляются с их соответствующими файлами - по этой причине вы не можете изменять исполняемые файлы, когда они используются, поэтому, если копия кода в ОЗУ не изменена, оникак правило, не используют файл подкачки / подкачки.
В большинстве случаев часть диапазона виртуальной памяти зарезервирована для ядра ОС. не означает, что память ядра видна пользователям или доступна любым способом;это просто способ гарантировать, что при передаче данных в или из процессов пользовательского пространства ядро ОС может использовать адреса виртуальной памяти пользовательского пространства, а не смешивать их со своими собственными внутренними адресами.По сути, ядро ОС просто не будет создавать никаких сопоставлений виртуальной памяти с адресами, которые оно использует само для любого пользовательского процесса, чтобы упростить свою собственную работу.
Интересная деталь в Linux состоит в том, что, как правило, стек по умолчаниюразмер для новых потоков довольно большой, 8 МБ (8 388 608 байт) на 32-разрядной x86.Если вы не установите меньший стек, число потоков, которые может создать процесс, ограничено доступной виртуальной памятью.Каждый процесс в пользовательском пространстве может использовать младшие 3 ГБ или адреса виртуальной памяти ниже 3221 225 472 на 32-разрядной платформе x86;и вы можете разместить в нем не более 384 стеков по 8 МБ.Если вы учитываете стандартные библиотеки и т. Д., Обычно в этих системах процесс может создать около 300 потоков, прежде чем он исчерпает виртуальную память.Если вы используете намного меньший стек, скажем, 65536 байт, процесс может создать тысячи потоков даже на 32-битной x86.Просто помните, что проблема заключается в нехватке доступного адресного пространства виртуальной памяти , а не памяти как таковой.