32 Linux の物理ページのカウ

序文

Linux プロセスのメカニズムに詳しい人なら、Linux の新しいプロセスが fork + exec の形式で作成されるプロセスであることを知っています。 

fork の場合、親プロセスの関連データ構造がコピーされ、実行されるバイナリが更新されて実行されます。  

その後、親プロセスと子プロセス間のメモリ管理はコピーオンライトに基づいて行われます。 

ある物理ページについては、フォーク後、メモリを読み取り専用にし、書き込み要求が発生すると物理ページをコピーして操作を実行します。 

テストケース

使用例は主に、スペースの一部を申請し、それを aaa に設定することです。 

次にフォークすると、単一プロセスが親子プロセスになり、親プロセスはスペースを bbbb に設定し、子プロセスはスペースを ccccc に設定します。 

上記の牛をデバッグするプロセスは次のとおりです。 

#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");
    }

}

牛 親プロセスと子プロセスのページ テーブル エントリが読み取り専用に設定されている

まず ASLR を無効にします。この比較的小規模なケースでは、malloc が brk を呼び出して最初のブロック スペースを適用します。最初のアドレスは 0x602000 になります。 

親プロセスと子プロセスのページテーブルエントリを読み取り専用に設定する場所はここです 

copy_pte_range でこの vma の範囲を確認できます。[6299648 - 6434816] は [0x602000 - 0x6230000] です。malloc が適用したスペースはこの vma に属しています 

親プロセス/子プロセスが対応するページのコンテンツを変更すると、cow は物理ページをコピーします。

ここでの現在のルールによれば、1 回の実行で 2 つのプロセスが生成され、他のプロセスは生成されません。 

親プロセスは奇数、子プロセスは偶数です 

ここでは、親/子プロセスが [0x602000 - 0x6230000] が配置されている領域を変更しようとし、その後、カーネルの関連処理が行われます。 

変更するプロセスは、まず元の物理ページをコピーして読み取りおよび書き込み可能に設定し、その後、対応するプロセスが指定された物理ページを操作します。 

変更後のプロセスでは、現在のプロセスのみが物理ページを使用できることがわかり、物理ページを直接再利用します。 

物理ページのコピーは kmap_atomic + memcpy に基づいています 

ここでの最初の操作のプロセス番号は 313 で、これは親プロセスに対応します。 

変更後のプロセスでは、現在のプロセスのみが物理ページを使用できることがわかり、物理ページを直接再利用します。 

(initramfs) ./Test23MemoryCowChildFirst 
 parent - 313, p1 : 0x602010, aaaaaaaaaaaaaaaa 
 child1 - 314, p1 : 0x602010, bbbbbbbbbbbbbbbb 
 parent - 313, p1 : 0x602010, cccccccccccccccc 

ここでの最初の操作は、子プロセスが対応する読み取り専用ページを最初に変更するときです。 

(initramfs) ./Test23MemoryCowChildFirst 
 parent - 319, p1 : 0x602010, aaaaaaaaaaaaaaaa 
 child1 - 320, p1 : 0x602010, bbbbbbbbbbbbbbbb 
 parent - 319, p1 : 0x602010, cccccccccccccccc 

以上

参考

Linuxカーネルのコピーオンライト技術のCOWの仕組みを詳しく解説(ソースコードを手で破る)

おすすめ

転載: blog.csdn.net/u011039332/article/details/128170093