1、进程创建
一般使用fork()创建子进程
返回值:
子进程的返回值是0
父进程返回的是子进程的pid(一个父进程有多个子进程,需要通过子进程的pid找到子进程)
-1就是创建失败
创建子进程就是为了让子进程和父进程干不一样的事情,或者执行一个全新的程序
写时拷贝
子进程和父进程是贡献一份代码和数据的,但是当需要改变程序和代码的时候,就会发生写时拷贝。需要改变的时候,会重新拷贝一份数据,在上面修改
2、进程终止
进程退出的三种场景:
1、代码执行完毕,结果正确
2、代码执行完毕,结果错误
3、代码没有执行完,异常终止
进程退出方式
1、通过main函数返回,代表进程退出。。非main函数return叫做函数返回
2、通过exit终止,参数是退出码
3、收到信号,异常终止退出
进程退出,OS层面来说就是,少了一个进程,释放了进程相关的数据结构和数据代码申请的空间
3、进程等待
1、是什么?
进程等待就是让父进程fork之后,通过wait/waitpid等待子进程退出
2、为什么?
1,通过获取子进程的退出信息,得到子进程的执行结果
2,可以保证时序问题,父进程比子进程活的时间长,子进程先退出,父进程后退出
3,进程退出的时候会变成僵尸进程,会造成内存泄漏,需要通过父进程等待,回收子进程的的资源,避免造成内存泄漏
僵尸进程是一个已经死掉的进程,不能再次被杀死
3、怎么办?
通过wait 、waitpid
pid_t wait(int*status)
返回值,成功返回被等待进程的pid,失败返回-1
子进程的执行结果信息可以通过status得到,具体的如下
pid_ t waitpid(pid_t pid, int *status, int options)
返回值
当正常返回的时候waitpid返回收集到的子进程的进程ID;
如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0;
如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在;
参数
1、pid 可以具体的等待某个子进程结束。如果设置为-1就是,任意一个子进程结束
2、status 输出型参数,使用传指针来返回结果,包含了子进程执行的结果
32个bite位,这个参数只使用低16bite位,
其中次低8位表示的是退出状态,低8位中有退出码
可以通过按位与的操作得到,也可以通过宏得到
WIFEXITED(status):若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出)
WEXITSTATUS(status):若WIFEXITED非零,提取子进程退出码。(查看进程的退出码)
3、options表示等待的方式
设置为0就是阻塞等待 父进程啥都不干,等待子进程结束
设置为WNOHANG,就是非阻塞等待,隔一会检测一次子进程是否结束,自己期间可以执行别的任务
两者都是等待的一种方式,阻塞的本质就是 就是进程的PCB模块被放在了等待队列中,将进程的状态改为S
4、进程程序替换
进程创建的目的就是为了让子进程的执行不一样的代码程序,
可以通过if else让执行代码的一部分,但是要如果需要执行一份全新的代码程序,就需要使用程序替换。
程序替换的过程: PCB进程控制块是一样的,其中就是将页表和物理空间之间的代码程序的映射关系修改一下,达到执行一个新程序的目的
进程不变,仅仅替换当前的代码和数据,这个过程中是没有创建任何的进程的
程序替换的本质就是把程序代码和数据加载到特定进程的上下文中,
加载到内存中,使用的是加载器,其中重要的是exec系列的替换函数
程序替换函数
主要使用的就是上面的函数
path代码程序执行的路径+文件 arg表示可变参数列表,就是命令行中怎么执行,就怎么写,其中以NULL结尾
其中execv是系统提供的接口函数,其它是根据不同的场景需要提供的函数参数
其中exec表示的就是这一类的函数
l(list) :表示参数采用列表
v(vector) :参数用数组
p(path) :有p自动搜索环境变量PATH
e(env) :表示自己维护环境变量
当程序替换完成时,就可以执行一个完整的程序了,也就是可以实现程序调用程序。