2009-08-10 5 views
1

У меня есть эта программа в C++, что вилы два новых процесс:О вилке вызова системы и глобальных переменных

#include <pthread.h> 
#include <iostream> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/wait.h> 
#include <cstdlib> 
using namespace std; 

int shared; 

void func(){ 
    extern int shared; 
    for (int i=0; i<10;i++) 
     shared++; 
    cout<<"Process "<<getpid()<<", shared " 
     <<shared<<", &shared " 
     <<&shared<<endl; 
} 

int main(){ 
    extern int shared; 
    pid_t p1,p2; 
    int status; 
    shared=0; 
    if ((p1=fork())==0) {func();exit(0);}; 
    if ((p2=fork())==0) {func();exit(0);}; 
    for(int i=0;i<10;i++) 
     shared++; 
    waitpid(p1,&status,0); 
    waitpid(p2,&status,0);; 
    cout<<"shared variable is: "<<shared<<endl; 
    cout<<"Process "<<getpid()<<", shared " 
     <<shared<<", &shared " 
     <<&shared<<endl; 
} 

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

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

Мне нужно объяснение, почему адрес тот же, хотя они являются отдельными переменными.

+0

запомнить fork делает копию при записи, таким образом, пока вы не измените var, это будет одинаково во всех процессах. – Lodle

+0

Это не может работать иначе, иначе ваши указатели будут признаны недействительными после вилка. Не очень полезно ... – Eugene

ответ

9

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

4

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

7

Это называется «виртуальный адрес». Каждый процесс имеет собственное адресное пространство, и каждый адрес означает что-то другое, в зависимости от процесса. fork() создает копию вместо совместного использования данных (технически они могут получать совместную копию на запись, но это имеет тот же эффект, что и предварительное копирование). IOW переменная «shared» не разделяется между процессами.

0

Это относится и к объектам pthread_mutex. Скажем, у меня есть мьютекс в родительском элементе, который блокируется и разблокируется в определенной функции. Теперь родитель создает дочерний процесс. И родительский, и дочерний могут одновременно вызвать эту функцию (родитель не заблокирован до тех пор, пока дочерний элемент не выйдет, поскольку родительский объект является многопоточной программой, поток, который порождает дочерний элемент, блокируется только одним). Итак, состояние объекта мьютекса - разделяемое между двумя процессами? Если родитель, мьютекса был заперт тогда ребенок был создан ребенок получает запустить первые ребенка видит мьютекс в заблокированном состоянии, как он только что унаследовал объект мьютекса, как это от родителей Теперь ребенок разблокирует мьютекс Как это состояние этого мьютекса у родителя сейчас - все еще заблокировано (потому что родитель никогда не разблокирован) или Unlocked, потому что его разблокировал.

Можно ли назвать такую ​​функцию, которая блокирует/открывает глобальные мьютексы от родителя и дочернего?

0

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

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