linux系统编程---fork()函数

fork()函数


目录

fork函数的基本使用

头文件:#include

函数原型:pid_t fork(void)

返回值:

fork()的写时拷贝

父子进程的执行顺序:

如何区分父子进程?

当进程调用fork后,当控制转移到内核中的fork代码后,内核会做4件事情:

父子进程之间能够使用全局变量通信?

fork函数的底层做了什么

vfork和fork的之间的比较:

vfork和fork之间的区别:


fork函数的基本使用

linux系统编程---fork()函数

头文件:#include<unistd.h>

函数原型:pid_t fork(void)

返回值:

-1,创建子进程失败

==0,子进程的返回值

>0 ,父进程的返回值

子进程创建成功后,代码的执行的位置:父进程执行到哪,子进程就从那开始执行

fork() 函数被调用一次,但返回两次。两次返回的区别是:子进程的返回值是 0,而父进程的返回值则是新子进程的进程 ID。

fork()的写时拷贝

在刚fork出来后,两个地址空间用户区数据完全相同,在后续各自进行不同的操作,各个进程的地址空间中数据是完全独立的。

PS:虽然说对于在各自的地址空间的数据完全独立,但如果,两个进程只是访问(也就是说read操作)此时,其映射在物理内存中的数据是共享的;但如果两者各自进程修改了数据值,在物理内存中将原来的数据空间进行拷贝一份副本,存入修改的数据。<总结:读时共享,写时复制>写时拷贝技术)。

linux系统编程---fork()函数

父子进程的执行顺序:

不一定,谁抢到cpu资源,谁先执行。

如何区分父子进程?

通过fork函数的返回值

当进程调用fork后,当控制转移到内核中的fork代码后,内核会做4件事情:

* 1.分配新的内存块和内核数据结构给子进程**

** 2.将父进程部分数据结构内容拷贝至子进程**

** 3.添加子进程到系统进程列表当中**

** 4.fork返回,开始调度器调度**

父子进程之间能够使用全局变量通信?

(不能,两个进程间的内存不能共享)

fork函数的底层做了什么

linux平台通过clone()系统调用实现fork(). fork(),vfork()和clone()库函数都根据各自需要的参数标志去调用clone(),然后由clone()去调用do_fork(). 再然后do_fork()完成了创建中的大部分工作,他定义在kernel/fork.c当中.该函数调用copy_process(). 然后重点来了,我们看看这个copy_process函数到底做了那些事情?? 我画一张图帮我们理解:

linux系统编程---fork()函数

 

vfork和fork的之间的比较:


      vfork()的诞生是在fork()还没有写时拷贝的时候,因为那个时候创建一个子进程的成本太大了,如果一下子创建好多了那么程序的效率一定会下降. 然后就有人提出了vfork(). vfork的实现原理非常简单,就是子进程,父进程完全公用一个资源. 就是是有人修改了内容,甚至main()函数退出了也不会新开辟一个空间. 这里里会有问题的,如果你的一个子进程没有使用exit()退出,那么程序就会出现段错误. 

为什么会出现段错误? 

在函数栈上面,子进程运行结束了,main的函数栈被子进程释放了,然后父进程在使用的时候,就访问不到了,一旦vfork出子进程,退出的时候需要使用exit来结束.


vfork和fork之间的区别:

1.fork父子进程交替运行,vfork子进程运行,父进程阻塞,直到子进程结束.

2.fork实现了写时拷贝. vfork直接让父子进程公用资源然后无论如何也不会多开辟空间拷贝了,

3,vfork必须使用exit或者excl退出.

4.就算是fork使用了写时拷贝,也没有vfork性能高.

5.每个系统上的vfork都有问题,推荐不要使用.