【Linux】11. 进程控制

简介: 【Linux】11. 进程控制

小实验(谨慎测试)

在这里插入图片描述

1. 进程退出码的引出

在这里插入图片描述

2. 进程码的使用

在这里插入图片描述

3. 进程退出

3.1 进程退出情况

==进程退出分三种情况:==
1.代码运行完毕,结果正确 -- return 0;
2.代码运行完毕,结果不正确 -- 根据退出码判断错误情况
3.代码没有运行完毕,程序出现异常,退出码毫无意义

3.2 进程退出方式

在这里插入图片描述
对于第二第三种情况:exit()函数的底层实现就是通过调用_exit()系统接口来实现的。
我们再来看一种现象:
在这里插入图片描述
在这里插入图片描述

4. 进程等待

在之前进程状态的学习中,我们认识到一种状态--“僵尸状态” --"Z" ,僵尸状态的原因是由于父进程未接收子进程退出信息导致的,子进程一直处于僵尸状态等待父进程接收其退出信息。僵尸进程是一种危害,存在内存泄漏的问题,该如何解决呢?

--通过进程等待的方式解决僵尸问题,如何解决:进行回收子进程资源并接收子进程退出信息

4.1 进程等待方式

4.1.1 wait方法

在这里插入图片描述

4.1.2 waitpid方法

在正式认识waitpid方法之前我们需要先认识一个输出型参数status(专门接收并输出给操作系统的参数)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

再谈进程退出

进程退出会使进程进入僵尸状态,等待父进程或者操作系统接收退出结果,这时候进程会将自己的退出结果写入到自己的task_struct(PCB)
而wait/waitpid是系统调用接口,让操作系统去读取子进程的task_struct(PCB)的退出信息
==进程退出其他资源可以释放,但是PCB必须保留(确保操作系统/父进程接收到子进程退出的信息)==

5. 等待实现(操作系统)

操作系统是如何实现这种等待状态的呢? -- 分为阻塞等待和非阻塞等待

5.1 阻塞等待

在这里插入图片描述
在这里插入图片描述

5.2 非阻塞等待

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5.3 阻塞等待和非阻塞等待的区别

从上述代码还看不出来二者存在什么区别:
阻塞等待:一直处于等待状态
非阻塞等待:在等待的过程中还可以处理其他事务(主要体现在轮询等待的情况)
在这里插入图片描述

5.4 轮询等待的实现

在这里插入图片描述

6. 进程程序替换

在运行进程时,创建子进程的目的是什么?

  1. 想让子进程执行父进程代码的一部分:也就是执行父进程对应的磁盘代码的一部分
  2. 想让子进程执行一个全新的程序:让子进程想办法加载磁盘上指定的程序,并执行新程序的代码和数据
    (这种子进程加载新程序并运行的行为,我们称之为进程的程序替换)

    6.1 替换函数

    #include <unistd.h>
    int execl(const char *path, const char *arg, ...);
    int execlp(const char *file, const char *arg, ...);
    int execle(const char *path, const char *arg, ...,char *const envp[]);
    int execv(const char *path, char *const argv[]);
    int execvp(const char *file, char *const argv[]);
    
    替换函数的作用:将指定的程序(这里的程序指的是在磁盘当中保存的代码和数据)加载到内存当中,让指定的进程进行执行
    要使用替换函数首先需要先找到磁盘当中的程序,其次执行命令存在选项,例如:ls -a -l
    如何找到呢?-根据第一个参数 const char* path,来找到程序所在位置
    根据后面两个参数来实现执行命令参数的选项
    (其中括号中带... 这表示的是可变参数列表【可以给C语言传递多个不同个数的参数】)
    在这里插入图片描述
    很多函数都是存在可变参数列表的,例如上述的printf和scanf,这也就是为什么在打印时可以以不同的形式打印%d/%s等

    6.2 使用替换函数

    在这里插入图片描述
    在这里插入图片描述

    6.3 进程替换的原理

    用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),子进程往往要调用一种exec函数以执行另一个程序。
    当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行。
    调用exec并不创建新进程,所以调用exec前后该进程的id并未改变
    在这里插入图片描述
    在这里插入图片描述
    写时拷贝时,程序和数据就会在物理内存上占用新空间(保证了进程的独立性)
    ==这时候也就可以深刻理解shell创建子进程来执行对应的命令(王婆雇佣实习生的案例),==
    shell命令行解释器也是进程如果不创建子进程,
    直接进行程序替换那么我们也就无法通过shell接收返回结果,
    如果一旦是非法进程可能直接使得shell挂掉(这样也进一步保护shell)
    子进程挂掉不会影响父进程,且父进程可以接收子进程的错误原因并返回给用户

    7. exec* 系列函数的分析使用

    在这里插入图片描述
    其中子进程发生进程替换并不会影响父进程
    在这里插入图片描述

    7.1 对后缀进行分析

    在这里插入图片描述
    在这里插入图片描述
    实际上默认的环境变量,即便你不传,子进程也能获取
    那如果即想获取自定义的环境变量又想获取系统的环境变量该如何操作呢?
    在这里插入图片描述
    针对这些后缀分析完毕后,要了解一个概念,之前的学习过程中总是说程序要运行必须先加载到内存当中,如何加载呢?
    在Linux下采用的就是exec系列的接口 -- exec系列的函数又被称之为加载器
    提问我们在编写程序时main(int argc,charargv[ ],char env[ ])是先加载呢?还是先执行main函数?
    答案:先加载,main函数也是函数,也需要被调用传参,这些工作都离不开加载器
    而main函数中的三个参数正是从exec*系列函数当中的参数而来(环境变量/命令行参数)
    即便main函数不传递参数,子进程照样可以拿到系统默认的环境变量,通过environ表/虚拟地址空间的方式让子进程获取

    8. 替换自己写的程序

    以上的学习进程替换都是替换的系统命令,那如果我们想实现通过子进程替换我们自己编译的代码该如何实现呢?

    C语言

    在这里插入图片描述
    这只是C语言的情况,那么是否可以实现不同语言中的程序替换呢?
    答案:可以

    C++

    在这里插入图片描述

    Python

    在这里插入图片描述

    shell

    在这里插入图片描述
    程序替换,可以让任何后端语言调用起来(甚至java也可以,但是非常麻烦:java虚拟机的存在)

    系统命令

    在这里插入图片描述
    在这里插入图片描述

    总结

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