fork
fork系统调用的实现在kernel/fork.c文件中。最主要函数do_fork
fork是最常见的创建子进程的方法。它创建一个新的子进程,子进程是父进程的复制品,包括所有的内存、文件描述符等。子进程在父进程开始执行,但它们是独立的进程、互不影响。
fork是一种相对重量级的操作,因为它复制了大部分父进程的资源,包括内存。
适用于需要完全隔离的情况,例如常见的命令行工具和服务器程序。
vfork
- vfork(虚拟fork)也用于创建新的子进程,但与'fork'不同,它不会复制父进程的内存。相反,子进程与父进程共享内存空间,直到子进程调用exec或_exit为止。
- 因为不涉及内存复制,vfork操作更加轻量级。但是,使用vfork需要谨慎,因为如果进程修改了共享内存,可能会破坏父进程的状态。
- 适用于需要更高性能和更低开销的情况,例如在子进程中立即调用exec的情况,通常用于创建新的执行环境。
clone
-
clone是最通用的创建新进程或线程的系统调用。它允许细粒度地控制新进程的属性,例如内存,文件描述符、信号处理等。通过指定不同的标志和选项,可以实现fork和vfork相似的行为,也可以创建轻量级的线程
-
clone是Linux下多线程库的基础,例如pthread库就是建立在clone系统调用之上的。
-
可以用于需要更灵活的情况,例如多线程应用程序。
总结
-
fork复制了父进程的资源,创建一个独立的进程
-
vfork创建一个共享父进程内存的子进程,通常用于立即执行exec的场景。
-
clone提供了更多的选项,可用于创建进程或线程,支持更细粒度的控制。
写时拷贝技术
写时拷贝(Copy-On-Write,COW),是一种用于优化内存管理的技术,它的主要思想在需要修改数据时才进行复制,而不是在数据复制时就进行数据的复制
当P1把P2创建出来时,会把task_struct里描述的资源结构体拷贝给p2。
区分进程的标志pid,就是p2的资源不是p1的资源。两个task_struct的资源都相同,那就不叫两个进程了。
执行一个Copy,但是任何修改都造成分裂,如:chroot,open,写memory,最难copy的是mm这个部分,因为要做写时拷贝。Linux通过MMU进行虚拟地址到物理地址的转换,当进程执行fork()后,会把页表中的权限设置为RD-ONLY,当P1,P2去写该页时,CPU会收到page fault,申请新的内存。Linux再将页表中的vit1指向新的物理地址。