linux系统编程---fork()函数
fork()函数
目录
当进程调用fork后,当控制转移到内核中的fork代码后,内核会做4件事情:
fork函数的基本使用
头文件:#include<unistd.h>
函数原型:pid_t fork(void)
返回值:
-1,创建子进程失败
==0,子进程的返回值
>0 ,父进程的返回值
子进程创建成功后,代码的执行的位置:父进程执行到哪,子进程就从那开始执行
fork() 函数被调用一次,但返回两次。两次返回的区别是:子进程的返回值是 0,而父进程的返回值则是新子进程的进程 ID。
fork()的写时拷贝
在刚fork出来后,两个地址空间用户区数据完全相同,在后续各自进行不同的操作,各个进程的地址空间中数据是完全独立的。
PS:虽然说对于在各自的地址空间的数据完全独立,但如果,两个进程只是访问(也就是说read操作)此时,其映射在物理内存中的数据是共享的;但如果两者各自进程修改了数据值,在物理内存中将原来的数据空间进行拷贝一份副本,存入修改的数据。<总结:读时共享,写时复制>(写时拷贝技术)。
父子进程的执行顺序:
不一定,谁抢到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函数到底做了那些事情?? 我画一张图帮我们理解:
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都有问题,推荐不要使用.