2016-01-15 2 views
1
#include<stdio.h> 
int giCtr0; 

int main(void){ 
int iPid; 

iPid = fork(); 
if (iPid == 0){ 
    giCtr0++; 
    printf("In Child\n"); 
    printf("Addr\t%x Value\t%d\n",&giCtr0,giCtr0); 
} 
else{ 
    giCtr0+=2; 
    printf("In Parent\n"); 
    printf("Addr\t%x Value\t%d\n",&giCtr0,giCtr0); 
} 
return 0; 

}На вилке() в Linux

Выходной сигнал из Ubuntu выглядит следующим образом:

In Parent 
Addr 601054 Value 2 
In Child 
Addr 601054 Value 1 

Значение является правильным и, как и ожидалось. Как адрес переменной остается таким же в дочернем и родительском процессах? В коде есть что-то неправильное? Пожалуйста, предложите.

+0

Ожидается. Каждый процесс будет иметь точно такое же содержимое в своем адресном пространстве на fork(), но по мере изменения содержимого в одном процессе Linux предоставит новую страницу физической памяти для региона, который вы изменяете. То есть модуль управления памятью (MMU) на вашем CPU вызовет различные процессы для использования одних и тех же адресов для отображения в разные области физической памяти. – mkimball

+0

Как это могло измениться? Считаете ли вы, что вызов 'fork' каким-то образом волшебным образом определяет каждую переменную в процессе, которая содержит адрес, и изменяет его на наличие другого значения ?! –

ответ

2

Как адрес переменной остается таким же в дочернем и родительском процессах?

Чтобы добавить комментарий от mkimball

Linux реализует виртуальную память. Это означает, что он устанавливает аппаратное обеспечение, поэтому каждый процесс видит «виртуальную» карту памяти вместо «реальной»/физической карты памяти.

Из-за этого адрес памяти 0x601054 одного процесса не обязательно соответствует той же самой ячейке реальной памяти, что и тот же адрес 0x601054 внутри другого процесса.

+0

Я не думаю, что вы имеете в виду это «* не обязательно соответствует *», а скорее «* никогда не соответствует». – Soren

+0

«Не обязательно соответствует» правильно. Linux использует копию для семантики записи для обмена страницами между разветвленными процессами. Если процесс вилки, и ни ребенок, ни родительский элемент не изменяют содержимое страницы памяти, память будет разделяться. Когда модификация делается на общую страницу, страница затем копируется, а дубликат изменяется, оставляя исходное неповрежденным. Кроме того, общие библиотеки, используемые несколькими процессами, могут совместно использовать память, используемую для хранения функций, предоставляемых библиотекой. – mkimball

3
  1. Адреса памяти в Unix-подобной системе VM - это процесс. Адрес, который вы получаете с помощью оператора C &, представляет собой конструкцию уровня ОС, а не схему адресации, которая непосредственно сопоставляется с битами в чипах ОЗУ (или выгруженных VM-страницах). Таким образом, один и тот же адрес в двух разных процессах может ссылаться на два разных местоположения в «реальной» памяти.

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

Смежные вопросы