进程控制有关结束

文章介绍了进程退出的三种场景和exit函数的使用,强调了退出码在判断程序结果中的作用。wait和waitpid用于父进程等待子进程结束,获取子进程的退出信息,防止僵尸进程的产生。同时讨论了进程退出时操作系统所做的工作以及进程间通信的基础知识。
摘要由CSDN通过智能技术生成

进程控制有关结束

一般来说进程退出有三种场景:
1.代码跑完了,正常退出
2.代码跑完了,结果不对
3.代码直接异常终止了
当我们的代码出现异常,在我们vs里面出现的场景就是程序崩溃了,这时退出码也就没有了意义。
那么我们应该怎样查询最近一次进程退出时的代码呢?在shall里面用echo $?
main函数的return值时进程的退出码,那么退出码用来干嘛呢?答:退出码用来判断结果是否正确用的
返回0:默认success,出现其他的不同返回值对应不同的程序错误,毕竟错误的原因有很多,!0:fail

1.我们对main()函数的return,表示进程退出
2.非main函数return值,表示函数的返回值

exit

exit可以在任意地方直接调用,都表示终止进程,exit(a),这个a代表的就是退出码。
不管时exit还是直接main return本身都会要求系统刷新缓冲区,

_exit表示直接终止程序,是强行终止进程,不会进行后续的收尾工作,比如刷新缓冲区。
在这里插入图片描述
那么在进程退出时,OS层面会做什么呢?
当OS层面少了一个进程:会free掉PCB,free mm_struct,free 页表,代码+数据也会全部回收,申请的空间也会否掉。

二、wait,waitpid

我们知道fork():子进程:是为了帮助父进程完成某种任务用的,如果子进程没结束,父进程先结束了,子进程就会成为孤儿进程就被OS领养;如果子进程已经结束了,而父进程在死循环,子进程就会出现僵尸进程,那么为了避免出现子进程都成僵尸了没人理,我们的父进程在fork之后就需要wait/waitpid进行等待子进程完成它的使命。
那么为什么要让父进程等待呢?
1.通过获得子进程退出的信息,能得知子进程执行的结果。
2.可以保证:时序问题,子进程先退出,父进程后退出,父进程必须得等子进程完成之后才能结束
3.进程退出时会先进入僵尸状态,会造成内存泄漏的问题,需要通过父进程的wait来该子进程占用的资源。

  1 #include <stdio.h>
  2 #include<string.h>
  3 #include<stdlib.h>
  4 #include<unistd.h>
  5 #include <sys/types.h>
  6 #include<sys/wait.h>
  7 
  8 int main()
  9 {
 10   pid_t id=fork();
 11   if(id<0)
 12   {
 13      perror("fork");
 14      exit(1);//进程运行完毕,结果不正确
 15   }
 16   else if(id==0)
 17   {
 18 //子进程
 19     int cnt=5;
 20     while(cnt)
 21     {
 22      // int*p=NULL; 
 23     //  *p=100;
 24       printf("cnt: %d,我是子进程,pid: %d,ppid:%d\n",cnt,getpid(),getppid());                                                                  
 25       sleep(1);
 26       cnt--;
 27     }
 28     exit(202);//终止了子进程
 29   }
 30   else{
 31     //父进程
 32      printf("我是父进程,pid:%d,ppid:%d\n",getpid(),getppid());
 33   //  pid_t ret=wait(NULL);//父进程在阻塞式的等待
 34     int status=0;
 35      pid_t ret=waitpid(id,&status,0);//等价于wait
 36     if(ret>0)
 37     {
 38       printf("等待子进程成功,ret:%d,子进程收到的信号编码:%d,子进程退出码status:%d\n",ret,status&0x7F,(status>>8)&0xFF);
 39     }
 40     }
 41       } 

在这里插入图片描述
可以看到,这里确实父进程得到了子进程的退出码。从上面的代码中,我们看到在以后的多进程的基础写法就是要靠wait/waitpid。

pid_t waitpid(pid_t pid,int*status,int options);

其中:1.pid=-1等待任意一个子进程与wait
2. pid>0,等待其进程ID与pid相等的子进程
这上下两个都可以

status:输出型参数,status并不是按整数来整体使用的,而是按照32位来进行划分,在这里我们只看低16位。

程序异常退出或者崩溃的本质时:OS杀掉了你对进程。
OS是怎么杀掉呢?答:本质是通过发送信号的方式,OS发送不同的信号来杀死我们的进程。

为什么父进程可以通过wait函数来拿到子进程的结果呢?
因为进程具有独立性,那么数据就要发生写时拷贝,父进程就无法拿到,调用wait函数本质其实就是读取了子进程的task_struct结构

我们知道僵尸进程:至少是会保留该进程的PCB信息的,task_struct里面就保留任何进程退出时的退出结果信息

总结

了解了有关wait函数,了解了多进程的控制和结束的使用。
6月19号

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值