Странное поведение программы «родитель-ребенок-ребенок» - PullRequest
4 голосов
/ 10 июня 2011

У меня есть сомнения относительно программы, вставленной ниже. Я объясняю свое понимание программы здесь: в этой программе родитель создает ребенка и ожидает его завершения. Затем ребенок создает поток и ожидает его завершения. Таким образом, в конце переменная ' value ' будет иметь значение '5' в дочернем процессе и '0' в родительском процессе, поскольку фактически существует две копии переменной ' value * 1004. * 'один в родительском, а другой в дочернем (поскольку fork по сути копирует адресное пространство родительского объекта в дочерний) Однако адреса переменной ' value ' в родительском и дочернем элементах оказываются одинаковыми. Я не понимаю как. Буду благодарен, если кто-нибудь сможет объяснить это поведение.

#include <stdio.h>
#include <pthread.h>


int value = 0;
void *runner( void *param );

int main ()
   {
   int pid ;
   pthread_t tid;
   pthread_attr_t attr;

   pid = fork();

   if( pid == 0 ) /* child */
      {
      pthread_attr_init( &attr );
      pthread_create( &tid, &attr, runner, NULL );
      pthread_join(tid, NULL);
      printf( "CHILD: value = %d, address = %p\n", value, &value );
      }
   else if( pid > 0 ) /* Parent */
      {
      wait(NULL);
      printf( "PARENT: value = %d, address = %p\n", value, &value );
      }
   }

void *runner( void *param )
   {
   value = 5;
   pthread_exit(0);
   }

Ответы [ 2 ]

3 голосов
/ 10 июня 2011

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

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

1 голос
/ 10 июня 2011

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

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

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

...