进程创建:
fork-----通过复制调用进程创建一个新的子进程 复制PCB(代码共享数据独有)---程序计数器(运行的位置都一样)
父进程返回子进程的pid,子进程返回0;
写时复制技术
vfork-----创建子进程,共用同一个虚拟地址空间 共用一个调用栈,会发生调用栈混乱
为了防止调用栈混乱,因此父进程调用vfork会阻塞,阻塞到子进程exit退出---(不可以使用return退出)
或者子进程程序替换,开辟内存创建自己的地址空间
return退出会释放所有资源,包括虚拟地址空间
fork/vfork在内核中创建进程都是调用clone函数实现pcb创建并拷贝数据
进程终止:
进程退出场景: 正常退出(结果符合预期、结果不符合预期)、异常退出(常见的程序奔溃)
如何退出:
main函数中的return 退出前刷新缓冲区 函数中调用只是退出函数
exit: 三号手册---库函数手册 退出前刷新缓冲区 任意位置调用都是退出进程
_exit: 二号手册---系统调用手册 不会刷新缓冲区,缓冲区的数据被丢弃
ateit传的是函数指针
进程等待:
等待子进程的状态改变(等待子进程退出-----获取子进程的退出返回值(退出原因)
Q:为什么要等待子进程的退出?
A:因为子进程退出时为了保存退出原因,因此操作系统不能释放子进程的全部资源,因此通知父进程获取子进程
程的返回值,允许释放资源,但是这个通知是静音的,导致父进程没有关注到子进程退出,因此导致僵尸进程,
若父进程获取了子进程的返回值,僵尸子进程将没有存在的意义了,僵尸子进程会被释放掉资源,因为不知道子
进程何时退出,所以只能创建之后一直等着子进程的退出
Q:如何等待?
A:wait接口的功能是一直等待任意一个子进程退出,子进程退出后,就获取到返回值,放到传入的参数staus中,
如果一直没有子进程退出,wait函数将一直阻塞
Q:阻塞?非阻塞?
A:为了完成一个功能发起调用,当前若不具备完成条件,等待直到条件具备,完成功能后返回
为了完成一个功能发起调用,当前若不具备完成条件,立即报错返回
获取子进程退出返回值:
errno是一个全局变量,存储每次系统调用出现错误原因编号
strerror,通过错误编号获取字符串错误原因
peeor直接打印上一次系统调用错误原因
高16位不使用,低16位的高8位,放的是返回值,exit code 低8位中的高1位,储存core dump标志
核心转储:
程序异常退出的时候保存程序的运行信息,便于事后调试(包含各种敏感信息),所以默认关闭
剩余的低7位是异常退出信号值 操作系统检测到某种异常,把信号发给进程,进程自己退出
低7位如果是0,表示没有异常退出信号,正常退出;否则表示程序异常退出,返回值将不具有意义
获取低7位: statu & 0x7f
获取低16位中的高8位: (statu >>8) & 0xff
exit code最大值255