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



相关文章
|
17天前
|
算法 Linux 调度
深入理解Linux操作系统的进程管理
本文旨在探讨Linux操作系统中的进程管理机制,包括进程的创建、执行、调度和终止等环节。通过对Linux内核中相关模块的分析,揭示其高效的进程管理策略,为开发者提供优化程序性能和资源利用率的参考。
43 1
|
2月前
|
资源调度 Linux 调度
Linux c/c++之进程基础
这篇文章主要介绍了Linux下C/C++进程的基本概念、组成、模式、运行和状态,以及如何使用系统调用创建和管理进程。
48 0
|
5天前
|
存储 监控 Linux
嵌入式Linux系统编程 — 5.3 times、clock函数获取进程时间
在嵌入式Linux系统编程中,`times`和 `clock`函数是获取进程时间的两个重要工具。`times`函数提供了更详细的进程和子进程时间信息,而 `clock`函数则提供了更简单的处理器时间获取方法。根据具体需求选择合适的函数,可以更有效地进行性能分析和资源管理。通过本文的介绍,希望能帮助您更好地理解和使用这两个函数,提高嵌入式系统编程的效率和效果。
47 13
|
12天前
|
SQL 运维 监控
南大通用GBase 8a MPP Cluster Linux端SQL进程监控工具
南大通用GBase 8a MPP Cluster Linux端SQL进程监控工具
|
20天前
|
运维 监控 Linux
Linux操作系统的守护进程与服务管理深度剖析####
本文作为一篇技术性文章,旨在深入探讨Linux操作系统中守护进程与服务管理的机制、工具及实践策略。不同于传统的摘要概述,本文将以“守护进程的生命周期”为核心线索,串联起Linux服务管理的各个方面,从守护进程的定义与特性出发,逐步深入到Systemd的工作原理、服务单元文件编写、服务状态管理以及故障排查技巧,为读者呈现一幅Linux服务管理的全景图。 ####
|
1月前
|
缓存 监控 Linux
linux进程管理万字详解!!!
本文档介绍了Linux系统中进程管理、系统负载监控、内存监控和磁盘监控的基本概念和常用命令。主要内容包括: 1. **进程管理**: - **进程介绍**:程序与进程的关系、进程的生命周期、查看进程号和父进程号的方法。 - **进程监控命令**:`ps`、`pstree`、`pidof`、`top`、`htop`、`lsof`等命令的使用方法和案例。 - **进程管理命令**:控制信号、`kill`、`pkill`、`killall`、前台和后台运行、`screen`、`nohup`等命令的使用方法和案例。
138 4
linux进程管理万字详解!!!
|
25天前
|
缓存 算法 Linux
Linux内核的心脏:深入理解进程调度器
本文探讨了Linux操作系统中至关重要的组成部分——进程调度器。通过分析其工作原理、调度算法以及在不同场景下的表现,揭示它是如何高效管理CPU资源,确保系统响应性和公平性的。本文旨在为读者提供一个清晰的视图,了解在多任务环境下,Linux是如何智能地分配处理器时间给各个进程的。
|
1月前
|
存储 运维 监控
深入Linux基础:文件系统与进程管理详解
深入Linux基础:文件系统与进程管理详解
78 8
|
1月前
|
网络协议 Linux 虚拟化
如何在 Linux 系统中查看进程的详细信息?
如何在 Linux 系统中查看进程的详细信息?
72 1
|
1月前
|
Linux
如何在 Linux 系统中查看进程占用的内存?
如何在 Linux 系统中查看进程占用的内存?