Reputation: 19
I'm so confused about how fork() duplicate memory from parent process. I tried to find it out by writing an example:
int global_var = 0;
int main(int argc, char* argv[]){
int local_var = 1;
pid_t child;
child = fork();
if (child < 0){
cout << "Fork error: " << strerror(errno) << endl;
return 1;
}
if (child != 0 ){ // parent
cout << "Parent: global address: " << &global_var << endl;
cout << "Parent: local address: " << &local_var << endl;
++global_var;
++local_var;
cout << "Parent: global: " << global_var << endl;
cout << "Parent: local: " << local_var << endl;
}else{
cout << "Child: global address: " << &global_var << endl;
cout << "Child: local address: " << &local_var << endl;
sleep(1);
cout << "Child: global: " << global_var << endl;
cout << "Child: local: " << local_var << endl;
}
return 0;
}
And i saw the result:
Parent: global address: 0x6021a0 Parent: local address: 0x7fff942dd99c Parent: global: 1 Parent: local: 2 Child: global address: 0x6021a0 Child: local address: 0x7fff942dd99c Child: global: 0 Child: local: 1
Why child did not see the change of the variables even the child's variables are in the same addresses from the parent's. Could someone please help me explain this.
Thanks in advance.
Upvotes: 0
Views: 319
Reputation: 1084
processes are given two types of virtual memory: kernel and user. When you fork() you create a cloned child process with separate virtual memory which is almost identical to the parent. The fork() call is made in the parent, but returns twice, once in the parent and once in the child. The cases are distinguished by the return code:
int x = fork();
if(x == 0)
{
// we are in the child
}
else
{
// we are in the parent
}
The user memory will be identical except for this return code. The kernel memory has a few differences: timers are rest in the child, pid and ppid are different etc. It is common to follow up in the child with a call to execve() which will overlay the user area and allow the child to execute completely different code to the parent. execve() is called once and never returns, because the code is overwriiten, e.g.
int x = fork();
if(x == 0)
{
// we are in the child
execve("myprog", argv, envp); // overwrites the code with that from myprog
// never get here because execve never returns
}
else
{
// we are in the parent
}
Upvotes: 0
Reputation: 26
When you fork a process it becomes its own program, a copy of the parent.
In your example code you only ever increment global_var and local_var in the parent process.
try this to see it.
int global_var = 0;
int main(int argc, char* argv[]){
int local_var = 1;
pid_t child;
child = fork();
if (child < 0){
cout << "Fork error: " << strerror(errno) << endl;
return 1;
}
if (getpid() != 0 ){ // parent
cout << "Parent: global address: " << &global_var << endl;
cout << "Parent: local address: " << &local_var << endl;
++global_var;
++local_var;
cout << "Parent: global: " << global_var << endl;
cout << "Parent: local: " << local_var << endl;
}else if(getpid() == 0){ // child
cout << "Child: global address: " << &global_var << endl;
cout << "Child: local address: " << &local_var << endl;
++global_var;
++local_var;
cout << "Child: global: " << global_var << endl;
cout << "Child: local: " << local_var << endl;
}
return 0;
}
Hope this helps, fork is confusing sometimes.
Upvotes: 0
Reputation: 99134
The child and the parent do not share memory. The addresses have the same value, but they are in separate stacks, like "123 Main Street" in two different cities; they refer to two different locations in memory. The child does not see the changes the parent made, because those changes did not occur in the child's stack.
Upvotes: 1