foreword
Anyone who is familiar with the linux process mechanism knows that a new process in linux is a process created in the form of fork + exec
When fork, the relevant data structure of the parent process is copied, and then the binary to be executed is updated to execute
Then the memory management between the parent and child processes is based on copy on write
For a physical page, after fork, the memory is set to read-only, and then when a write request occurs, the physical page is copied, and then the operation is performed
test case
The use case is mainly to apply for a piece of space, and then set it to aaa
Then fork, a single process becomes a parent-child process, and then the parent process sets the space to bbbb, and the child process sets the space to ccccc
Here is the process of debugging our cow above
#include "stdio.h"
#include "stdlib.h"
#include "unistd.h"
void processHandler(int pid, char *p1, char *processName) {
printf(" %s - %d, p1 : 0x%x, %s \n", processName, pid, p1, p1);
}
int main(int argc, char **argv) {
char *p1 = (char *) malloc(20);
memset(p1, 'a', 16);
printf(" %s - %d, p1 : 0x%x, %s \n", "parent", getpid(), p1, p1);
int childPid = fork();
sleep(rand() % 5);
if (childPid == 0) {
memset(p1, 'b', 16);
processHandler(getpid(), p1, "child1");
} else {
memset(p1, 'c', 16);
processHandler(getpid(), p1, "parent");
}
}
cow The parent process and child process page table entries are set to read-only
First disable ASLR, in this relatively small case, malloc calls brk to apply for the first block space, the first address will be 0x602000
The place where the page table entries of the parent process and the child process are set to read-only is here
You can see the range of this vma in copy_pte_range, [6299648 - 6434816] is [0x602000 - 0x6230000] The space we malloc applied for belongs to this vma
When the parent process/child process modifies the content of the corresponding page, cow copies the physical page
According to our current rules here, one execution will generate two processes, and no other processes will be generated
The parent process is odd and the child process is even
Here is where the parent/child process tries to modify the space where [0x602000 - 0x6230000] is located, and then the related processing of the kernel
The process that modifies first copies the original physical page and sets it as readable and writable, and then the corresponding process operates the given physical page
The post-modification process finds that only the current process can use the physical page, and directly reuse the physical page
The copying of physical pages is based on kmap_atomic + memcpy
The process number of the first operation here is 313, which corresponds to the parent process
The post-modification process finds that only the current process can use the physical page, and directly reuse the physical page
(initramfs) ./Test23MemoryCowChildFirst
parent - 313, p1 : 0x602010, aaaaaaaaaaaaaaaa
child1 - 314, p1 : 0x602010, bbbbbbbbbbbbbbbb
parent - 313, p1 : 0x602010, cccccccccccccccc
The first operation here is when the child process first modifies the corresponding read-only page
(initramfs) ./Test23MemoryCowChildFirst
parent - 319, p1 : 0x602010, aaaaaaaaaaaaaaaa
child1 - 320, p1 : 0x602010, bbbbbbbbbbbbbbbb
parent - 319, p1 : 0x602010, cccccccccccccccc
over