当前位置: 首页 > news >正文

Linux操作系统 进程(3)

接上文 Linux进程优先级之后,我们了解到僵尸进程与孤儿进程的形成原因,既然是因为父进程没有接收子进程的退出状态导致的,那么我们该如何去获取子进程的退出状态呢?那本篇文章将围绕这个问题来解释进程。

环境 : vscode 链接 Centos 7

进程退出状态

还记得我们刚开始学习C语言的时候 main 函数 return吗,这个就算是这个程序退出的信息,那么我们所谓的进程的退出信息有什么呢? 不就是 进程正常退出且运行结果正确, 进程正常退出且运行但结果不正确和进程异常退出,那么对于父进程来说,这些信息就是父进程在对子进程进一步规划或者说是下一步操作的关键信息。

echo $?

在终端页面上,我们可以使用 "echo $?" 去获取上一个进程的退出信息,我们可以写一个程序让他正常退出,和异常退出,用来展示退出信息的不同。

echo $?

 既然在终端里,我们使用 echo $? 可以获得上一次进程退出的退出信息,那么Linux定义进程退出的退出信息是什么?

退出码 strerror

在官方文档定义中

我们可以通过函数来查看这些退出码分别对应的推出信息是什么,我们可以先尝试看几个

#include <iostream>
//#include <unistd.h>
#include <string.h>
using namespace std;int main()
{for (int i = 0; i < 5; i++){cout << i << ":" << strerror(i) << endl;}return 0;
}

 errno

保存的最近的一次的错误码

我们可以尝试申请很大的一块空间让malloc失效去看看错误信息是什么

int main()
{int *p = (int *)malloc(1000 * 1000 * 1000 * 4);  //4GB 后面学习后,程序被分配的所有空间也就4Gif(p==nullptr){cout << "errno" << ":" << errno << endl;perror("malloc error");}return 0;
}

_exit和exit

这两个函数一个是系统调用接口,一个是C语言库函数,主要的区别就在于C语言程序内部定义的缓冲区,在使用这两个函数终止程序的时候,系统调用接口_exit并不知道C语言程序内部存有缓冲区,并不会将其中的内容输出出来,但是exit会先把这个缓冲区内部信息先输出出来,再终止程序。

int main()
{printf("我存放在缓冲区内");//不使用 /n进行换行刷新缓冲区exit(12);   //_exit()return 0;
}

但是使用_exit() 并不会输出任何信息 

exit和_exit的退出信息也是退出码!

进程等待

 进程等待是在等待谁呢? 那肯定不用想,就是等待子进程退出,接收到退出信息后,回收资源

wait

函数参数的指针就是为了获取子进程的退出信息(因为C语言没有引用),函数返回值是当前等待到的进程的pid,我们可以让子进程return或者exit让父进程去获取退出信息 status

int main()
{pid_t id = fork();if(id == 0){printf("子进程pid: %d\n", getpid());exit(1);}else if(id < 0){perror("进程创建失败:");}else{int status;wait(&status);printf("子进程 status: %d\n",status);}return 0;
}

 

我们会发现,我们的exit退出信息是 1 ,但是为什么status 里返回的值是 256

status

在官方介绍中,status就是进程退出的具体信息,它将一个int分成几段,用这几段来返回不同的信息,同时我们可以看到,接口中提供了很多宏用来获取status里存放的不同段的返回信息,其中 WIFEXITED ,就是用来判断子进程是否正常返回,WEXITSTATUS 就是获得子进程退出信息,如果WIFEXITED 返回true ,子进程正常退出,子进程在正常退出的返回信息就使用WEXITSTATUS 进行获得(return  exit)

int main()
{pid_t id = fork();if(id == 0){printf("子进程pid: %d\n", getpid());return 12;}else if(id < 0){perror("进程创建失败:");}else{int status;wait(&status);if(WIFEXITED(status)){printf("子进程 status: %d\n",status);printf("exit: %d\n", WEXITSTATUS(status));}else{printf("子程序异常退出\n");}}return 0;
}

 这个WIFEXITED 是用来判断子进程是否由exit或者 return退出的,如果是就返回true然后我们就可以使用WEXITSTATUS 来查看正常退出的退出码

waitpid

wait函数可以回收所有子进程,获取他们的退出信息,但是如果我们想要对不同进程的退出进行不同的操作呢?

pid_t id

回收子进程id 为 这个id的进程 ,抽象,就是我们可以通过waitpid这个函数,并传入子进程的id,用来等待这个子进程,我们也可以通过传入参数为 -1 用来回收所有子进程。

int main()
{pid_t id1 = fork();if(id1 == 0){printf("子进程pid: %d\n", getpid());return 12;}else if(id1 < 0){perror("进程创建失败:");}pid_t id2 = fork();if(id2 == 0){printf("子进程pid: %d\n", getpid());return 14;}else if(id2 < 0){perror("进程创建失败:");}int status;waitpid(id1, &status, 0);//使用阻塞等待if (WIFEXITED(status)){printf("子进程 status: %d\n",status);printf("exit: %d\n", WEXITSTATUS(status));}else{printf("子程序异常退出\n");}waitpid(id2, &status, 0);//使用阻塞等待if (WIFEXITED(status)){printf("子进程 status: %d\n",status);printf("exit: %d\n", WEXITSTATUS(status));}else{printf("子程序异常退出\n");}return 0;
}

options

父进程对子进程的等待方式

参数 :0

阻塞等待,若等待的子进程没有结束,那父进程就会阻塞到当前语句,一直等待子进程结束,

参数 :WNOHANG

非阻塞轮询,父进程每一次运行到这个地方的时候,都会接收waitpid的返回值,返回0就是子进程还没有结束,返回非0就是子进程已经结束了,可以进行回收工作了!

int main()
{pid_t id1 = fork();if(id1 == 0){int ret = 3;while(ret--){printf("子进程任务ing pid: %d\n",getpid());sleep(1);}return 0;}else if(id1 < 0){perror("进程创建失败:");}else{int status;while (1){//waitpid(id1, &status, WNOHANG);//使用非阻塞轮询if(waitpid(id1, &status, WNOHANG)){if (WIFEXITED(status)){printf("子进程 status: %d\n",status);printf("exit: %d\n", WEXITSTATUS(status));}else{printf("子程序异常退出\n");}break;}sleep(1);printf("等待ing....\n");}}return 0;
}


http://www.mrgr.cn/news/30939.html

相关文章:

  • 在 ALV 报表中使用 CL_SALV 类时,如何处理多行?
  • TP6将HTML转换为PDF文件,非法UTF-8编码和中文乱码问题
  • Qt 获取当前系统中连接的所有USB设备的信息 lsusb版
  • Go语言中的`io.Copy`函数:高效的数据复制解决方案
  • Linux apt 命令
  • caozha-pinyin(中文转拼音源码)
  • 免密执行远程服务命令
  • Revit学习记录-版本2018【持续补充】
  • Streamlit:使用 Python 快速开发 Web 应用
  • 我的数据库旅程:从迷茫到觉醒
  • 1332. 删除回文子序列 脑筋急转弯
  • 《俄语翻译通》app一款专业的俄文OCR识别器,学俄语不会颤音怎么办?《俄语翻译通》可以帮助你!
  • Windows用管理员运行cmd命令后无法切换盘符
  • 23个Python在自然语言处理中的应用实例
  • TiDB 中的自增主键有哪些使用限制,应该如何避免?
  • HCL Domino 14.5EAP1快问快答
  • 解决Filament中使用ARCore出现绿色闪屏的问题
  • 力扣150题——多维动态规划
  • 【高阶用法】uniapp的i18n多语言模块修复与增强(Typescript)
  • numpy之随机抽样函数np.random.choice()
  • 阿里云大模型,这次云栖大会又“卷”出了新高度!
  • 【PostgreSQL教程】PostgreSQL详细介绍
  • Bayes networks可视化工具-Netica
  • 【C++】——多态详解
  • STM32cubeMX + VScode开发GD32移植(HAL库通用),保姆级!!!!!!!
  • 住宅代理IP如何提高 IP声誉?