How is the code segment shared between processes in Linux?
Asked Answered
U

2

5

I have read about the copy-on-write principle which occurs when a new process is being forked in Linux.

I have also read about the fact that if multiple instances of one program are running at the same time, only one instance of the program code can be found in the memory.

I was wondering whether this is a direct consequence of the copy-on-write principle or not, and if it is not, what is the process which ensures that no unnecessary copies of the program's code reside in the memory?

Ulmaceous answered 23/8, 2015 at 19:34 Comment(0)
S
7

I was wondering whether this is a direct consequence of the copy-on-write principle or not

No, it's not. FWIW, you could have shared code segments without COW, and you could have COW without shared code segments. It's independent.

If shared program code were to be achieved as a consequence of COW, then only related processes could benefit from that.

For example, if process A forks twice and creates processes B and C, and then B and C call one of the seven exec functions on the same binary, then you could say that the code segment is shared because of COW - since the code segment is never written during execution, and is mapped read-only, then it must be automatically shared, right?

What if you start the same executable from another shell? (Or some other unrelated process forks and executes the same program? It doesn't have to be a shell...)

If code segment sharing was a consequence of COW, in this scenario we wouldn't benefit from sharing the code segment, because the processes are unrelated (so there are no COW-shared pages with the other instances to begin with).

Instead, the code segment is shared with memory mapped files. When loading a new executable in memory, mmap(2) is called to map the binary file's contents into memory.

and if it is not, what is the process which ensures that no unnecessary copies of the program's code reside in the memory?

The exact implementation details depend on the operating system, but it's not that complicated. Conceptually, mmap(2) maps files into memory, so you just need to keep some state on the underlying file representation to keep track of which (if any) memory mappings are active for that file. Such information is usually kept in the file's inode.

Linux, for example, associates files with memory address spaces with the i_mapping field of struct inode. So, when mmap(2) is called on a binary for the first time, physical memory pages are allocated to hold information and the i_mapping field of that file's inode is set; later invocations will use the i_mapping field and realize that there is an address space associated with this inode, and because it is read-only, no physical pages are allocated, so everything ends up being shared. Note that the virtual memory might be different in each process, although it refers the same physical page (which means that the kernel will at least allocate and update each process's page tables, but that's about it).

The inode structure is defined in fs.h - I can only guess that other UNIX variants do this in a similar way.

Of course, this all works as long as the same binary file is used. If you copy the binary file and execute both copies separately, for obvious reasons, the code segment will not be shared.

Sensorimotor answered 23/8, 2015 at 21:24 Comment(1)
The same was asked during one of interview question, as how the code section is shared among different processes.Solute
S
2

The sharing of program code (sometimes called program text) relies on another mechanism: memory mapped files.

The key to understanding this, is that the code of the program does not need to be modified by the linker in order to resolve link to external symbols. Therefore, the operating system is only ever dealing in read-only copies of the program text, and it is inherently sharable amongst processes.

Upon run-time linking your program, the dynamic linker calls mmap() to create virtual address space for the your program's .so (and for any shared libraries it uses). At this stage, the file isn't backed by real pages of memory. Instead, as the program starts to execute, reads in the virtual address space of the file cause page-faults and the operating system either allocates a page, then fills it from disc, or if the page is already in memory, map to that.

A good place to learn more is Modern Operating Systems by Andrew Tanenbaum

Serotherapy answered 23/8, 2015 at 20:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.