長すぎます。一体カーネルが/proc/$PID/maps
。
次のCプログラムの説明を考えてみましょう。
static char page1[PAGE_SIZE] __attribute__ ((aligned (PAGE_SIZE)))
初期化されていない変数は最初はゼロです。私が理解したのは、プログラムの起動時にカーネルが初期化されていない変数をページ0にマップし、ページの書き込み時にコピー遅延割り当てを実行することです。ページエラーが発生したときにカーネルがダーティページの初期化されていない部分を説明する可能性があるため、これをお勧めします。
さて、この言葉を考えてみましょう。
static char page1[PAGE_SIZE] __attribute__ ((aligned (PAGE_SIZE))) = {'c'}
ここで、ローダーはプログラムの初期化中にpage1の値をロードし、そのページをRWとしてマークします。したがって、プログラムによって実行されたすべての書き込みはページエラーを引き起こさないため、カーネルには表示されません。
これは私が実験のために書いたプログラムです。
#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;
}
これで、ラベル1(コードのコメント)の前後に/proc/$PID/smaps
含まれるセクションの出力がpage1
下の表に貼り付けられます。
シュトゥ | 1個前タグ | TAG-2以降 |
---|---|---|
サイズ: | 8KB | 8KB |
カーネルページサイズ: | 4KB | 4KB |
MMUページサイズ: | 4KB | 4KB |
RSS: | 8KB | 8KB |
添付: | 8KB | 8KB |
共有_クリーン: | 0KB | 0KB |
共有_汚い: | 0KB | 0KB |
個人清掃: | 4KB | 0KB |
個人_汚い: | 4KB | 8KB |
引用: | 8KB | 8KB |
匿名: | 4KB | 8KB |
ご覧のとおり、太い色のパラメータが変更されました。
質問
- 私がこのページを書いたことをカーネルはどうやって知りましたか?
- この匿名フィールドは何で、なぜ変更されますか?
すべての作業を詳しく説明する他のページ/ブログ/マニュアルが役に立ちます。
私は推測する:
おそらく、カーネルはページがRWであるにもかかわらず、ページをROとしてマークし、ページエラーが発生して計算される可能性があります。あるいは、プロセスのページテーブルを連続的に巡回する他のプロセスがあるかもしれませんが、コストがかかりすぎます。
答え1
Linuxがサポートするほとんどの(おそらくすべては確認されていません)アーキテクチャでは、MMUはどのページがダーティであるかを追跡します。したがって、カーネルは、ページが初期化されたときにコンテンツがゼロでない場合でも、ページテーブルエントリのダーティビットをクリアでき、MMUはページが変更されたときにそれを更新します。
匿名メモリは、ファイルのバックアップがないメモリです。ページを作成すると、ファイルがサポートされていないメモリの量が増えます。初期化時には実行可能イメージとしてサポートされますが、一度変更するとサポートされなくなります。
カーネルがダーティページを確認する場所については、以下を参照してください。参考までにpte_dirty
。
カーネルもやや「柔らかくて汚い」、ユーザースペースから消去され、チェックポイントの回復に使用できます。