{eval=Array;=+count(Array);}
Linux 内核在系统启动的最后阶段会启动 init 进程。Linux 系统的进程之间存在着明显的继承关系,所有的进程都是 pid 为 1 的 init 进程的后代。
其他一些操作系统在创建进程时,首先在地址空间里创建进程,读入可执行文件,最后开始执行。Linux 是类 Unix 的操作系统,关于进程创建,它不同于前面那些操作系统,而是定义了 fork() 和 exec() 两组函数。这里以 fork() 函数为例介绍题主所说的“写时拷贝”。
fork() 函数通过拷贝父进程创建子进程,子进程与父进程的区别仅仅在于 pid,ppid 和一些资源的统计量,比如挂起的信号等。在早期,fork() 函数会将父进程的所有其他资源都复制给子进程。这种设计过于简单粗暴,因为子进程也许并不需要父进程的资源,如果子进程被创建后,转而执行和之前毫不相关的工作,那之前拷贝资源的开销就浪费了,一点意义也没有。
为了解决上面提到的可能会出现浪费的问题,“写时拷贝”的概念就被提出了。写时拷贝是一种可以推迟甚至免去拷贝数据的技术。子进程被创建后,系统将父进程的资源以只读的方式共享给子进程,这样子进程能够使用原本应该拷贝给子进程的数据,而同时又不会“污染”父进程。
这样一来,如果子进程只需要读取父进程数据,或者不需要使用父进程的数据,那么拷贝就免去了。如果子进程需要写这部分数据,则为了保证进程之间的数据独立性,系统才会将父进程的资源拷贝给子进程。
结合上面这两点,就是“写时拷贝”的含义了,下面给出 demo:
char *buf = (char*)malloc(100*1024*1024);
int pid = fork();
if(pid==0){
printf("child exit ");
free(buf);
exit(0);
}else{
wait(&status);
free(buf);
exit(0);
}
对于上面这种情况,因为子进程没有用到父进程的 buf,所以系统就免去了拷贝 buf 100MB 的开销,提升了效率。
char *buf = (char*)malloc(100*1024*1024);
int pid = fork();
if(pid==0){
buf[0] = 1;
printf("child exit ");
free(buf);
exit(0);
}else{
wait(&status);
free(buf);
exit(0);
}
而对于上面这种情况,因为子进程需要写 buf,系统就不可避免的要把父进程的资源拷贝给子进程了。
这就是“写时拷贝”了。
0
回答0
回答10
回答0
回答4
回答0
回答0
回答0
回答0
回答0
回答