Linux进程控制(2)

简介: Linux进程控制(2)

二、进程终止


1、退出码


概念:

其实main函数是间接性被操作系统所调用的,当main函数调用结束后就应该给操作系统返回相应的退出信息,而这个所谓的退出信息就是以退出码的形式作为main函数的返回值返回


我们一般以0表示代码成功执行完毕,以非0表示代码执行过程中出现错误,一般来说我们写的代码都不太规范,没有根据执行结果返回相应的退出码


注:退出码可以人为定义,也可以使用系统的错误码表


示图:系统错误码表


退出码查看:

使用指令 echo $?


示例:


注:如果main没有return,则echo $?查看的是最近函数的退出码,一般来说都是0


2、退出方法


  • 进程退出场景:


  1. 代码运行完毕,结果正确,退出码为0
  2. 代码运行完毕,结果不正确,逻辑存在问题,退出码为非0
  3. 代码异常终止,层序崩溃,退出码没有意义


  • 进程常见退出方法:


1) 调用_exit函数


  • _exit函数原型:


#include <unistd.h>
void _exit(int status);


  • 注意:
  1. status 定义了进程的终止状态,父进程通过wait来获取该值
  2. 虽然status是int,但是仅有低8位可以被父进程所用

注:_exit(-1)时,在终端执行$?发现返回值是255

  • 示图:


2)调用exit函数


  • exit函数原型:


#include <unistd.h>
void exit(int status);


exit与_exit的区别:

_exit仅仅是退出进程


exit在退出进程前,先执行用户通过 atexit或on_exit定义的清理函数,关闭所有打开的流,所有的缓存数据均写入(刷新缓冲区),最后调用_exit


示图:


示例:


3)main函数return



return是一种更常见的退出进程方法,执行return n等同于执行exit(n),因为调用main的运行时函数会将main的返回值当做exit的参数


示图:


注意:

只有是在main函数的的return才算是终止进程,其他函数return只是结束函数,因为系统调用的是main函数,main函数返回才是进程的返回


调用main函数运行结束后,main函数的return返回值当做exit的参数来调用exit函数,而使用exit函数退出进程前,exit函数会先执行用户定义的清理函数、冲刷缓冲,关闭流等操作,然后再调用_exit函数终止进程


4)异常退出

向进程发生信号

如在进程运行过程中向进程发生kill -9信号使得进程异常退出,或是使用Ctrl+C迫使进程退出


代码运行异常

如代码当中存在野指针问题等bug问题使得进程运行时异常退出


3、理解终止

以OS角度理解:核心思想-归还资源

释放曾经为管理进程所维护的数据结构资源,并非销毁释放数据结构对象,而是将状态设置为无效并保存起来,下一次需要就直接使用不用申请,相当于建立对应的数据结构“内存池”


释放程序数据和代码占用的空间,并非清空数据和代码,而是将对应内存区域设置为无效,要再次使用时直接覆盖数据和代码就行了


取消曾经该进程在进程队列里的链接关系(避免”野指针“)


三、进程等待


进程等待必要性:

当子进程退出,并不是完全退出,子进程的PCB任然存在,父进程如果不等待回收,就可能造成‘僵尸进程’的问题,进而造成内存泄漏


注:进程一旦变成僵尸状态,并不能被父进程给kill掉,因为子进程已经死去,只能父进程等待回收


子进程的PCB保留着退出前任务执行的信息,而通过回收子进程我们可以知道子进程运行完成,结果对还是不对,或者是否正常退出


注:非必须,依执行的程序和需求而定


尽量使父进程晚于子进程退出,可以规范化进行资源的回收


注:所以一般来说,当我们fork之后,就需要父进程等待回收子进程


1、等待方法

wait方法:

wait函数原型:


#include<sys/types.h>
#include<sys/wait.h>
pid_t wait(int*status);


  • 注意:


  1. wait函数作用的等待任意子进程
  2. 返回值:成功返回被等待进程pid,失败返回-1
  3. 参数:输出型参数,获取子进程退出状态,不关心则可以设置成为NULL


  • waitpid方法:


waitpid函数原型:



#include<sys/types.h>
#include<sys/wait.h>
pid_ t waitpid(pid_t pid, int *status, int options);


注意:

返回值:


当正常返回的时候waitpid返回收集到的子进程的进程ID


如果设置了选项options为WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0;如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在


参数pid:


Pid=-1,等待任一个子进程,与wait等效


Pid>0,等待其进程ID与pid相等的子进程


参数status:


参数status是一个输出型参数,需要我们传入一个整形变量的地址,以此获取子进程退出的信息


使用对应的宏可以查看我们需要的退出信息:WIFEXITED(status): 若为正常终止子进程返回的状态,则为真(查看进程是否是正常退出);WEXITSTATUS(status): 若WIFEXITED非零,提取子进程退出码(查看进程的退出码)


参数options:


设置为0:表示默认的阻塞式等待子进程退出,即子进程没退出就不返回,一直等待到子进程退出回收子进程


设置为WNOHANG:若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待;若正常结束,则返回该子进程的ID


示例1:阻塞等待


#include<stdio.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>
#include<stdlib.h>
int main()
{
    pid_t id=fork();
    if(id==0)
    {
        printf("I am child process:  pid:%d ppid:%d\n",getpid(),getppid());
        sleep(5);
       // int* p=12345;
       // *p=100;//野指针
        exit(123);
    }
    printf("father wait...\n");
    int status=0;
    //pid_t ret=wait(&status);//等待特定任意子进程
    pid_t ret=waitpid(id,&status,0);//阻塞等待特定子进程
    if(ret>0&&WIFEXITED(status))//等待成功并子进程退出正常
    {
        printf("wait success: wait for id:%d status code:%d\n",ret,WEXITSTATUS(status));
    }
    else if(ret>0)//等待成功但是子进程退出异常
    {
        printf("exit error! status codedump:%d sign:%d\n",(status>>7)&1,status&0x7F);
    }
    return 0;
}


image.png



相关文章
|
1月前
|
资源调度 Linux 调度
Linux c/c++之进程基础
这篇文章主要介绍了Linux下C/C++进程的基本概念、组成、模式、运行和状态,以及如何使用系统调用创建和管理进程。
35 0
|
3月前
|
网络协议 Linux
Linux查看端口监听情况,以及Linux查看某个端口对应的进程号和程序
Linux查看端口监听情况,以及Linux查看某个端口对应的进程号和程序
634 2
|
3月前
|
Linux Python
linux上根据运行程序的进程号,查看程序所在的绝对路径。linux查看进程启动的时间
linux上根据运行程序的进程号,查看程序所在的绝对路径。linux查看进程启动的时间
67 2
|
13天前
|
缓存 监控 Linux
linux进程管理万字详解!!!
本文档介绍了Linux系统中进程管理、系统负载监控、内存监控和磁盘监控的基本概念和常用命令。主要内容包括: 1. **进程管理**: - **进程介绍**:程序与进程的关系、进程的生命周期、查看进程号和父进程号的方法。 - **进程监控命令**:`ps`、`pstree`、`pidof`、`top`、`htop`、`lsof`等命令的使用方法和案例。 - **进程管理命令**:控制信号、`kill`、`pkill`、`killall`、前台和后台运行、`screen`、`nohup`等命令的使用方法和案例。
44 4
linux进程管理万字详解!!!
|
4天前
|
存储 运维 监控
深入Linux基础:文件系统与进程管理详解
深入Linux基础:文件系统与进程管理详解
41 8
|
13天前
|
算法 Linux 定位技术
Linux内核中的进程调度算法解析####
【10月更文挑战第29天】 本文深入剖析了Linux操作系统的心脏——内核中至关重要的组成部分之一,即进程调度机制。不同于传统的摘要概述,我们将通过一段引人入胜的故事线来揭开进程调度算法的神秘面纱,展现其背后的精妙设计与复杂逻辑,让读者仿佛跟随一位虚拟的“进程侦探”,一步步探索Linux如何高效、公平地管理众多进程,确保系统资源的最优分配与利用。 ####
46 4
|
13天前
|
缓存 负载均衡 算法
Linux内核中的进程调度算法解析####
本文深入探讨了Linux操作系统核心组件之一——进程调度器,着重分析了其采用的CFS(完全公平调度器)算法。不同于传统摘要对研究背景、方法、结果和结论的概述,本文摘要将直接揭示CFS算法的核心优势及其在现代多核处理器环境下如何实现高效、公平的资源分配,同时简要提及该算法如何优化系统响应时间和吞吐量,为读者快速构建对Linux进程调度机制的认知框架。 ####
|
15天前
|
消息中间件 存储 Linux
|
21天前
|
运维 Linux
Linux查找占用的端口,并杀死进程的简单方法
通过上述步骤和命令,您能够迅速识别并根据实际情况管理Linux系统中占用特定端口的进程。为了获得更全面的服务器管理技巧和解决方案,提供了丰富的资源和专业服务,是您提升运维技能的理想选择。
23 1
|
1月前
|
算法 Linux 调度
深入理解Linux操作系统的进程管理
【10月更文挑战第9天】本文将深入浅出地介绍Linux系统中的进程管理机制,包括进程的概念、状态、调度以及如何在Linux环境下进行进程控制。我们将通过直观的语言和生动的比喻,让读者轻松掌握这一核心概念。文章不仅适合初学者构建基础,也能帮助有经验的用户加深对进程管理的理解。
21 1