首页 > 解决方案 > fork 似乎在不必要时复制

问题描述

我正在尝试 CoW fork有关更详细的背景,请参阅编辑,这可能完全不相关

#include <stdio.h>
#include <time.h>
#include <unistd.h>

#define N 262144
struct {
    int n;
    int padding[1023];
} arr[N];
int main() {
    int i, sp = 0, t, tx = clock();
    for (i=0; i<N; ++i) arr[i].n = i;
    printf ("Init Time: %d\n", clock()-tx);
    #if 1
        sp = fork();
        if(!sp) _exit(0);
        waitpid(sp, &sp, 0);
    #endif
    // 5045 without fork
    // 104192 with fork
    t = clock();
    for (i=0; i<N; ++i) arr[i].n = -i;
    printf ("Runner %d Time: %d\n", sp, clock() - t);
    getchar();
    return 0;
}

fork使以后的内存访问变慢。

fork复制会变慢吗?如果是这样,为什么?我在 Ubuntu 20.04.3 LTS 上运行

标签: linuxfork

解决方案


尝试在下面运行它/usr/bin/time -v并观察 Minor (reclaiming a frame) page faults:线路。

即使孩子立即退出,叉子也会使其翻倍。

增加的时间似乎完全是由于这些页面错误。

据推测,在分叉时,内核在写入时将页面设置为错误,以期需要复制。如果在这样的页面错误时孩子已经死了,则复制的需要被取消(该页面不再与任何人共享,因此无需费心复制它),但您仍然需要为页面错误命中付费。

现在,如果您让孩子保持活动状态,那么页面错误处理程序也应该需要进行复制,实际上,保持孩子活动会增加循环持续时间几次。那应该是完整的写时复制。

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <time.h>
#include <unistd.h>

#define N 262144
struct {
    int n;
    int padding[1023];
} arr[N];
int main() {
    int i, t, tx = clock();
    pid_t sp=0;
    for (i=0; i<N; ++i) arr[i].n = i;
    printf ("Init Time: %ld\n", clock()-tx);

    #if 1
    if(0>(sp = fork())) return 1;
    enum  { KEEP_THE_KID_EH = 1 };
    if(!sp){ if(KEEP_THE_KID_EH){ for(;;) pause(); }  exit(0); }
    #endif

    t = clock();
    for (i=0; i<N; ++i) arr[i].n = -i;
    printf ("Runner %ld Time: %ld\n", (long)sp, clock() - t);
    /*getchar();*/
    if(sp) kill(sp,SIGTERM);
    return 0;
}

我的时间是:

7371 without fork
189073 with fork
1092145 with fork and the kid kept

推荐阅读