【Linux系统化学习】进程终止的奥秘

=========================================================================

个人主页点击直达:小白不是程序媛

Linux专栏:Liunx系统化学习

代码仓库:Gitee

=========================================================================

目录

获取函数返回值

退出码

进程退出的场景

错误码

信号终止异常代码

进程的终止

main函数直接return

exit函数

_exit函数


获取函数返回值

在C语言学习过程中,每次主函数或者自己写的函数都会返回一个值(return x),而且在main函数最后我们通常会返回0(return 0 ),那么这个值返回给谁呢?必须返回0吗?返回其他的数字不行吗?有什么用呢?

其实在Linux中我们可以使用指令拿到这个main函数最后的返回值

echo $?

复制代码
int main()
{
    return 10;
}

我们什么也不干只需要在main函数中返回一个非0数,使用上面的指令获取;

其实在Liunx中 就相当于一个环境变量保存最近一次进程的返回值


退出码

在Linux中运行我们编写的程序相当于创建一个新的进程,我们又知道每个进程都有自己的父进程,这样就通了:当我们的代码运行完毕时进程会退出,子进程是由父进程创建用来完成某些任务的,子进程退出时父进程肯定要知道子进程任务完成得怎么样,因此子进程需要返回一些信息,这些信代表着子进程任务完成得怎样。

进程退出的场景

  • 代码运行完毕,结果正确
  • 代码运行完毕,结果不正确
  • 代码异常终止

就像在现实生活中我们完成一些任务也只有这三种情况:任务完成了,拿到好的结果;任务完成了,没有拿到好结果;完成任务时因为一些突发状况没能完成,终止了;

在C语言中返回0代表success非0代表failed ;这些0或者非0的数字就代表进程的退出码 ,每个不同的数字代表程序退出的不同原因这就是退出码

然而非0的数字又有很多,随便说一个数字我们也不知道是什么意思不是很便于人们理解;这个数字的意义可以自己定义,但是在C语言库中存在;

复制代码
  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<stdlib.h>
  4 #include<string.h>                                                                                                                                                    
 18 int main()
 19 
 20 {
 21     int i =0 ;
 22     for(i =0 ;i<200 ;i++)
 23     {
 24         printf("%d %s\n",i,strerror(i));
 25     }
 26     return 10;
 38 }

总共有133退出码,每个退出码都有其指定的含义;

因此父进程通过获取子进程的退出码得知子进程运行结束后的结果。


错误码

编写程序时我们会使用各种的系统调用 或者使用库函数,当然进行这些调用时也会出现调用失败,影响我们的程序运行。因此C语言中有一个宏常量errno代表我们进行系统的出错信息,调用结束后会自动设置;

复制代码
    #include<stdio.h>
    2 #include<unistd.h>
    3 #include<stdlib.h>
    4 #include<string.h>
    5 #include<errno.h>
   18 int main()
   19 
   20 {
   21     printf("before : %d \n",errno);
   22     FILE *pf = fopen("data.txt","r");
   23     printf("before : %d \n",errno);
   24     printf("%s\n",strerror(errno));
       }

使用库函数打开一个文件时,当文件不存在时调用的库函数就要返回指定的数字也就是errno,代表着调用库函数结束的结果,配合strerror可以清楚的得到程序运行的结果的具体原因。

退出码与错误码

  • 错误码通常是衡量一个库函数或者一个系统调用一个函数的调用情况
  • 退出码通常时一个进程退出的时候,其自己退出的结果
  • 都是用来衡量函数、进程出错的详细原因。

信号终止异常代码

代码能运行结束是是上面的情况,还有一种特别严重的问题就是代码运行期间由于代码异常而造成的进程终止,代码异常时退出码或者错误码已经没有任何意义了。

复制代码
  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<stdlib.h>
  4 #include<string.h>  
  5 #include<errno.h>   
 17   
 18 int main()  
 19 {
 20     int i = 10/0;
 21     return 0;   
    }

在编译期间就会报异常,运行这个代码会报浮点数异常;因为非法的操作,操作系统通过信号会终止这个进程;

因此一个进程是否出异常,我们只需要看有没有收到信号即可;


进程的终止

main函数直接return

复制代码
  1 #include<stdio.h>  
  2 int func()  
  3 {  
  4     return 1;
  5 }
  6 int main()
  7 {
  8     func();                                                                                                                                                                            
  9     return 0;                                                                                                              
 10 }  

通过上面的实验我们我们可以得出结论:在其他函数中return,表示的是这个函数的调用结束而不是进程的终止;

exit函数

我们对上面的程序进行修改,直接在main函数一开始调用exit函数;

复制代码
  1 #include<stdio.h>
    2 int func()
    3 {
    4     return 1;
    5 }
    6 int main()
    7 {
    8     exit(30);                                                                                                                                                                        
    9     func();
   10     return 0;
   11 }

我们会发现exit会直接终止进程,不会执行后面的代码,且exit的参数为这个进程的退出码。

_exit函数

相同点:

exit函数和_exit函数都是用来终止进程的,参数都是此进程的退出码。

不同点:

  • exit()函数是库函数底层使用_exit函数包装起来的
  • _exit()函数是系统调用
  • exit()函数终止进程的时候,会自动刷新缓冲区。
  • _exit()函数终止进程的时候不会自动刷新缓冲区。

今天对Linux下进程的终止的分享到这就结束了,希望大家读完后有很大的收获,也可以在评论区点评文章中的内容和分享自己的看法。您三连的支持就是我前进的动力,感谢大家的支持!!!

相关推荐
磊灬泽几秒前
【日常错误】鼠标无反应
linux·windows
知白守黑2674 分钟前
Ansible角色
运维·服务器·ansible
Jwest20214 分钟前
工业显示器在地铁电力监控与运维中的应用
运维·计算机外设
知识分享小能手28 分钟前
React学习教程,从入门到精通, React 属性(Props)语法知识点与案例详解(14)
前端·javascript·vue.js·学习·react.js·vue·react
茯苓gao3 小时前
STM32G4 速度环开环,电流环闭环 IF模式建模
笔记·stm32·单片机·嵌入式硬件·学习
是誰萆微了承諾3 小时前
【golang学习笔记 gin 】1.2 redis 的使用
笔记·学习·golang
DKPT4 小时前
Java内存区域与内存溢出
java·开发语言·jvm·笔记·学习
aaaweiaaaaaa4 小时前
HTML和CSS学习
前端·css·学习·html
Miracle&4 小时前
2.TCP深度解析:握手、挥手、状态机、流量与拥塞控制
linux·网络·tcp/ip
专注API从业者4 小时前
Python/Java 代码示例:手把手教程调用 1688 API 获取商品详情实时数据
java·linux·数据库·python