一本书讲透Java线程:原理与实践
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

1.1.3 进程创建

Linux创建一个进程大致需要经历初始化进程描述符、申请内存空间、设置进程初始状态、将进程加入调度队列等过程。为了完整地描述一个进程,操作系统设计了非常复杂的数据结构。在进程创建的时候需要申请大量的内存空间,同时需要复制大量父进程的资源,整个过程的效率非常低下。为了提升进程创建效率,Linux构造了写时复制技术。当子进程被创建的时候,Linux内核并不会立即将父进程的所有内容复制给子进程,而是只复制一些基础信息。当父进程空间的内容发生变化时,会通过写时复制技术同步给子进程。写时复制技术允许父、子进程读取相同的物理页,只要两者有一个试图更改页的内容,内核就会把这个页的内容复制到新的物理页上,并把这个页分给正在写的进程。

Linux提供了3种创建进程的函数,分别是clone、fork、vfork。clone函数是最基础的创建进程的系统调用,可以通过各种flag标识指明子进程的基础属性、堆栈等。fork函数是通过clone函数来实现的,可以通过一系列的参数标志来指明父、子进程需要的共享资源。fork函数创建的子进程需要完全复制父进程的内存空间,但是得益于写时复制技术,进程创建的过程加快。vfork函数也是基于clone函数实现的,是对fork函数的优化。因为fork函数需要复制父进程的内存空间,虽然fork函数采用写时复制技术提升了性能,但是这种不必要的复制的代价是比较高昂的,所以vfork函数可以指定flag告诉clone函数是否共享父进程的虚拟内存空间,以加快进程的创建过程。