中国电子商务企业,广州抖音seo公司,个人手机版网站app怎么做,那个网站做宝贝主图好接上文 Linux进程优先级之后#xff0c;我们了解到僵尸进程与孤儿进程的形成原因#xff0c;既然是因为父进程没有接收子进程的退出状态导致的#xff0c;那么我们该如何去获取子进程的退出状态呢#xff1f;那本篇文章将围绕这个问题来解释进程。
环境 #xff1a; vsco…接上文 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(pnullptr){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\ngetpid());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;
}