DP读书:《openEuler操作系统》(五)进程与线程

进程与线程

  • 进程的概念
    • 程序:从源码到执行
      • 1. 编译阶段:
      • 2. 加载阶段:
      • 3. 执行阶段:
    • 程序的并发执行与进程抽象
  • 进程的描述
    • 进程控制块
      • 1. 描述信息
      • 2. 控制信息
      • 3. CPU上下文
      • 4. 资源管理信息
    • 进程状态
      • 1.就绪状态
      • 2.运行状态
      • 3.阻塞状态
      • 4.终止状态
  • 进程的控制
    • 进程控制源语
      • 1.创建
      • 2.销毁
      • 3.阻塞与唤醒
    • 进程创建
      • 1.PCB的复制
      • 2.CPU上下文的复制
      • 3.地址空间的复制
    • 程序装载
      • 1.exec函数簇的系列函数接口
      • 2.可执行文件的寻找与打开
      • 3.可执行文件的装载
      • 4.新程序的执行
    • 进程终止
      • 1.用户资源的回收
      • 2.状态信息的发送与僵尸状态的设置
      • 3.内核资源的回收
      • 4.为所有子进程寻找新父进程
    • openEuler中的进程树

这章我啃了很久,作为计算机领域最为重要的两个概念之一,今天我想讲一讲进程的概念、描述、控制。这三小结的内容,差不多我每天啃一小节终于啃完了,那就敲吧~~~

现代计算机采用多道程序技术,允许多个程序并发执行,不同于早期的单道批处理系统计算机只能一次性处理一道的。而在这个过程中,程序只是对计算任务与数据的静态描述,并不能反应多道程序之间相互影响的这一状态。因此计算机系统中使用进程这一概念来反映程序在执行过程以及能来共享资源的基本单位。另外由于进程的创建于切换之间切换资源开销较大,操作系统中引入了线程这一概念。

进程的概念

程序:从源码到执行

下图展示了一份C语言源代码(符合C99标准),判断日期是否为闰年。

好的,以下是一份C语言源代码,用于判断给定日期是否为闰年:

#include <stdio.h>int isLeapYear(int year) {if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {return 1;} else {return 0;}
}int main() {int year = 2024;if (isLeapYear(year)) {printf("%d is a leap year.\n", year);} else {printf("%d is not a leap year.\n", year);}return 0;
}

1. 编译阶段:

在编译阶段,编译器将源代码转换为机器代码。编译器首先检查代码的语法错误,例如拼写错误、缺失的括号等。如果源代码没有语法错误,编译器将创建一个可执行文件,其中包含计算机可以直接执行的机器代码。对于上述代码,编译器将检查变量和函数是否正确定义,然后将其转换为相应的机器代码。
闰年代码示例

以上为 C语言程序示例

gcc -o leap_year leap_year.c
./leap_year

以上为编译命令示意
用VScode来示例
为了使操作系统能够以标准方法对编译后二进制文件进行处理,类UNIX操作系统通常采用ELF格式(Executable and Linkable Format,可执行可链接文件格式)作为二进制文件的标准格式,ELF文件的执行视图如下:
ELF文件执行视图
ELF头部包含了描述整个ELF文件的基本信息,段头(Program Header)表包含了描述各个段(Segment)的信息,其中Segment是存储程序中数据或代码的逻辑结构。

在ELF(Executable and Linkable Format)中,有以下一些段(segments)是比较重要的:

  1. .text:这个段包含了程序的代码。这是执行程序时首先执行的段。它通常是可执行的,即它包含了那些被操作系统允许执行的指令。.text段通常被分为多个区段(section),包括.text.plt.got等。
  2. .data:这个段包含了初始化的全局变量和静态变量。这些数据在程序开始执行之前被加载到内存中,并被存储在只读和可写的方式。
  3. .rodata:这个段包含的是只读数据,比如常量,字符串字面量等。这些数据在程序开始执行之前被加载到内存,且只能被读取,不能被修改。
  4. .bss:这个段包含了未初始化的全局变量和静态变量。这些数据在程序开始执行之前被加载到内存,并被假定为零或空值。

这些不同的段在ELF文件和程序执行中扮演着重要的角色,它们描述了如何将程序的代码和数据加载到内存中,以及这些数据应该如何被操作系统和程序使用。

示例程序编译后的二进制可执行文件反汇编:

2. 加载阶段:

在加载阶段,操作系统将可执行文件加载到内存中,并准备开始执行。操作系统将分配必要的内存来存储程序的不同部分,例如代码、全局变量和堆栈。此外,操作系统还将设置程序所需的任何其他资源,例如打开文件句柄或分配网络连接。在这个阶段,程序的各种组成部分被放置在内存中适当的位置,并为执行做好准备。

操作系统把ELF文件装入内存,这个过程称为程序的加载。分为两步:1.解析ELF头部,进行程序加载,检查ELF文件格式是否被当前CPU架构支持;2.读取段头表获取每段的信息,加载至内存段分配内存空间。

3. 执行阶段:

程序加载之后,利用ELF找到程序入口。

在执行阶段,计算机开始执行程序。计算机从程序的main函数开始执行,即上述代码中的main()函数。在上述代码中,程序首先定义一个名为isLeapYear的函数,该函数接受一个整数参数year,并返回一个整数值。函数检查年份是否是闰年,如果是,则返回1,否则返回0。接下来,程序在main函数中调用isLeapYear函数,并打印结果。在这个阶段,CPU开始执行程序中的指令,并根据指令执行各种操作,例如读取和写入内存、执行算术运算等。根据上述代码,如果年份是闰年,程序将打印“2024是闰年”,否则将打印“2024不是闰年”。

程序在内存中的布局
对于程序执行过程中,动态申请的内存保存在一个称为堆的内存空间。让操作人员自主申请与及时释放。栈是先入后出的结构,在内存中,通常用低地址向高地址生长。上图,图四,为程序在内存中的布局。
程序栈的内容

程序的并发执行与进程抽象

进程的描述

进程控制块

进程控制块(Process Control Block,PCB)是操作系统用于管理进程的重要数据结构。它包含了关于进程的诸多信息,包括描述信息、控制信息、CPU上下文和资源管理信息。

1. 描述信息

描述信息主要包括以下部分:

  • 进程标识符(PID):用于唯一标识系统中的进程。
  • 进程状态:表示进程在执行过程中的状态,例如就绪、运行、等待或结束。
  • 父进程标识符:对于一个非初始进程,记录其父进程的PID。
  • 进程优先级:表示进程执行的优先级。

2. 控制信息

控制信息主要用于控制和协调进程的执行,包括以下部分:

  • 程序计数器(PC):指向下一条要执行的指令。
  • 栈指针:指向栈的顶部。
  • 中断向量:当发生中断时,指向中断处理程序的地址。
  • 信号掩码:用于屏蔽某些信号,防止它们中断程序的执行。
  • 调度参数:用于进程调度,例如估计运行时间、等待时间和剩余运行时间。

3. CPU上下文

CPU上下文记录了当前进程在CPU上执行所需的所有信息,包括以下部分:

  • 全局寄存器:例如程序计数器、栈指针等。
  • 局部寄存器:例如通用寄存器、状态寄存器等。
  • CPU的标志位:例如中断标志位、陷阱标志位等。
  • 堆栈:用于保存程序运行时的上下文信息。

4. 资源管理信息

资源管理信息用于记录和管理进程所需的资源,包括以下部分:

  • 打开文件表:记录进程打开的所有文件信息。
  • 内存管理信息:例如分页表、段表等,用于进程的内存管理。
  • 权限和安全信息:例如用户ID、组ID、文件权限等。
  • 进程间通信(IPC)信息:例如信号量、消息队列等,用于进程间的通信。
  • 其他资源:例如定时器、线程等。

进程状态

1.就绪状态

当进程已分配到必要的资源,并准备运行时,它处于就绪状态。在这种情况下,进程在等待CPU时间片的分配,一旦分配到时间片,它就可以被调度到CPU上执行。

2.运行状态

当进程正在占用CPU并执行其任务时,它处于运行状态。这是进程进行实际工作的状态。

3.阻塞状态

如果进程需要等待某些条件或资源才能继续执行,例如等待I/O操作完成,它就会进入阻塞状态。在这状态下,进程不会获得CPU时间片,直到它所需的资源或条件得到满足。

4.终止状态

当进程已完成任务或出现错误而不能继续执行时,它就处于终止状态。在这种情况下,进程不再占用CPU时间片,并且它的资源将被释放回系统,供其他进程使用。

进程的控制

进程控制源语

1.创建

创建一个新的进程。这通常由操作系统内核或用户程序发起。新的进程从父进程继承了许多属性,如代码、数据、内存配置、文件描述符等。

2.销毁

结束一个进程。这可以通过操作系统内核或用户程序发起。当一个进程结束时,它的资源(如内存、文件句柄等)会被回收,以便分配给其他进程。

3.阻塞与唤醒

进程在执行过程中可能遇到某种情况,使其无法继续执行,此时进程会进入阻塞状态。例如,当进程等待某个I/O操作完成时,它通常会进入阻塞状态。当阻塞的条件被满足时(例如,I/O操作完成),进程会被唤醒并回到就绪状态。

上述这些操作都是由操作系统提供的系统调用实现的。例如,在Unix和类Unix系统中,"fork()"系统调用用于创建新进程,"kill()"用于销毁进程,"wait()"用于阻塞进程直到其子进程结束。

进程创建

1.PCB的复制

PCB是操作系统用于管理进程的重要数据结构,其中包含了进程的各种信息,如进程标识符、状态、优先级、寄存器上下文等。在进程创建时,操作系统会为新进程创建一个新的PCB,并将父进程的PCB中的一些信息复制到子进程的PCB中,这些信息包括进程状态、优先级、寄存器上下文等。

2.CPU上下文的复制

CPU上下文是指当前进程在CPU上执行所需的各种信息,如寄存器状态、内存映射等。在进程创建时,操作系统会将父进程的CPU上下文复制到子进程的PCB中,以便子进程在CPU上执行时使用。

3.地址空间的复制

在进程创建时,操作系统还会为新进程分配一个独立的地址空间,这个地址空间是只读的,可以保证不同进程之间的数据隔离。父进程的地址空间会被复制到子进程的地址空间中,包括代码、数据、堆、栈等。当然,对于共享内存等特殊情况,操作系统会采取其他措施来管理不同进程之间的数据共享。

程序装载

程序装载是操作系统中一个重要的过程,它涉及到将可执行文件加载到内存中,并在CPU上执行。以下是程序装载的常见步骤:

1.exec函数簇的系列函数接口

在许多编程语言中,如C和C++,可以使用exec函数簇来装载和执行新的程序。这些函数包括exec()、execl()、execv()、execlp()等,它们接受一个或多个参数,指定要执行的新程序的路径和参数列表。调用这些函数后,当前进程的代码和数据将被替换为新程序的代码和数据。

需要注意的是,上述步骤仅适用于传统的静态链接的执行文件。对于动态链接的执行文件(如DLL或.so文件),装载的过程会有所不同,通常需要涉及到动态链接器的帮助。此外,不同的操作系统在具体实现上可能有所不同,但大致的流程是相似的。

2.可执行文件的寻找与打开

当调用exec函数簇时,需要提供要执行的可执行文件的路径。操作系统会解析这个路径,并在文件系统中寻找指定的可执行文件。一旦找到文件,操作系统会打开文件并准备将其加载到内存中。

3.可执行文件的装载

在可执行文件被打开后,操作系统将其从磁盘读入到内存中。这个过程称为“装载”,操作系统会根据可执行文件的二进制格式解析其内容,并将其映射到内存中的适当位置。装载过程涉及到一些底层的操作,如分配内存空间、设置内存保护等。

4.新程序的执行

一旦可执行文件被装载到内存中,操作系统会将CPU的控制权转移到新的程序中。新的程序从其入口点开始执行,入口点通常是程序的main()函数。此时,原来的进程将不复存在,取而代之的是新的程序在内存中的副本。

进程终止

进程终止是指一个正在运行的进程由于某种原因停止执行,结束其运行。在操作系统中,进程终止通常由系统或程序员通过发送终止信号来触发。当一个进程终止时,操作系统会执行一系列操作来清理和回收该进程所使用的资源,并确保该进程对系统的影响最小化。

1.用户资源的回收

在进程终止时,操作系统会回收该进程所使用的用户资源,例如打开的文件、分配的内存、创建的线程等。这些资源的回收可以防止资源泄漏和不必要的资源占用。回收这些资源可以确保其他进程可以使用这些资源,或者系统可以将其重新分配给其他需要的进程。

2.状态信息的发送与僵尸状态的设置

当一个进程终止时,操作系统会将其状态信息发送给父进程或操作系统本身。这些状态信息通常包括进程的PID、退出状态码(表示进程的结束状态)、时间戳等。在发送状态信息后,操作系统会将该进程的状态设置为“僵尸状态”,以表示该进程已经结束,但仍然占用着部分系统资源(例如内存)。

3.内核资源的回收

在进程终止后,操作系统会回收该进程所使用的内核资源,例如系统调用表、进程控制块(PCB)、虚拟内存空间等。这些资源的回收可以确保系统正常运行并防止资源泄漏。回收这些资源后,操作系统可以将这些资源重新分配给其他需要的进程。

4.为所有子进程寻找新父进程

在进程终止时,如果该进程有子进程,操作系统会为这些子进程寻找新的父进程。这是为了确保子进程不会成为孤儿进程,从而导致系统资源的浪费。寻找新父进程的过程通常涉及到操作系统的进程调度器,它会将一个父进程指定给子进程,以确保子进程可以被正确地管理和调度。

在进程终止后,操作系统会将其从进程调度中移除,并将其放入到一个适当的等待队列中,直到其状态被设置为僵尸状态并被彻底清理掉。整个过程是为了确保系统的稳定性和资源的有效利用。

openEuler中的进程树

1. 根进程(Root Process):根进程是整个进程树的起点,也是系统的第一个进程。在openEuler中,根进程的PID(进程ID)为0。
2. 系统进程(System Processes):系统进程是伴随着操作系统启动而生成的进程,它们负责维护操作系统的运行。在openEuler中,系统进程的PID通常以1开头。
3. 用户进程(User Processes):用户进程是由用户执行的程序产生的进程。在openEuler中,用户进程的PID以大于1的整数开头。
4. 子进程(Child Processes):子进程是根进程或系统进程派生出来的进程,它们通常执行一些特定的任务。子进程的PID与父进程的PID相关联。
5.僵尸进程(Zombie Processes):当子进程结束时,其父进程会为其回收资源并将其状态信息发送给内核。这个过程被称为“僵尸化”。僵尸进程已经结束,但仍然占用着部分资源(如内存),直到其父进程将其彻底清理掉。

在openEuler中,可以通过图形界面查看进程树。一种常用的方法是通过systemd工具。

以下是通过systemd工具在图形界面下查看进程树的步骤:

  1. 首先,确保你的系统中安装了systemd工具。如果你不确定是否已安装,可以通过以下命令进行安装:
sudo apt-get update
sudo apt-get install systemd-gui
  1. 安装完毕后,可以通过以下命令打开进程树:
systemctl --no-pager --state=running

这将在图形界面下显示当前正在运行的进程及其之间的关系。你可以通过这个图形界面浏览和查看各个进程的状态、PID等信息。

除了systemd工具外,还可以使用其他一些图形界面工具来查看进程树,如htop、glances等。这些工具通常需要在安装后才能使用,你可以通过包管理器进行安装。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/118161.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CrossOver23.6软件激活码怎么获取 CrossOver软件2023怎么激活

CrossOver一款类虚拟机&#xff0c;它的主要功能是在mac系统中安装windows应用程序。其工作原理是将exe格式的windows应用程序安装包安装至CrossOver容器中&#xff0c;并将运行该exe文件所需的配置文件下载至容器中&#xff0c;便能在mac正常运行windows应用程序了。下面就让我…

如何构建一个外卖微信小程序

随着外卖行业的不断发展&#xff0c;越来越多的商家开始关注外卖微信小程序的开发。微信小程序具有使用方便、快速上线、用户覆盖广等优势&#xff0c;成为了商家们的首选。 那么&#xff0c;如何快速开发一个外卖微信小程序呢&#xff1f;下面就让我们来看看吧&#xff01; 首…

【C++入门:C++世界的奇幻之旅】

1. 什么是C 2. C发展史 3. C的重要性 4. C关键字 5. 命名空间 6. C输入&输出 7. 缺省参数 8. 函数重载 9. 引用 10. 内联函数 11. auto关键字(C11) 12. 基于范围的for循环(C11) 13. 指针空值---nullptr(C11)05. 1. 什么是C C语言是结构化和模块化的语言&…

什么是web3.0?

Web 3.0&#xff0c;也常被称为下一代互联网&#xff0c;代表着互联网的下一个重大演变。尽管关于Web 3.0的确切定义尚无共识&#xff0c;但它通常被认为是一种更分散、更开放且更智能的互联网。 以下是Web 3.0的一些主要特征和概念&#xff1a; 1. 去中心化 Web 3.0旨在减少…

人工智能:CNN(卷积神经网络)、RNN(循环神经网络)、DNN(深度神经网络)的知识梳理

卷积神经网络&#xff08;CNN&#xff09; 卷积神经网络&#xff08;CNN&#xff09;&#xff0c;也被称为ConvNets或Convolutional Neural Networks&#xff0c;是一种深度学习神经网络架构&#xff0c;主要用于处理和分析具有网格状结构的数据&#xff0c;特别是图像和视频数…

CSS中 通过自定义属性(变量)动态修改元素样式(以 el-input 为例)

传送门&#xff1a;CSS中 自定义属性&#xff08;变量&#xff09;详解 1. 需求及解决方案 需求&#xff1a;通常我们动态修改 div 元素的样式&#xff0c;使用 :style 和 :class 即可&#xff1b;但想要动态修改 如&#xff1a;Element-ui 中输入框&#xff08;input&#x…

Windows与Linux服务器互传文件

使用winscp实现图形化拖动的方式互传文件. 1.下载winscp软件并安装&#xff0c;官方地址&#xff1a; https://winscp.net/eng/index.php 2.打开软件&#xff1a; 文件协议选择scp&#xff0c;输入linux服务器的IP和端口号&#xff0c;然后输入你的用户名和密码就可以登陆了。…

postman打开后,以前的接口记录不在,问题解决

要不这些文件保存在C:\Users\{用户名}\AppData\Roaming\Postman 比如&#xff0c;你目前使用的window登录用户是abc&#xff0c;那么地址便是C:\Users\abc\AppData\Roaming\Postman 打开后&#xff0c;这个目录下会有一些命名为backup-yyyy-MM-ddThh-mm-ss.SSSZ.json类似的文…

渗透攻击漏洞——原型链污染

背景 2019年初&#xff0c;Snyk的安全研究人员披露了流行的JavaScript库Lodash中一个严重漏洞的详细信息&#xff0c;该漏洞使黑客能够攻击多个Web应用程序&#xff0c;这个安全漏洞就是一个“原型污染漏洞”&#xff08;JavaScript Prototype Pollution&#xff09;&#xff…

【分布式】大模型分布式训练入门与实践 - 04

大模型分布式训练 数据并行-Distributed Data Parallel1.1 背景1.2 PyTorch DDP1&#xff09; DDP训练流程2&#xff09;DistributedSampler3&#xff09;DataLoader: Parallelizing data loading4&#xff09;Data-parallel&#xff08;DP&#xff09;5&#xff09;DDP原理解析…

图论06-【无权无向】-图的遍历并查集Union Find-力扣695为例

文章目录 1. 代码仓库2. 思路2.1 UF变量设计2.2 UF合并两个集合2.3 查找当前顶点的父节点 find(element) 3. 完整代码 1. 代码仓库 https://github.com/Chufeng-Jiang/Graph-Theory 2. 思路 2.1 UF变量设计 parent数组保存着每个节点所指向的父节点的索引&#xff0c;初始值为…

Java IDEA controller导出CSV,excel

Java IDEA controller导出CSV&#xff0c;excel 导出excel/csv&#xff0c;亲测可共用一个方法&#xff0c;代码逻辑里判断设置不同的表头及contentType&#xff1b;导出excel导出csv 优化&#xff1a;有数据时才可以导出参考 导出excel/csv&#xff0c;亲测可共用一个方法&…

【多线程】Java如何实现多线程?如何保证线程安全?如何自定义线程池?

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ 多线程 Java多线程1. 进程与线程2. 多线程1&am…

人工智能基础_机器学习001_线性回归_多元线性回归_最优解_基本概念_有监督机器学习_jupyter notebook---人工智能工作笔记0040

线性和回归,就是自然规律,比如人类是身高趋于某个值的概率最大,回归就是通过数学方法找到事物的规律. 机器学习作用: 该专业实际应用于机器视觉、指纹识别、人脸识别、视网膜识别、虹膜识别、掌纹识别、专家系统、自动规划、智能搜索、定理证明、博弈、自动程序设计、智能控制…

【PyTorch】深度学习实践 01 Overview

人工智能概述 课程前置知识 线性代数 概率论 &#xff08;不要有路径依赖&#xff0c;遇到不会的就现学&#xff09;Python基础 人工智能 问题分类 人工智能&#xff0c;实际上就是利用计算机来代替人脑进行智能工作&#xff0c;计算机所要实现的智能可以分为两大部分&am…

python造测试数据存到excel

代码&#xff1a; from ExcelHandler import ExcelHandler from faker import Faker # 导入faker库的Faker方法 # ↓默认为en_US&#xff0c;只有使用了相关语言才能生成相对应的随机数据 fkFaker(locale"zh_CN")def create_date():m int(input(请输入要造的数据条…

PostgreSQL12中浮点数输出算法优化带来的小问题

最近碰到同事发来这样两个SQL&#xff0c;开发反馈输出的结果异常。 bill# select 0.1284*100::float;?column? --------------------12.839999999999998 (1 row)bill# select (0.1284*100)::float;float8 --------12.84 (1 row) 乍一看其实能看出明显的区别&#xff0c;由于…

通俗介绍:什么是 Redis ?

刚接触 Redis 的伙伴们可能会因为不熟悉而感到困惑。本文简述 Redis 是什么、有哪些作用的问题&#xff0c;是一篇短浅而入门级别的文章。 Redis官网&#xff1a;Redis 打开 Redis 官网可以看到&#xff0c;官方对 Redis 的介绍是这样的&#xff1a;The open source, in-memo…

pytorch C++ 移植

文章目录 前言安装 libtorch安装 opencv&#xff08;C&#xff09;模型转换通过跟踪转换为 Torch Script通过注解转换为 Torch Script 编写 C 代码编译环境搭建C 库管理方法一&#xff1a;手动配置 visual studio 环境方法二&#xff1a;cmake 配置环境 python 调用 C 程序 前言…