Is libc reloaded to memory for every process or a single copy is shared?

There are a few posts and articles which claims it's loaded once to physical memory and other processes only map their (randomized) virtual address to it at load time: How Libc shared library loaded in memory and shared amongst processes?

But I did my own small experiment with my tiny shared library and the result is not as expected:

1- I made a shared lib called libadd.so, here is the code:

int add(int a){ return ++a;}

2- Made main.c which uses libadd, here is the code:

while(1){
   printf("%d\n", add(1));
   sleep(1);
 }

Running main will print 2 in a loop every second as expected.

3- While main is running I modified libadd.so to return 0; and re-ran main in a separate process.

Result: First process kept printing 2 while the new process is printing 0. If libadd.so is truly only loaded once to physical memory and other process only map their virtual address to it then both process should have printed 0, no? My example shows there are 2 different copies of this lib in executable memory.


3- While main is running I modified libadd.so to return 0; and re-ran main in a separate process.

The OS noticed libadd.so had changed since it loaded it and it loaded the new version and linked it to the new process. If you run another process which uses libadd.so, and libadd.so has not changed, it will share this cached copy.

The old version is also still loaded in memory. It will remain so until no processes reference it.


Your little experiment fails to take into account that the executable code lives in an entirely different segment, named .text, that's different from the .data segment (pre-initialized with nonzero values global variables), the .bss segment (global variables default-initialized to zero), the stack, and memory allocated dynamically.

What's shared between processes is only the .text segment (and the .rodata segment which is for constant data, which is essentially just .text without the PROT_EXEC permission set). Everything else is being mapped as process private memory.