fork
fork()
是Linux中在一个进程中创建一个子进程的系统调用。
函数原型
#include <unistd.h>
pid_t fork(void);
进程创建的一般过程
1.给新进程分配一个标识符,在内核中分配一个PCB
2.复制父进程的环境(不复制地址空间)
3.分配资源(程序,数据,堆栈等)
4.复制父进程的地址空间的内容
5.将进程置成就绪状态,放入就绪队列
从父进程继承了什么东西?
地址空间(写时拷贝)
进程上下文
文件描述符
环境
当前路径
根目录
进程堆栈
信号量
控制终端
进程调度优先级
不会从父进程继承什么?
父进程的pid子进程不继承
父进程的未决信号子进程不继承
父进程的锁子进程不继承
理论上子进程有独立的进程ID号和地址空间,但是在考虑到效率问题后,Linux引入了写时拷贝技术(COW):
即fork出来的子进程完全复制父进程的内存空间(包括代码段,数据段,堆空间,栈空间),也同时复制了页表,但是没有复制物理页面,所以这时子进程的虚拟地址和物理地址同父进程完全相同,但是会把父子进程共享的页面标记为”只读”,如果父子进程中的任何一个进程要对共享区域进行“写操作”,那么内核会复制一个物理页面给这个进程使用,同时修改页表,使虚拟进程映射到新的物理页面。而留下的只读页面被改写为“可读写”,留给另外一个进程使用。
vfork
vfork()
的作用同fork()
相同,都是创建一个子进程,但是也与fork()有所不同
特点
1.vfork()
创建的子进程和父进程共享地址空间,而fork()
的子进程具有独立的地址空间。
2.vfork()
保证子进程先运行,在他调用exec或 exit()之后父进程才可能被调度运行。
注意exit()和return:
1.使用vfork
创建的子进程中千万不能使用return
,在进程运行结束后,想要退出时一定要用exit()
来结束进程
至于为什么不能使用return?要明确return
和exit
的区别:
本质上的区别:
return
是函数返回,返回后释放栈帧资源,把控制权交给调用函数exit