进程创建等待与终止
进程的创建:
Linux通过fork函数进行进程的创建
他从已存在的进程中创建一个新进程。新进程为子进程,而原进程为父进程。
#include <unistd.h>
pid_t fork(void);
子进程返回0,父进程返回子进程pid,出错返回-1
进程调用fork后,内核分配新的内存块和内存数据结构给子进程,将父进程部分数据结构内容拷贝至子进程,添加子进程到系统进程列表中,fork返回,开始调度器调度
fork之前父进程独立运行,fork之后,父子两个执行流分别执行。fork之后,谁先执行完全由调度器决定.
父子代码共享,父子不再写入时,数据也是共享的。当有一方试图写入时,便以写时拷贝的方式各自私有一份。
fork的常规用法:
一个父进程希望复制自己,使父子进程同时执行不同的代码段。
一个进程要执行一个不同的程序。
fork调用失败的原因:
- 系统中有太多的进程(资源不够用,有上限,pcb太大)
- 实际用户的进程数超过了限制。
vfork用于创建一个子进程,而子进程和父进程共享地址空间,fork的子进程具有独立的地址空间。
vfork保证子进程先运行,在他调用exec或exit之后父进程才可能被调度运行。
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <sys/types.h>
4
5 int a=100;
6 int main()
7 {
8 pid_t id=vfork();
9 if(id==-1)
10 {
11 perror("fork");
12 exit(1);
13 }
14 if(id==0)
15 {
16 //child
17 a=200;
18 printf("%d\n",a);
19 exit(1);
20 }else{
21 //parent
22 printf("%d\n",a);
23 }
24 return 0;
25 }
进程终止
进程终止的三种情况:
- 代码运行完毕,结果正确
- 代码运行完毕,结果不正确
- 代码异常终止
进程常见的退出方法
正常终止(可以通过echo $? 查看进程退出码)
$? 用来保存最近一条进程的退出码
1.从main返回 (main的返回值,正确为0不正确不为0)
2.调用exit
3.调用_exit
exit与_exit的区别:
_exit:不刷新内存的缓存区
exit: 会刷新内存的缓存区
异常退出:
ctrl+c 信号终止
#include <unistd.h>
void _exit(int status);
void exit(int ststus);
//status 定义了进程的退出状态,父进程通过wait获取该值,但是仅有低八位可以被父进程使用
exit在最后还是会第调用_exit,但此之前要
-
执行用户定义的清理函数
-
关闭打开的流,刷新缓冲
进程等待
僵尸进程无法被杀死,只能被回收
-
父进程回收子进程的资源,避免内存泄漏
-
获取子进程的退出信息,以此来判断子进程的退出状态
进程等待的方法:
wait
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int* status)
成功返回子进程的pid,失败返回-1
输出型参数,获取进程退出状态,不关心可以设置位NULL
如果有多个子进程,父进程等待任意一个退出的子进程
waitpid
#include <sys/types.h>
#include <sys/wait.h>
pid_t waitpid(pid_t pid,int* status,int options)
返回值:
- 当正常返回时,外套披的返回收集到的子进程的id;
- 如果设置了选项WNOHANG,而调用中的waitpid发现没有可收集的子进程的pid则返回0;
- 如果调用中出错,则返会1,这时erron会被设置成相应的值以知识错误的所在
参数:
pid:
pid=-1,等待任意一个子进程,与wait等效
pid=0,等待id与其相等的子进程
status:
WIFEXITED(status):若为正常终止子进程则返回为真(查看进程是否正常退出)
WEXITSTATUS(status):若WIFEXITED非0,提取子进程的退出码(查看进程的退出码)
options:
WNOHANG:若pid指定的子进程没有结束,waitpit()返回0,不予等待。如果正常退出,返回u该进程的id.
如果子进程已经退出,调用wait/waitpid时,wait/waitoid会立即返回,回收资源,获取子进程退出信息。
如果在任意时刻调用wait/waitpid,子进程存在且正常运行,则进程可能阻塞。
如果不存在该进程则立即出错返回
程序等待调用结果时的状态
阻塞式:
就是指在执行设备操作时若不能获得资源则挂起操作,直到满足可操作的条件后再进行操作,被挂起的进程进入休眠状态,被从调度器的运行队列移走,直到等待的条件满足。
非阻塞式:进程在不能进行设备操作时并不挂起,它或者放弃,或者不停的查询,直到可以进行位置。
周期性的去检测某项事物是否发生是基于非阻塞轮寻式
获取子进程status
wait 和waitpid都有一个status参数,该参数是一个输出性参数,由操作填充
如果传递NULL表示不关心子进程的退出信息
status不能简单的当作整形来看,可以当作位图来看,只研究status的低16比特位
正常终止时高8位为退出状态
被信号所杀时 低七位为终止信号 第八位为core dump标志(异常退出信号)
kill -l 查看所有退出信号
1~64 无31 32