【Linux】进程控制(进程退出方式)的理解和使用

1. fork的常规用法

  1. 一个父进程希望复制自己,使父子进程同时执行不同的代码段。例如,父进程等待客户端请求,生成子进程来处理请求。
  2. 一个进程要执行一个不同的程序。例如子进程从fork返回后,调用exec函数;

创建子进程去执行和父进程一样的代码:也是可以的,但是并没有意义,所以一般我们不会这么做;


2. fork调用失败的原因

1. 系统中有太多的进程;
进程的创建是比较耗费资源滴,单独对于一个进程来说:不单单是把代码和数据加载内存就可以,还要为它创建PCB,这个PCB就很耗费资源了;
2. 实际用户的进程数超过了限制;


3. 进程退出场景

1. 代码运行完毕,结果正确;
2. 代码运行完毕,结果不正确
3. 代码异常终止


对于第一种场景:一般我们使用0表示正常退出,也就是我们所谓的return 0语句,但是这个进程的return 0语句要表示进程退出状态,只能在 main函数中生效,也就是说,假如在其他函数出现 return 0语句,它不表示进程退出,只表示函数指向完毕返回一个结果罢了;
但是:一个进程运行完毕,它的返回值可以有很多的,不仅仅是0,只不过我们约定0是正常返回而已,如果,你愿意,也可以在你的程序之中,main函数返回其他任意的值,也可以表示进程退出,但是这样就没有任何意义了,因为在我们Linux中,进程的退出状态,都是用0来表示正常退出的,而假如你的进程是正退出,还返回其他不是0的值,那么显得你在搞事情了;


对于第二种场景:我们的进程也可以退出,但是返回的状态码并不是0,这个返回的状态码也就是return返回的值,当然也可以是exit 函数;而是其他值,在Linux中,非0值就表示异常退出,也即是这个代码运行结束了,但是并没有达到我们运行的预期,它也结束了;


我们关心:进程退出的结果不正确的情况,不会关心进程运行结束正常的状况,因为进程退出结果不正常,会有很多不一样的表示,非0的值那么多,每一个值,都可以表示不正确的原因是什么,正常退出就一个0值;
我们可以通过:C 标准库的一个函数 strerror查看状态码对应的原因;


在这里插入图片描述


#include<stdio.h>    
#include<string.h>    
int main()    
{    
  int i = 0;    
  for(;i<135;i++){                                                                                                                       
    printf("%d:%s\n",i,strerror(i));    
  }    
  return 0;    
}   

Linux测试状态码有134个,我这里截图只截取前面几个,由于图片太长就不截取了;
我们需要知道 strerror这个函数,可以查看状态码的原因即可;
在这里插入图片描述


第三种场景:异常退出的状态:代码没运行到return 0语句时候,可以就因为你的某种异常操作导致退出了;
比如越界内存,除于0操作等;其实我们也可以通过一些手段获得进程异常退出的原因,但是不是我们今天要讨论的话题;


4. 进程退出的方式

正常终止(可以通过 echo $? 查看进程退出码):

  1. 从main返回;
  2. 调用exit;
  3. _exit;

异常退出

  1. ctrl + c,信号终止;

对于:exit函数:参数就是退出码;exit函数有个特点:不管你是在哪个位置调用,只要运行到了exit函数, 就会使得你的进程退出;一旦进程退出,exit 后面的那些代码也就自然而然不会被执行了
在这里插入图片描述


#include<stdio.h>    
#include<string.h>    
#include<stdlib.h>    
int main ()    
{    
  printf("这是执行exit函数之前的代码我会被执行\n");    
  exit(0); //这里退出码可以给对应的原因,但我这里是瞎给的;    
  printf("我是exit函数之后的代码,我不会被执行");                                                                                        
  return 0;    
}  

测试结果如下:
在这里插入图片描述


exit 在退出进程时候,还会刷新我们的输出缓冲区内容,再退出进程的;


我们可以通过一个小demo来测试一下:

#include<stdio.h>    
#include<string.h>    
#include<stdlib.h>    
#include<unistd.h>                                                                                                                       
int main()    
{    
  printf("hello world");    
  sleep(4);    
  exit(0);//exit函数:进程退出时候,会刷新缓冲区的内容    
  //return 0;    
}  

结果:先睡4s再打印我们的 hello world;原因是 hello world 先存在缓冲区的,4s过后,执行了 exit,而exit会刷新缓冲区,所以才会有hello world到屏幕;
在这里插入图片描述


我们退出进程还有一个函数是_exit;它的使用和exit是完全一样的,但是,这个函数相对于exit就少了一个功能:
_exit并不会刷新缓冲区,它仅仅就是进程退出,不会做任何事情,不清理资源,不会关闭文件流等操作


在这里插入图片描述
这个图:可以表示_exit和exit的区别:exit是在进程退出时候,会做一些操作,而_exit进程推出时候,并不会做任何事情,而是直接退出;
进程退出都需要先进入操作系统内核的,进去清理PCB资源啥啥啥的;
并且我们上面所谈的缓冲区都是用户级别缓冲区,并不是内核级别的缓冲区;
很容易理解:假如不是在不是用户级缓冲区的话,_exit和exit都会进入内核,那么就会都刷新缓冲区,实际上,并不是这样;所以可以说:我们谈的刷新缓冲区都是用户级别的;


在这里插入图片描述


5. 进程退出是否会刷新缓冲区(用户级别)的总结

在这里插入图片描述


6. 进程退出总结

在这里插入图片描述


  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

呋喃吖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值