I'm trying to understand fork()
and process address spaces. I wrote a basic proof of concept program that forks a new process and changes a variable in the new process. My expectation was that when I change a variable in the child, this should cause that variable to get a new address. If I understand correctly, Linux does copy-on-write with fork. So I would expect the variable address in the parent and child to match until I change it in one of them. Then I would expect them to be different. However, that's not what I'm seeing.
Is this because with copy-on-write a new page is allocated from physical memory, but the process address space is unchanged - just remapped to the new page by the TLB? Or am I not understanding this or made a dump mistake in my program?
Proof of concept code:
#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
void describe(const std::string &descr, const int &data) {
pid_t ppid = getppid();
pid_t pid = getpid();
std::cout << "In " << descr << ":\n"
<< "Parent Process ID: " << ppid
<< "\nMy Process ID: " << pid
<< "\nValue of data: " << data
<< "\nAddress of data: " << &data << "\n\n";
}
void change(int &data) {
// Should cause data to get new page frame:
data *= 2;
}
int main () {
int data = 42;
int status;
pid_t pid = fork();
switch(pid) {
case -1:
std::cerr << "Error: Failed to successfully fork a process.\n";
exit(1);
break;
case 0:
// In forked child
describe("Child", data);
// Lazy way to wait for parent to run describe:
usleep(1'000);
break;
default:
// In calling parent
describe("Parent", data);
// Lazy way to wait for child to run describe:
usleep(1'000);
}
if (pid == 0) {
std::cout << "Only change data in child...\n";
change(data);
describe("Child", data);
} else {
// Lazy way to wait for child to change data:
usleep(1'000);
describe("Parent", data);
}
// Wait for child:
if (pid != 0) {
wait(&status);
}
return 0;
}
Example run:
ubuntuvm:~$ ./example
In Parent:
Parent Process ID: 265569
My Process ID: 316986
Value of data: 42
Address of data: 0x7fffb63878d4
In Child:
Parent Process ID: 316986
My Process ID: 316987
Value of data: 42
Address of data: 0x7fffb63878d4
Only change data in child...
In Child:
Parent Process ID: 316986
My Process ID: 316987
Value of data: 84
Address of data: 0x7fffb63878d4
In Parent:
Parent Process ID: 265569
My Process ID: 316986
Value of data: 42
Address of data: 0x7fffb63878d4