业界的各位同行都知道,fork函数和vfork函数都是进行创建一个进程的。但是呢,各位知道它们之间有什么区别吗?接下来就让我给大家阐述一下:
我总结了一下几个区别:
- fork()创建的子进程拷贝了父进程的代码段,数据段,堆栈;而vfork()创建出来的子进程和父进程共享数据段;
- fork()创建的子进程执行次数不确定,操作系统对他们进行交替执行,而vfork()创建出来的必须要保证子进程先执行,子进程在调用exit()或exec()函数之前和父进程共享数据段和代码段,相当于线程的概念,父进程阻塞等待,子进程在它调用exit()或exec()函数之后父进程才可能被调度执行。
那我们就会问已经有了fork了,为什么还要有个vfork呢?
原因:以前的fork当它创建一个子进程时,将会创建一个新的地址空间,并且拷贝父进程的资源,然后将会有以下这两种行为:
1.执行从父进程那里拷贝过来的代码段;
2.调用一个exec()执行一个新的代码段;
当一个子进程调用了exec()之后,然后一个全新的子进程替换了当前的代码段,数据段,堆栈。去执行他想要执行的功能,这样的话,对于fork而言,之前的拷贝工作都白费了,于是呢人们就提出了vfork(),vfork并不会拷贝父进程的进程环境,它和父进程共享运行地址空间,所以子进程不可以进行写操作,并且当儿子“霸占”着老子的房子时候,要委屈老子一下了,让他在外面歇着(阻塞),一旦儿子执行了exec或者exit后,相当于儿子买了自己的房子了,这时候就相当于分家了。
并且,子进程在vfork()返回后直接运行在父进程的栈空间,并使用父进程的内存和数据。这意味着子进程可能破坏父进程的数据结构或栈,造成失败。为了避免这些问题,需要确保一旦调用vfork(),子进程就不从当前的栈框架中返回,并且如果子进程改变了父进程的数据结构就不能调用exit函数。子进程还必须避免改变全局数据结构或全局变量中的任何信息,因为这些改变都有可能使父进程不能继续。通常,如果应用程序不是在fork()之后立即调用exec(),就有必要在fork()被替换成vfork()之前做仔细的检查。
用vfork函数创建子进程后,子进程往往要调用一种exec函数以执行另一个程序,当进程调用一种exec函数时,该进程完全由新程序代换,而新程序则从其main函数开始执行,因为调用exec并不创建新进程,所以前后的进程id 并未改变,exec只是用另一个新程序替换了当前进程的正文,数据,堆栈段。
因此,如果我们创建子进程调用exec()就是为了执行一个新程序是,建议大家使用vfork。
以上就是我所总结的vfork和fork的区别,如有错误,请各位同仁指正!