系统编程1(进程的概念与原理)

进程的概念与原理

计算机组成部分一般遵循冯诺依曼结构,也就是由控制器、运算器、存储器、输入设备、输出设备五个部分组成。

在这里插入图片描述
⦁ 程序的编译

一般在编写出程序之后,并不能直接运行,而是需要把程序通过编译器进行编译,生成可执行文件才能运行。而对于嵌入式学习,一般都是在Linux系统下使用GCC编译器对程序进行编译。
在这里插入图片描述
GCC编译器是Linux系统默认的C/C++编译器,大部分Linux发行版本中都是默认安装的。GCC编译器主要以Linux命令的形式在shell终端中使用,所以需要大家掌握关于GCC编译器的相关参数。
在这里插入图片描述
在这里插入图片描述
C语言程序编译过程:源程序 ---- 预处理 — 编译 — 汇编 — 链接 — 可执行文件

预处理:
对源码进行简单的加工,GCC编译器会调用预处理器cpp对程序进行预处理,其实就是解释源程序中所有的预处理指令,如#include(文件包含)、#define(宏定义)、#if(条件编译)等以#号开头的预处理语句。

这些预处理指令将会在预处理阶段被解释掉,如会把被包含的文件拷贝进来,覆盖掉原来的#include语句,把所有的宏定义展开,所有的条件编译语句被执行,GCC还会把所有的注释删掉,添加必要的调试信息。

预处理指令: gcc -E xxx.c -o xxx.i 会生成预处理文件 xxx.i

编译:
就是对经过预处理之后的.i文件进行进一步翻译,也就是对语法、词法的分析,最终生成对应硬件平台的汇编文件,具体生成什么平台的汇编文件取决于编译器,比如X86平台使用gcc编译器,而ARM平台使用交叉编译工具arm-linux-gcc。

编译指令:gcc -S xxx.i -o xxx.s 会生成对应汇编文件 xxx.s

汇编:
GCC编译器会调用汇编器as将汇编文件翻译成可重定位文件,其实就是把.s文件的汇编代码翻译为相应的指令。

编译指令:gcc -c xxx.s -o xxx.o 会生成汇编后的文件 xxx.o

链接:
经过汇编步骤后生成的.o文件其实是ELF格式的可重定位文件,虽然已经生成了指令流,但是需要重定位函数地址等,所以需要链接系统提供的标准C库和其他的gcc基本库文件等,并且还要把其他的.o文件一起进行链接。-lc -lgcc 是默认的,可以省略

编译指令:gcc hello.o -o hello -lc -lgcc 会得到可执行文件 xxx // l是lib的缩写

⦁ 程序的格式

一般对源文件进行编译和汇编之后,就会得到对应的目标文件xxx.o,目标文件也被称为可重定位文件,就是指还未完成链接的中间文件,用户可以把这些目标文件制作成在Linux系统下使用的静态库libxxx.a或者动态库libxxx.so。

其实目标文件和可执行文件的内容和结构非常相似,所以Linux系统下把目标文件xxx.o和可执行文件都称为ELF文件,ELF指的是Executable Linkable Format的缩写,中文翻译为可执行可链接格式。

注意:可以在linux系统中利用查看文件格式的指令: file 查阅目标文件和可执行文件的区别:

在这里插入图片描述
思考:还未完成链接的目标文件中存储了哪些内容,以及如何查看目标文件中的内容信息???

回答:目标文件中的内容至少有编译后的机器指令代码、数据。除了这些内容以外,目标文件中还包括了链接时所需要的一些信息,比如符号表、调试信息、字符串等。一般目标文件将这些信息按不同的属性,以“节”(Section)的形式存储,有时候也叫“段”(Segment),一般情况下,它们都表示一个一定长度的区域,基本上不加以区别。

程序源代码编译后的机器指令经常被放在代码段(Code Section)里,代码段常见的名字有“.code”或“.text”。全局变量和局部静态变量数据经常放在数据段(Data Section),数据段一般名字都叫“.data”。

注意:linux系统的GCC编译套件有一款工具叫做objdump,可以查看目标文件内部的数据!
在这里插入图片描述
数据段中有一个叫做.bss段, bss以前其实是汇编伪指令,作用是为某些数据预留一块空间,bss其实是Block Started by Symbol,也就是用于存储未被初始化的全局变量和静态局部变量,但是在程序编译阶段是没有分配空间的,在程序运行时会得到空间。

在这里插入图片描述
在这里插入图片描述
另外,objdump工具也可以实现把可执行文件进行反汇编,可以把得到的反汇编代码重定向到某个文本中进行查看 “objdump -D demo > > xxx.txt”

⦁ 进程的概念

当源文件编译通过并且完成链接动作之后,则得到一个可以执行的ELF文件,ELF文件中包含了程序的指令和数据以及相关函数接口的跳转地址等信息,当用户运行程序时,操作系统就会把程序相关的指令和数据载入内存,并为程序分配对应的内存空间,然后通知CPU完成程序的相关动作。

用户编写的源文件是存储在外存(磁盘)中的,而使用编译器生成的ELF可执行文件也是存储在外存中的,这两者都是静态的,操作系统也并没有为两者分配系统资源。

在这里插入图片描述
当可执行文件得到运行,操作系统才会把可执行文件中的指令和数据从外存中读取出来并写入内存,并且会为程序分配系统资源(内存空间、CPU使用权等),所以程序从静态变为动态,这种正在进行中的程序,操作系统就把其称之为进程(process)。也可以理解为进程是程序在处理器上的一次执行过程。

进程定义:进程是一个具有一定独立功能的程序在一个数据集合上依次动态执行的过程。进程是一个正在执行程序的实例。

注意:进程是操作系统分配资源的基本单位!操作系统是以进程为单位来分配系统资源的,比如内存空间、CPU使用权等。 线程是操作系统调度资源的最小单位! 进程包含线程!

⦁ 进程的特征

进程具有四个基本特征,分别是动态性、并发性、独立性、异步性,具体的区别如下所示:

(1) 动态性:进程是程序在处理器上的一次执行过程,因而是动态的。比如进程会在程序运行时被创建出来,当无法获取足够的系统资源时进程会暂停,当得到资源后会继续执行。

(2) 并发性:多个进程同时存在于内存中,目的是与其他程序并发执行,提高资源的利用率。

(3) 独立性:进程是一个能独立运行的基本单位,也是系统进行资源分配和调度的独立单位。

(4) 异步性:指的是进程以各自独立的、不可预知的速度向前推进。一个进程的执行过程可能是无法被预测的,因为会受到各方面因素的影响,比如当系统资源不够时或者出现其他进程抢占资源时,都会影响进程的执行进度。

⦁ 进程的组成

思考:操作系统中可能会有n个进程同时执行,请问操作系统如何掌握这些进程的执行情况?

回答:一般进程在创建之后,操作系统都会为进程分配一块内存来记录进程的各项参数信息,所以这块内存被称为进程控制块(Processing Control Block,缩写为PCB)。每个进程都有PCB,用于标识进程的存在以及记录进程的信息。

在Linux系统中进程控制块PCB是以一个名称叫做struct task_struct的结构体作为载体来存储信息的,该结构体被定义在一个名称叫做sched.h的头文件中。

在这里插入图片描述
进程一般由三个部分组成,分别是进程控制块、代码段、数据段。代码段指的是进程中能被调度程序调度到CPU上执行的程序代码段,数据段指的是进程对应的程序原始数据或者程序执行过程中产生的中间数据等。

不同操作系统对于一个进程的信息记录是不同的,也就是PCB中的内容会有一些区别,但是大同小异,基本都会包含以下内容:

  1. 进程标识符

每个进程都有一个有系统分配的唯一的PID进程标识符(process identifier),用于区分系统中的其他进程,这个PID也是Linux内核提供给用户访问进程的一个接口,用户可以通过PID控制进程。

比如Windows系统可以通过任务管理器了解系统中正在执行的进程的数量以及进程的状态:

在这里插入图片描述
思考:windows系统下可以通过任务管理器查看进程的PID,那Linux系统如何查看进程PID?

回答:Linux系统中提供了关于获取进程状态的shell命令:ps ,该命令的使用方法详见man手册,一般使用 ps -ef 或者 ps -aux来查看Linux系统中所有用户相关的进程的所有信息。

在这里插入图片描述
2) 进程当前状态

在进程的运行过程中由于系统中多个进程的并发运行和相互制约的结果,所以使进程的状态不断发生变化。操作系统以进程的状态来作为调度程序分配处理器的依据。

通常一个运行中的进程至少可划分为5种基本状态:就绪态、运行态、阻塞态、创建态、结束态。当然进程状态的叫法是比较灵活的,大家不用死记硬背,重在理解相关概念。

A. 创建态

指的是进程正在被创建,但是还没有准备好,也就是还没有达到就绪状态,此时系统申请进程PCB需要的内存空间,并向PCB中填写关于进程的管理信息,然后系统分配进程运行需要的资源,最后把进程转换为就绪状态。

B. 就绪态

指的是进程已经获得了除了处理器之外的其他资源,相当于“万事俱备,只欠东风”,只要进程获得处理器资源,就可以立即执行。

C.执行态

执行态也被称为运行态,指的是进程已经获得了其他资源和处理器资源,并正在被CPU执行的状态。

D.阻塞态

阻塞态也被称为暂停态,指的是进程在执行过程中由于某个事件导致无法继续执行下去,此时进程处于暂时停止的状态。

E. 结束态

指的是进程正在从系统中消失,原因可能是进程正常退出或者由于其他问题中断退出运行。有一种情况比较特殊,就是如果该进程退出之后资源还没有释放,但是此时进程已经无法被调度和运行,进程就会进入僵尸态,此时用户需要对这类进程进行处理,避免占用过多资源。

在这里插入图片描述
思考:Linux系统下运行了n个进程,每个进程的状态都不同,请问如何区分进程的状态???

回答:在Linux系统的终端中输入shell指令: ps -aux,就可以看到当前系统中运行的进程状态。

在这里插入图片描述
注意:进程不是一直处于某一个状态,进程的状态会受到外界因素和执行进度的影响而发生改变,当然,进程的状态在某一个时刻是唯一的,也就是在某一时刻进程必须且只能处于一种状态。

⦁ 进程的控制

进程控制指的是对系统中的所有进程实施有效的管理,其功能一般包括进程的创建、进程的撤销、进程的阻塞与唤醒等。这些功能一般是由操作系统的内核来实现的。

  1. 进程的创建

Linux系统中的一个进程中可以创建若干个新进程,新创建的进程中又可以创建子进程,所以一般使用进程前趋图来描述创建的进程之间的关系。进程前趋图也被称为进程树,是为了描述进程家族关系的树。

在这里插入图片描述
比如在进程A中创建了一个新进程B,则进程B就是进程A的子进程,进程A就是进程B的父进程。

如果在进程A中创建了2个子进程B和C,进程B中创建了2个子进程D和E,进程C中创建了1个子进程F,则进程A就是该进程家族的祖先。

在Linux系统中运行的所有进程也可以构成一个进程树,并且该进程树也有一个祖先,用户可以通过Linux系统提供的shell命令:pstree 来打印进程关系。
在这里插入图片描述
可以发现,Linux系统中的所有进程都和一个进程有关系,那就是systemd进程,该进程是Linux系统运行的第一个进程,英文全称是system daemon,中文翻译为系统守护进程,系统中其他进程都是该进程的子进程。

守护进程也被翻译为精灵进程或者后台进程,是一种旨在运行于相对干净环境、不受终端影响的、常驻内存的进程,就像神话中的精灵拥有不死的特性,长期稳定提供某种功能或服务。

systemd其实是一个 Linux 系统基础组件的集合,它提供了一个系统和服务管理器,然后运行为 PID 1的进程,负责在系统启动或运行时激活系统资源,并且管理服务器进程和其它进程。
在这里插入图片描述
注意:Linux系统中只有进程才可以在系统运行,所以一个程序想要运行,就必须为该程序创建进程。linux内核提供了一个名字叫做fork()的系统调用接口,该接口可以在进程中创建一个子进程。
在这里插入图片描述
在这里插入图片描述
可以看到fork函数的返回值对于父进程和子进程而言是不同的,fork函数在父进程中返回的是创建成功的子进程的PID,fork函数在子进程中的返回值是0,当然,如果子进程失败则返回-1。

思考:由于子进程会拷贝父进程的代码段和数据段,所以父进程剩余的程序会执行两遍,请问如何区分到底是哪个进程在执行程序?是否父进程的程序会优先于子进程执行?

回答:通过fork函数的返回值来区分父进程和子进程,父进程和子进程的执行顺序是由操作系统的调度器决定的。也可以选择利用某些机制来调整执行顺序。

在这里插入图片描述
获取当前进程PID的函数接口getpid(),获取当前进程的父进程PID的函数接口是getppid()
在这里插入图片描述
思考:调用fork函数之后可以创建一个子进程,但是调用了一次fork函数为什么会有两个不同的返回值?

回答:就是调用fork的时候子进程已经拷贝了父进程的代码段、数据段、堆栈段,所以fork函数还没有执行完成,就会在两个进程空间继续执行,就会得到两个不同的返回值。

  1. 进程的撤销

一个进程在完成自身任务之后应该及时撤销,这样就可以及时的释放进程的资源,此时可以分为两种情况:一种是撤销指定进程,另一种是撤销指定进程以及该进程的所有子孙进程。不管是哪种情况,都应该及时回收进程占用的资源。

Linux系统中提供了一个名称叫做wait()的系统调用接口,该接口用于让父进程等待子进程的状态改变并获取已经改变状态的子进程的信息。

在这里插入图片描述
僵尸态指的是进程终止但是并未释放相关资源的一种状态,此时由系统内核对处于僵尸态的进程进行维护,处于僵尸态的进程会占用创建进程的资源和数量,如果僵尸态进程数量太多,则会导致系统无法创建新进程。

所以父进程应该及时的对终止的子进程进行等待,这样就可以回收子进程占用的资源,当然,如果父进程终止,则处于僵尸态的子进程会由系统内核完成资源的回收。

注意:如果当前进程没有子进程,则wait函数立即返回,如果当前进程有很多个子进程则wait函数会回收第一个变为僵尸态的子进程资源。

wait函数的参数是一个指针,用于记录子进程的退出状态,如果该参数为NULL,则表示当前进程放弃子进程的退出状态。对于该指针中记录的值,用户可以通过系统提供的宏定义来分析子进程的退出状态。

在这里插入图片描述
通过man手册可以发现Linux内核还提供了另一个叫做waitpid()的系统调用函数,该函数也可以等待子进程状态改变并回收子进程的系统资源,只不过该函数的针对性更强,可以指定回收某个子进程的系统资源。
在这里插入图片描述
在这里插入图片描述
3) 进程的执行

思考:既然在一个进程中可以创建多个子进程,并且子进程和父进程的数据段和代码段是相同的,也就是一份程序会执行两次,一般情况下是没有意义和必要的,请问能否让子进程单独的加载新的程序的代码段和数据段,如果可以,应该如何实现?

回答:当然是可以的,Linux系统标准库中提供了一组函数接口来实现在进程中加载和执行指定的程序。

在这里插入图片描述
这组接口可以把exec作为前缀,然后以exec后面的字符进行分类,比如l指的是list的缩写,p指的是path的缩写,e指的是environment的缩写,v指的是vector的缩写。

(1) l : 以列表的方式来组织指定程序的参数
(2) v: 以数组的方式来组织指定程序的参数
(3) e: 执行指定程序前顺便设置环境变量
(4) p: 执行程序时可自动搜索环境变量PATH的路径
在这里插入图片描述
以 execl(const char *pathname, const char *arg, …) 为例,参数pathname是需要加载的指定程序,而arg则是该程序运行时的命令行参数,命令行参数包括程序名本身,并且全部是字符串,其实和带参数的main函数通过命令行传参的流程类似,但是函数的参数列表必须以NULL结束,也就是函数的最后一个参数填NULL即可。

其实,linux系统还提供一个函数,名称叫做system(),这个函数也可以让新进程执行shell命令。
在这里插入图片描述

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

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

相关文章

《Vue Router实战教程》5.嵌套路由

欢迎观看《Vue Router 实战(第4版)》视频课程 嵌套路由 一些应用程序的 UI 由多层嵌套的组件组成。在这种情况下,URL 的片段通常对应于特定的嵌套组件结构,例如: 通过 Vue Router,你可以使用嵌套路由配置…

使用Python解决Logistic方程

引言 在数学和计算机科学中,Logistic 方程是描述人口增长、传播过程等现象的一种常见模型。它通常用于表示一种有限资源下的增长过程,比如动物种群、疾病传播等。本文将带领大家通过 Python 实现 Logistic 方程的求解,帮助你更好地理解这一经典数学模型。 1.什么是 Logist…

《从零搭建Vue3项目实战》(AI辅助搭建Vue3+ElemntPlus后台管理项目)零基础入门系列第十二篇(完结篇):数据统计功能实现

🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 《从零搭建Vue3项目实战》(AI辅助…

研究嵌入式软件架构时遇到的初始化堆栈溢出问题

文章目录 2025年4月10日新增分析PC寄存器指针值排查问题map文件设计到的知识点1. **.bss 段(Block Started by Symbol)**2. **.data 段**3. **.text 段**4. **.heap 段**5. **.stack 段**6. **.rodata 段(只读数据段)**7. **.init…

软件架构评估两大法:ATAM 和 SAAM 的对比与实践

架构权衡分析方法(ATAM)和软件架构分析方法(SAAM)是软件架构评估领域中非常重要的两种方法,以下为你详细介绍: 一、架构权衡分析方法(ATAM) 1.背景与起源:ATAM 是由卡耐…

Python爬虫-爬取全球股市涨跌幅和涨跌额数据

前言 本文是该专栏的第52篇,后面会持续分享python爬虫干货知识,记得关注。 本文中,笔者将基于Python爬虫,实现批量采集全球股市行情(亚洲,美洲,欧非,其他等)的各股市“涨跌幅”以及“涨跌额”数据。 具体实现思路和详细逻辑,笔者将在正文结合完整代码进行详细介绍。…

电流互感器的两相星形接线的建模与仿真

微♥“电击小子程高兴的MATLAB小屋”获取巨额优惠 1.模型简介 本仿真模型基于MATLAB/Simulink(版本MATLAB 2016Rb)软件。建议采用matlab2016 Rb及以上版本打开。(若需要其他版本可联系代为转换) 2.仿真模型 3.仿真结果 3.1一次…

详解 kotlin 相对 Java 特有的关键字及使用

文章目录 1. val 和 var2. fun3. when4. is 和 !is5. lateinit6. by7. reified8. companion 本文首发地址:https://h89.cn/archives/366.html 最新更新地址:https://gitee.com/chenjim/chenjimblog Kotlin 在兼容Java的基础上,引入了许多特有…

国标GB28181视频平台EasyCVR如何搭建汽车修理厂远程视频网络监控方案

一、背景分析 近年我国汽车保有量持续攀升,与之相伴的汽车保养维修需求也逐渐提高。随着社会经济的发展,消费者对汽车维修服务质量的要求越来越高,这使得汽车维修店的安全防范与人员管理问题面临着巨大挑战。 多数汽车维修店分布分散&#…

linux RCU技术

RCU(Read-Copy-Update)是Linux内核中的一种同步机制,用于在多核处理器环境中实现无锁读取和延迟更新。Linux RCU(Read-Copy-Update)技术通过一种高效的同步机制来处理并发冲突,确保在多核环境中读者和写者对…

【笔记ing】AI大模型-02开发环境搭建

按实验需求合理选用实例规格,一般:模型开发阶段:使用最低算力2U8GB CPU。训练或推理阶段:切换至GPU规格,用完及时关闭算力环境,且切回最低算力规格。 每次实验结束手动关闭实例。使用ModelArts公有云资源。…

Python——numpy测试题目

题目: 生成一个2行3列随机整数二维数组a使用Numpy方法对(1)中数组a进行整体求积使用Numpy方法对(1)中数组a进行求每列最大值索引定义一个NumPy一维数组 b,元素为 1 到 10 的整数获取(4&#x…

系分论文《论面向服务开发方法在设备租赁行业的应用》

系统分析师论文系列 【摘要】 2022年5月,我司承接某工程机械租赁企业"智能租赁运营管理平台"建设项目,我作为系统分析师主导系统架构设计。该项目需整合8大类2000余台设备资产,覆盖全国15个区域运营中心与300家代理商,实…

Unity UI中的Pixels Per Unit

Pixels Per Unit在图片导入到Unity的时候,将图片格式设置为Sprite的情况下会出现,其意思是精灵中的多少像素对应世界中的一个单位,默认是100 1. 对于在世界坐标中 在世界坐标中,一般对于Sprite的应用是Sprite Renderer组件 使…

Boost Graph Library (BGL) 介绍与使用示例

Boost Graph Library (BGL) 介绍与使用示例 Boost Graph Library (BGL) 是 Boost 库中用于图论计算的模块,提供了处理图数据结构的通用接口和多种图算法实现。 BGL 主要特性 提供多种图表示方式:邻接表、邻接矩阵等包含常用图算法:DFS、BF…

opencv(C++)操作图像像素

文章目录 添加噪点的案例图像像素值1、访问图像属性2、像素访问方法 at灰度图像彩色图像 3、OpenCV 的向量类型4、 图像传递方式 The cv::Mat_ 类1、作用及优点2、使用 cv::Mat_ 简化像素访问 用指针扫描图像背景算法案例原理1. 图像数据存储的基本结构2、行填充(Pa…

Python实现贪吃蛇一

贪吃蛇是一款经典的小游戏,最近尝试用Python实现它。先做一个基础版本实现以下目标: 1、做一个按钮,控制游戏开始 2、按Q键退出游戏 3、右上角显示一个记分牌 4、随机生成一个食物,蛇吃到食物后长度加一,得10分 5、蛇碰…

《AI大模型应知应会100篇》第13篇:大模型评测标准:如何判断一个模型的优劣

第13篇:大模型评测标准:如何判断一个模型的优劣 摘要 近年来,大语言模型(LLMs)在自然语言处理、代码生成、多模态任务等领域取得了显著进展。然而,随着模型数量和规模的增长,如何科学评估这些模…

工会考试重点内容有哪些:核心考点与备考指南

工会考试重点内容总结:核心考点与备考指南 工会考试主要考察考生对工会法律法规、职能职责、实务操作等内容的掌握程度,适用于企事业单位工会干部、社会化工会工作者等岗位的选拔。本文梳理工会考试的核心考点,帮助考生高效备考。 一、工会…

Verilog学习-1.模块的结构

module aoi(a,b,c,d,f);/*模块名为aoi,端口列表a、b、c、d、f*/ input a,b,c,d;/*模块的输入端口为a,b,c,d*/ output f;;/*模块的输出端口为f*/ wire a,b,c,d,f;/*定义信号的数据类型*/ assign f~((a&b)|(~(c&d)));/*逻辑功能描述*/ endmoduleveirlog hdl 程…