Вилка - те же адреса памяти? - PullRequest
14 голосов
/ 20 марта 2011

Это о C в Linux.

У меня есть fork() в main(), где я создаю 2 дочерних процесса.Затем в обоих дочерних процессах запускается функция abc(), где есть локальная переменная x.Я пишу некоторую ценность в этом.Затем я печатаю адрес этой переменной с помощью printf("%p",&x).

Оба процесса выводят один и тот же адрес.Я думал, что каждый ребенок получает (независимую) копию памяти родителей.Мне нужно, чтобы у каждого процесса была своя собственная переменная x.Как я могу это сделать или я делаю что-то не так?

Ответы [ 5 ]

22 голосов
/ 20 марта 2011

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

Каждый отдельный процесс получает свое собственное 4G виртуальное адресное пространство, и это работаоперационных систем и менеджеров аппаратной памяти для сопоставления ваших виртуальных адресов с физическими.

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

Диспетчер памяти отобразит его на совершенно другой физический адрес a .

Это отображение такжечто позволяет запускать десять процессов, каждый из которых занимает 1 ГБ, хотя на вашей машине только 4 ГБ физической памяти.Операционная система может выгружать биты вашей памяти на диск и возвращать их обратно, когда вы пытаетесь их использовать.


a : В основном, это правда.Он может отображаться на один и тот же физический адрес, если вы делитесь информацией между процессами.Например, общая память, код и данные ядра, динамические библиотеки и т. Д.

5 голосов
/ 20 марта 2011

Если вы перестанете думать на минуту, fork не сможет дать переменным отдельные адреса в родительском и дочернем процессах. Вы могли уже хранить адреса где-нибудь в памяти, или хэшировать их, или сохранять их в файл, или что-нибудь еще, и тогда все в дочернем объекте, которое зависело от того, что эти адреса действительны, ужасно сломалось бы. Фактически fork действительно и должны создать дочерний процесс, в котором виртуальное адресное пространство идентично виртуальному адресному пространству родительского.

2 голосов
/ 20 марта 2011

Из-за системы виртуальной памяти каждый дочерний процесс имеет свою собственную переменную с одинаковым (виртуальным) адресом.

Одни и те же виртуальные адреса не будут указывать на одно и то же физическое местоположение.

1 голос
/ 09 августа 2014

Чтобы понять, как это может произойти, вам нужно понять модель процесса / потока в Linux.Linux следует модели fork-and-exec, унаследованной от UNIX.Процесс, порожденный системным вызовом fork () в этой модели, представляет собой нечто среднее между потоком и процессом Windows.

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

Когда процесс создается в среде Windows, ОС с нуля создает совершенно новое адресное пространство и заполняет его памятью и необходимыми данными.,Теоретически локальная переменная обоих процессов может иметь одинаковые адреса, но на практике вероятность этого будет очень низкой.И даже в случае, когда обе переменные будут использовать один и тот же адрес, эти две переменные все равно будут разными объектами.

Процессы UNIX имеют сходство с потоками и с процессами Windows.Как и во втором случае, ОС создаст НОВОЕ адресное пространство для дочернего процесса, но в отличие от Windows, Linux создает его путем ленивого копирования адресного пространства родительского процесса с использованием подхода Copy-On-Write (COW).COW означает, что оба процесса будут совместно использовать одну и ту же память, но до того момента, пока один из них не изменит ее.В момент попытки записи в память операционная система снова будет задействована, чтобы скопировать часть памяти, которая будет изменена, и назначить одну копию родительской, а другую - дочерней.Начиная с этого момента каждый процесс будет работать со своей независимой копией объектов в измененном фрагменте памяти, но они будут иметь те же адреса.То же самое верно для стека и локальных переменных, хранящихся в нем.

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

0 голосов
/ 18 декабря 2014

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...