I recently learned that fork applies COW (copy on write) even on registers.
I played with a simple toy case to verify:
(gdb) info inferiors
Num Description Connection Executable
* 1 process 59316 1 (native) /home/Drew/mycode/a.out
2 process 59386 1 (native) /home/Drew/mycode/a.out
(gdb) print( $rdi )
$1 = 18874385
(gdb) set $rdi=42
(gdb) print( $rdi )
$2 = 42
(gdb) inferior 2
[Switching to inferior 2 [process 59386] (/home/Drew/mycode/a.out)]
[Switching to thread 2.1 (process 59386)]
#0 0x00002aaaab090291 in fork () from /lib64/libc.so.6
(gdb) print( $rdi )
$3 = 18874385
As you guys see, modifying rdi in parent proc does not interfere child proc.
I wonder how is it done? does modern CPU provides multiple same registers exclusively for multi-process?
EDIT:
Thanks to you fellows for commenting. I'll answer the questions in comments here collectively, hope it helps clarify.
The reference I'm using is this lecture note.
I generally want to figure out:
Systems that provide pre-emptive multi-tasking provide CPU virtualization. This allows each thread to behave as if it has a CPU core (and its registers) to itself. More specifically, this allows a thread to use registers without having to worry about them getting changed by another thread (of the same process or a different one) in the middle of an operation.
This is the case no matter how the thread is created, and thus includes threads created by fork
. How the system achieves this is not relevant. But it ensures that any changes to, say, rdi
or the instruction pointer in one thread isn't seen in another.
I don't know what guarantees fork
provides about the initial value of registers after a fork
. It could be the same guarantees as other calls covered by the system's ABI.