Primeiro, seu código exibe um comportamento indefinido ( cnt
é usado sem ter sido inicializado, mesmo para os 6M que você está lendo sem inicializar), portanto certifique-se de que seu compilador produza instruções que correspondam ao seu código: não é preciso. (Eu estou supondo que você tenha verificado isso.)
As páginas do 6M que você está lendo só não podem ser consideradas limpas. Uma página limpa é aquela que é sincronizada com seu armazenamento de apoio (o que quer que seja, swap, um arquivo, etc.). Essas páginas não têm nada que as apoie.
Eles não são realmente sujos no sentido usual - afinal, eles não foram modificados.
Então, o que está acontecendo aqui? Todas as páginas no bloco 6M que você está lendo são mapeadas para a mesma página, e essa página é a "página zero" (ou seja, uma página compartilhada (em x86 pelo menos) que contém 4k bytes zero).
Quando o kernel recebe uma falha de página em uma página anônima não mapeada, e essa falha é uma leitura, ela mapeia em uma página zero (a mesma página a cada vez). (Isso está em do_anonymous_page
in mm/memory.c
)
Esse não é um mapeamento "normal" (no vm_normal_page
sense) e não é contabilizado nos campos smaps
como nada compartilhado ou privado ( smaps_pte_entry
in fs/proc/task_mmu.c
ignora totalmente as páginas "especiais"). Ele é contabilizado em RSS e Size: na perspectiva do espaço de endereço, essas páginas virtuais existem e foram "usadas".
Se você começar a modificar (gravar) qualquer página nessa área, ele obterá um mapeamento normal e adequado com uma página anônima (zero-inicializada neste caso específico, curiosamente - ela não será inicializada com zero se a anterior (não (normal / falso) mapeamento não foi para a página zero). (Veja do_wp_page
in mm/memory.c
.) Nesse ponto, você verá smaps
exibir o que espera.
Por favor, note que nada em C, POSIX ou qualquer outra coisa garante que estas páginas contenham zeros, você não pode confiar nisso. (Você também não pode confiar nisso no Linux - é assim que é implementado agora, mas pode mudar).