TL;DR: how exactly is the kernel able to do dirty page accounting in /proc/$PID/smaps
?
Consider the following program statement in C:
static char page1[PAGE_SIZE] __attribute__ ((aligned (PAGE_SIZE)));
Now uninitialized variables are zero at start. My understanding is that on the start of the program, the kernel maps uninitialized variables to the zero page, and does copy-on-write lazy allocation of the page. Fine, make sense, and that way kernel can account for dirty page of the uninitialized sections when page fault occurs.
Now consider the statement:
static char page1[PAGE_SIZE] __attribute__ ((aligned (PAGE_SIZE))) = {'c'};
Here, the loader will load the values for page1
at initialization of the program, and
mark the page as RW. So any write done by the program must be invisible to kernel
as no page fault is triggered.
Here is the program I wrote for experimentation:
#define PAGE_SIZE (4*1024)
static char page1[PAGE_SIZE] __attribute__ ((aligned (PAGE_SIZE))) = {'c'};
int main()
{
char c; int i; int *d;
scanf("%c", &c); // --------- tag 1
for(i = 0; i < PAGE_SIZE; i++)
{
page1[i] = c; // --------- tag 2
}
d = malloc(sizeof(int));
while(1);
return 0;
}
Now before tag 1 and after tag 2 (comments in code), the output of /proc/$PID/smaps
for the section containing page1
is pasted below in the table:
smap | BEFORE TAG-1 | AFTER TAG-2 |
---|---|---|
Size: | 8 kB | 8 kB |
KernelPageSize: | 4 kB | 4 kB |
MMUPageSize: | 4 kB | 4 kB |
Rss: | 8 kB | 8 kB |
Pss: | 8 kB | 8 kB |
Shared_Clean: | 0 kB | 0 kB |
Shared_Dirty: | 0 kB | 0 kB |
Private_Clean: | 4 kB | 0 kB |
Private_Dirty: | 4 kB | 8 kB |
Referenced: | 8 kB | 8 kB |
Anonymous: | 4 kB | 8 kB |
As you can see, the bold parameters above changed.
Questions:
- How on earth did the kernel got to know I wrote the page?
- What is this
Anonymous
field and why did it change?
Any other page/blog/manual explaining all the working in detailed would be helpful.
My guess is that maybe the kernel marks the page as RO, even though it is RW so that page fault triggers and it can do the accounting. Or maybe there is some other process that continuously walks the page tables of processes, but that just seems too expensive.