5.fork和vfork

版权声明:本博客为记录本人学习过程而开,内容大多从网上学习与整理所得,若侵权请告知! https://blog.csdn.net/Fly_as_tadpole/article/details/82764051

fork和vfork函数都是用于创建子进程的系统函数。

fork函数调用一次,返回两次。两次返回的返回值不同。

1)返回值等于0时,处于子进程空间。

理由:一个进程只会有一个父进程,所以子进程总是可以调用getppid()来获得父进程的进程ID(进程ID为0的进程为系统的内核交换进程,所以一个子进程的进程ID不可能为0)

2)返回值为正值(也即子进程pid)时,处于父进程空间

理由:一个父进程可以创建多个子进程,并且也没有一个函数能够返回父进程的所有子进程ID。通过返回子进程的进程ID给父进程,有助于父进程记录子进程的相关信息。


我们知道在调用fork()函数之后,常常会接着调用exec()函数。子进程会复制父进程的地址空间(数据段,堆栈),父子进程共享正文段(也即是代码段),尽管有写时复制技术,但是还是不可避免的会进行内存空间的复制。而后面我们要提到的vfork函数会直接使得子进程依附在父进程空间执行,只是子进程优先于父进程执行!


一般来说,fork之后父子进程之间的执行顺序是不确定的,取决于内核的调度算法。

fork函数与I/O函数之间具有一定的交互关系。比如在fork子进程之前,我们调用write函数输出一行内容,由于write函数是不带缓冲的,所以将其数据写到标准输出一次。标准I/O是带有缓冲的。我们知道,当标准输出连接到终端设备的时候,它是行缓冲的,其它的则是全缓冲的。由于标准输出缓冲区是以换行符来冲洗,因此当我们以交互式的方式运行该程序的时候。只得到该printf输出一次。而当我们将标准输出重定向到一个文件的时候,却可以得到两次输出行。其原因是子进程复制了父进程的数据空间,该缓冲区也被复制进子进程中,此时父子进程都拥有该行内容的缓冲区。具体看APUE(184)


记得,父进程的标准输出被重定向之后,子进程的标准输出也会被重定向的。很简单,其实fork的一个特性就是:父进程所有打开的文件描述符都会被复制到子进程之中。父子进程之间共享一个文件表项。

fork之后,处理文件描述符有两种情况:

1)父进程等待子进程完成。子进程读写操作完之后,更新文件描述符的文件偏移量。

2)父子进程各自执行不同的代码段。父子进程各自关闭自己不需要的文件描述符,这样就不会对对方产生影响。网络服务器程序就是这种处理方式。


fork一般有两种用法:

1)一个父进程希望复制自己,使父进程和子进程执行不同的代码段。例如:在服务器程序中,父进程用于监听外来连接,一旦请求介入,父进程就fork出子进程处理连接。

2)各自执行不同的程序。这在这种情况下,fork返回后立即调用exec函数。


vfork和fork的调用序列、返回值都是相同的。只是,vfork函数用于创建一个子进程,而这个子进程的目的是来exec一个新的程序。vfork创建的子进程在调用exec或者exit之前都在父进程空间执行。能够大大提高UNIX系统的实现效率。

vfork和fork另一个区别就是:vfork优先执行子进程!!!在它调用exec或者exit之后父进程才可能被调用。

但有一点缺点,如果子进程调用这两个函数的操作依赖于父进程的进一步操作,则会导致死锁的发生!

猜你喜欢

转载自blog.csdn.net/Fly_as_tadpole/article/details/82764051
今日推荐