第三部分:2---进程理解/Linux下进程初识

news2024/9/21 4:37:23

目录

操作系统如何管理进程?

进程的结构体:

操作系统如何加载进程?

CPU如何调度进程?

进程如何在多个队列排队:

offsetof宏:

进程标识符:

程序打印自己的pid和ppid:

杀死进程:

———————————————

getpid()和getppid()如何得到当前进程的pid/ppid:

父进程和子进程的关系:

动态进程目录:

当前目录是什么?

———————————————

fork创建进程:

创建子进程的目的?

创建子进程后一般写法思路:

fork之后,干了什么事情?

fork之后父子进程谁先运行?

fork之后,为什么会return两个返回值?

代码共享,数据独立:

———————————————

进程状态通俗理解:

运行状态 / 运行队列:

阻塞状态 / 资源的等待队列:

阻塞挂起状态:

swap分区:

———————————————

Linux下,进程的运行状态:

运行状态:

前台进程 / 后台进程:

休眠状态:

暂停状态 / 18和19信号:

僵尸状态:

父进程不存在僵尸状态:

孤儿进程和进程领养:

———————————————

排队的本质——确认优先级:

进程优先级的本质:

通过NI值修正进程优先级值PRI:

限定优先级在一定范围的原因:

进程的并行和并发:

进程切换和上下文保存:


操作系统如何管理进程?

进程是由操作系统创建的->操作系统是由C语言写的->进程需要被C语言写的操作系统管理->C语言通过结构体管理数据->进程相当于一个个结构体->结构体中的成员是进程的一个个属性。

进程的结构体:

进程的结构体被称为“进程的PCB”,当进程被创建PCB就会被创建。Linux下PCB叫做task_struct。

操作系统如何加载进程?

  • 操作系统先将可执行程序从磁盘加载到内存中。

  • 操作系统为加载的进程创建PCB,用于管理进程信息。

  • 将新创建的PCB链接到PCB链表上(Process Table)。

CPU如何调度进程?

  • CPU通过调度算法(轮转调度、优先级调度等),找到下一个需要运行的进程==找到进程的PCB。

  • 操作系统保存当前运行中的进程的上下文(寄存器、程序计数器等状态信息) 。

  • 操作系统加载新进程的上下文,将其寄存器、程序计数器等信息加载到 CPU 中。

  • CPU开始执行新进程的指令。

进程如何在多个队列排队:

  • 进程排队排的是进程PCB。

  • PCB之间的链接属于双向链表。

  • 一般情况下,双向链表存储两个指针,一个指向前前一个节点,一个指向后一个节点。

  • PCB中特定存储一个结构体dlist存放这两个指针。

  • 当进程被排到某个队列中,就创建一个这种结构体,存放该PCB在当前队列的前后指针。

  • 这样PCB每被排序到一个队列,就创建一个dlist,就能实现PCB多队列排队。

offsetof宏:

  • offsetof 宏的定义通常依赖于 __builtin_offsetof 或者通过指针运算来实现。

  • 其原理是,通过计算某个结构体成员的地址减去结构体首地址,得到成员相对于结构体开头的偏移量。

进程标识符:

  • 操作系统中进程标识符pid(process id)会唯一标识一个进程。

  • pid在进程创建时被分配,是唯一的。当进程被释放,pid会被回收给其他新进程使用。

ps ajx | grep my_program
a: 显示所有终端的进程,包括其他用户的进程。
j: 以作业格式显示,包含会话、进程组等信息。
x: 显示没有控制终端的进程,例如守护进程。
grep 命令过滤指定名称的进程

  • 每条命令都可以当作是一个进程,当调用grep过滤指定名称的进程时。他也会作为一个进程运行。

ps ajx | grep my_program | grep -v grep
//加上grep -v grep来过滤grep自身的进程。
//grep过滤器,在过滤某个关键字时,如果关键字不包含特殊符号可以不加双引号,如果包含特殊符号就需要加上双引号确保能够正确解析字符串。比如mycode可以不加双引号,my code就需要加上双引号。

程序打印自己的pid和ppid:

#include <stdio.h>
#include <sys/types.h>//调用getpid要包含这两个库
#include <unistd.h>

int main()
{
	pid_t pid=getpid();//调用失败返回0
	pid_t ppid=getppid();
	printf("%d",pid);
}

杀死进程:

kill -9 pid 
//发送9信号,杀死pid进程

———————————————

getpid()和getppid()如何得到当前进程的pid/ppid:

  • pid和ppid存放在进程的PCB中,当要得到他时需要访问PCB。

  • 操作系统不希望用户直接访问PCB。

  • 于是提供了“系统调用接口”,getpid和getppid得到PCB中的pid和ppid后,返回给用户。

父进程和子进程的关系:

  • 子进程是由父进程创建的,创建时:子进程会以父进程为模板,继承父进程的部分数据和状态。

动态进程目录:

  • 在Linux的根目录下有一个proc目录,其中动态维护当前存货的进程信息。

ls /proc 

  • 其中的子目录是当前存在的进程,子目录以进程pid命名。

ls /proc/pid -l//查看子目录中的文件 

  • 其中每个进程的目录中,有一条:exe->path,他会指向进程在磁盘中可执行程序的路径。

  • 有一条:cwd->path,指向当前目录。

当前目录是什么?

  • 当进程被创建,PCB会记录可执行程序当前的路径,存放在cwd中。

  • 之后对当前进程的路径操作,如果不写为绝对路径,默认使用cwd路径作为相对路径。

chdir("PATH");
//在可执行程序中更改当前目录,更改后进程的PCB中的cwd也会同时修改为PATH。 

  • 每个进程都有当前目录==工作目录。

———————————————

fork创建进程:

pid_t fork(void)//创建进程 

  • 使用fork创建一个子进程,fork之后的代码会被父进程和子进程同时执行。

  • 进程A创建了一个子进程B,子进程的父进程是进程A。

  • fork失败返回-1,创建成功给父进程返回子进程的pid,给子进程返回0。

创建子进程的目的?

  • 让子进程协助父进程完成单进程无法完成的工作。

  • 让子进程和父进程分别完成一项工作。

  • 基于fork的返回值对于父子进程有区别,通过分支让父子进程执行不同的代码段。

创建子进程后一般写法思路:

pid_t id=fork();
if(id<0) return 1;//说明fork失败
else if(id==0) {}//对子进程返回0,这里写子进程的执行逻辑
else {} //写父进程的执行逻辑

 

fork之后,干了什么事情?

  • fork创建子进程之后,系统中会多一个PCB,就是子进程的PCB。

  • 由于fork创建的子进程是直接在系统创建,所以这个进程没有自己的可执行程序。

  • 所以子进程需要共享父进程加载到内存的可执行程序==共享代码和数据。

fork之后父子进程谁先运行?

  • 进程创建后,在调度序列中被排序。

  • 由调度器算法和PCB中的调度信息共同决定当前调度的进程。

fork之后,为什么会return两个返回值?

  • fork先找到父进程PCB,根据父进程PCB初始化子进程的PCB。

  • 让子进程的PCB指向父进程的可执行程序。

  • 将子进程PCB放到调度队列。

  • fork之后的代码是父子进程之间共享的,包括return。

  • 当return时,父进程调度完成return一次,子进程调度完成return一次。返回两次也就是两个值。

代码共享,数据独立:

  • 父子进程,共用同一份代码。

  • 数据相互独立,子进程在用到某个成员时,从父进程的数据写时拷贝一份到自己的数据中。

———————————————

进程状态通俗理解:

  • 进程状态就是进程PCB中的一个变量的值,这个值来自于一个枚举类型。

  • 当变量的值对应枚举类型不同的成员时,代表进程处在对应的状态。

  • 状态的变化,就是修改变量的值为对应枚举类型的成员。

运行状态 / 运行队列:

  • 每个CPU都会维护一个运行队列。

  • 进程创建PCB,并且被排序到运行队列中,他所处在的状态就是运行状态。

  • 具体实现就是:进程中控制进程状态的变量被赋值为特定值,进程被链接到运行队列,PCB添加一个dlist标记队列前后节点。

阻塞状态 / 资源的等待队列:

  • 当一个进程需要访问某个资源时,如果资源尚未准备好,进程无法继续执行。

  • 资源的状态结构体中会自己维护一个队列,这个队列用于存储那些:因资源当前不可用而被阻塞的进程。

  • 当前正在运行的进程如果发现需要的资源不可用,那么它会从运行队列中被移出,并放入所需资源的等待队列。并且它的状态将被修改为“阻塞”。

  • 操作系统会调度其他进程运行,直到阻塞的进程所需的资源变得可用。资源的状态结构体会通知在等待队列中的进程,并将其从阻塞状态恢复到就绪状态。这些进程会被重新放回运行队队列。

阻塞挂起状态:

  • 当操作系统检测到内存严重不足时,它可能会将那些处于等待状态且短时间内不会被执行的进程 (PCB+可执行程序)从内存中转移到磁盘,从而节省出一部分内存。这一过程称为“挂起”。

  • 处于资源等待队列的进程,由于处于阻塞状态,短时间也不会被执行,不如直接挪动到磁盘来节省出空间。

  • 将进程从内存移至磁盘的操作会带来性能上的开销,因为磁盘I/O操作比内存访问要慢得多。但在内存极度紧张的情况下,这种代价是必要的,以防止操作系统因为内存耗尽而崩溃。

  • swap分区,不建议设置很大,可能导致频繁的内存和磁盘的交互,导致操作系统变慢。一般设置到和内存一样大或者两倍即可。

swap分区:

  • swap分区存储的就是被挂起的进程。

  • swap的读写速度远不及物理内存。如果系统频繁使用swap,整体性能会明显下降,可能导致系统响应变慢,甚至出现“卡死”的现象。

  • 如果swap分区过大,可能会诱导系统频繁将数据交换到磁盘上,导致更多的I/O操作,反而降低了系统的整体性能。

  • 一般建议swap分区的大小设置为物理内存的1倍或更小。  

———————————————

Linux下,进程的运行状态:

运行状态:

R (Running or runnable):进程正在运行或在运行队列中等待运行。

前台进程 / 后台进程:

  • 当stat显示的进程状态后面有+,比如R+,S+。代表这个进程为前台进程。前台进程通常是由用户直接控制的,比如通过终端启动的程序。比如有一个可执行程序mycode,./mycod直接运行就是以前台进程方式运行的。

  • 如果stat显示的进程状态没有+,代表这个进程为后台进程。以后台进程的方式运行某个进程,需要在进程后面加取地址符号(&)。例如:./mycode &  

休眠状态:

S (Sleeping):进程处于休眠状态,即它正在等待某个事件(如I/O操作完成)。这类进程可以被唤醒。
D (disk sleep):不可中断的休眠状态。进程通常在等待硬件设备时处于此状态,不会处理任何信号,不可被中断,直到进程调用完成。处于D状态的进程过多,系统资源被大量消耗,可能导致系统性能下降或者崩溃。 

暂停状态 / 18和19信号:

T (Stopped):进程已经停止运行。可能是因为收到了SIGSTOP信号或者被调试器暂停。
kill -18 pid  //暂停进程 -SIGCONT
kill -19 pid  //继续进程 -SIGSTOP

僵尸状态:

Z (Zombie):僵尸进程,进程已终止但尚未被其父进程回收。此状态下的进程只剩下一个PCB,系统资源已经被释放。

  • 当进程进入僵尸状态时,可执行程序和大部分资源已经被释放,但PCB仍然保留。

  • 当程序终止时会return一个值,会由操作系统写入到进程的PCB中(exit_code)。

  • 之后父进程在读取子进程的退出状态的同时适释放PCB == 将进程状态从 ‘Z’改为 ‘X’。

  • 再判断是否需要做出下一步动作,例如重新启动子进程、记录日志或采取其他相应的措施。

  • 僵尸进程本身并不消耗大量资源,但如果大量僵尸进程积累,可能会导致系统进程表耗尽,影响系统的进程管理。

父进程不存在僵尸状态:

  • 僵尸状态是专门针对子进程的,每个父进程也有他的父进程。

  • 当一个子进程的父进程终止,父进程的父进程就会处理他的退出状态并释放PCB。

孤儿进程和进程领养:

  • 当子进程的父进程先被终止,那么子进程就会变为孤儿进程。

  • 孤儿进程终止变为僵尸进程后,没有父进程读取其退出状态,并为其释放PCB,会导致内存泄漏。

  • 孤儿进程会被init进程(Linux系统中通常是systemd)收养并处理。当这些被收养的子进程终止时,init进程会读取它们的退出状态,防止它们成为僵尸进程。

———————————————

排队的本质——确认优先级:

  • 进程排队的本质源于资源的有限性与进程需求的无限性之间的矛盾。

  • 操作系统通过调度和排队机制管理这个矛盾,以确保资源被有效利用,同时为所有进程提供合理的执行机会。

进程优先级的本质:

  • 进程优先级的本质,是一个存在于PCB中int变量。

  • 变量的值越小,优先级越大。

  • linux中,进程优先级的范围为:60~99,默认进程的初始优先级为80。

ps -l //可以查看进程优先级,PRI字段就是优先级数值 

通过NI值修正进程优先级值PRI:

  • linux下,不允许直接修改进程优先级,需要通过nice值=>NI值,来修正优先级数值。

  • PRI(new) = PRI(old) + NI

 top//启动任务管理器 -> r//重设nice值 -> 输入pid -> 新的nice值。

  • 普通用户可以调低进程的优先级,但是不能调高,使用超级用户可以调高进程优先级

  • 由于PRI范围为60~99,基于pri初始值为80,所以调整nice值的范围为-20~19。

限定优先级在一定范围的原因:

  • 某些进程优先级过低,可能长时间无法被调度。导致进程饥饿。

  • 通过将进程优先级限制在一定的范围内,可以确保即使是最低优先级的进程,也能在合理的时间内获得CPU资源。

  • 还可以帮助操作系统在资源分配中实现公平性和有效性,避免极端优先级设置导致某进程一直被调用。

进程的并行和并发:

  • 并行:多进程分别在多CPU下,同时运行。

  • 并发:多进程在单CPU下,高速切换运行。

进程切换和上下文保存:

  • 一个CPU通常只有一套寄存器硬件。所以这套寄存器对不同进程都是共享。

  • 当CPU切换进程时,会将寄存器中的内容保存到进程的PCB中,也可以认为是保存在内存中(通常是堆栈)。

  • 当切换要调度的新进程后,不会直接清空存储在寄存器中上一个进程的数据,而是直接将新进程的数据覆盖到寄存器上。

 

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

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

相关文章

Java重修笔记 第五十三天 坦克大战(一)绘图入门

绘制简单的图形 1. 创建画板 定义一个画板类&#xff0c;通过继承 JPanel 类来创建画板 2. 创建画笔 在画板类中调用 paint 方法&#xff0c;并传入一个 Graphics g 对象&#xff0c;通过对 g 对象的操作来实现画画的过程 3. 开始作画 调用 Graphics g 对象的方法在 paint …

驰域货车四路监控ts视频格式化恢复方法

不少大货车都使用了驰域货车监控&#xff0c;一般是至少装四路&#xff0c;前后左右&#xff0c;有的还会车顶加一路。驰域货车记录仪特殊的地方在于&#xff1a;其采用了一种上古时期的视频格式----TS视频流。 故障存储: 128G卡/fat32 故障现象: 客户提供的信息是格式化后…

193页WORD省级智慧高速公路投标技术方案

关注智慧方案文库&#xff0c;学习9000多份智慧城市&#xff0c;智慧医院&#xff0c;智能制造&#xff0c;数字化转型&#xff0c;新质生产力&#xff0c;算力&#xff0c;大模型&#xff0c;AIGC&#xff0c;工业互联网&#xff0c;数字孪生......持续更新热点行业解决方案。…

云曦2024秋季开学考

ezezssrf 第一关&#xff1a;md5弱比较 yunxi%5B%5D1&wlgf%5B%5D2 第二关&#xff1a; md5强比较 需要在bp中传参&#xff0c;在hackbar里不行 yunxiiM%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DC V%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%00%A8%28K%F3n%8EKU%B3_B…

机器学习(西瓜书)第 6 章 支持向量机

6.1 算法原理 感知机要求就随便找一个超平面&#xff0c;只要能把正负样本分开就行 但是支持向量机不一样&#xff0c;它认为你不仅得把它分开&#xff0c;而且这个超平面还得尽可能的离正负样本远 6.2 间隔与支持向量 其中w (wi&#xff1b;w2;…;wd)为法向量&#xff0c;决…

基于51单片机的打点滴监控系统proteus仿真

地址&#xff1a;https://pan.baidu.com/s/1l3OxHLBwOzsChKHCJsAySQ 提取码&#xff1a;1234 仿真图&#xff1a; 芯片/模块的特点&#xff1a; AT89C52/AT89C51简介&#xff1a; AT89C52/AT89C51是一款经典的8位单片机&#xff0c;是意法半导体&#xff08;STMicroelectron…

深入探索:自适应中值滤波器在图像去噪中的应用

在数字图像处理领域&#xff0c;噪声是影响图像质量的重要因素之一。椒盐噪声&#xff0c;作为常见的一种噪声&#xff0c;会在图像中随机产生过度黑或过度白的像素&#xff0c;严重影响图像的视觉质量。为了有效去除这类噪声&#xff0c;自适应中值滤波器&#xff08;AMF&…

《论应用服务器基础软件》写作框架,软考高级系统架构设计师

论文真题 应用服务器是在当今基于互联网的企业级应用迅速发展,电子商务应用出现并快速膨胀的需求下产生的一种新技术。在分布式、多层结构及基于组件和服务器端程序设计的企业级应用开发中,应用服务器提供的是一个开发、部署、运行和管理、维护的平台,提供软件“集群”功能…

二十三种模式之原型模式(类比制作陶器更好理解一些)

1. 设计模式的分类 创建型模式(五种)&#xff1a;工厂方法模式、单例模式、抽象工厂模式、原型模式、建造者模式。 结构型模式(七种)&#xff1a;适配器模式、代理模式、装饰器模式、桥接模式、外观模式、享元模式、组合模式。 行为型模式(十一种)&#xff1a;状态模式、模板方…

re题(16)BUUCTF-Java逆向解密

BUUCTF在线评测 (buuoj.cn)BUUCTF在线评测 (buuoj.cn) jadx 1.4.4安装&#xff1a;jadx-gui-1.4.4 反编译工具使用教程 - 莫贞俊晗 - 博客园 (cnblogs.com) 认识.class&#xff1a; Java-初识 .class 文件_class文件怎么打开-CSDN博客 用查壳工具也可以知道是java写的 放到ja…

Ocelot + Consul 无法转发IP问题

现象 Ocelot Concul 进行访问 Ocelot Concul 服务都部署在同一台机器上时&#xff0c;访问正常 服务部署在另外一台机器上时&#xff0c;无法访问 显示 102 (unknown) status code of request URI: 发现Ocelot 日志显示是 hostname/api 所有 换了一台电脑就无法访问了 Ocel…

LabVIEW回转马达试验系统

基于LabVIEW的回转马达试验台通过高度集成的硬件与软件配合&#xff0c;实现对回转马达的各项性能测试&#xff0c;包括空载排量、跑合试验和冲击试验等&#xff0c;以满足出厂测试的严格标准和要求。 项目背景 回转马达作为多种机械设备的核心动力源&#xff0c;其性能的可靠…

一文搞定高并发编程:CompletableFuture的supplyAsync与runAsync

CompletableFuture是Java 8中引入的一个类&#xff0c;用于简化异步编程和并发操作。它提供了一种方便的方式来处理异步任务的结果&#xff0c;以及将多个异步任务组合在一起执行。CompletableFuture支持链式操作&#xff0c;使得异步编程更加直观和灵活。 在引入CompletableFu…

Python(TensorFlow和PyTorch)及C++注意力网络导图

&#x1f3af;要点 谱图神经网络计算注意力分数对比图神经网络、卷积网络和图注意力网络药物靶标建模学习和预测相互作用腹侧和背侧皮质下结构手写字体字符序列文本识别组织病理学图像分析长短期记忆财务模式预测相关性生物医学图像特征学习和迭代纠正 Python注意力机制 对…

Java面试篇基础部分-Java 实现的I/O方式

Java I/O 在整个的java.io包中提供了5个重要的I/O类和1个接口类。5个类分别是File、OutputStream、InputStream、Writer、Reader ,1个接口是指Serializable序列化接口。具体的使用方式可以查看JDK的参考文档。 Java NIO 实现 Java NIO的实现内容主要有如下的三个核心内容 Sel…

使用Vue3.5的onWatcherCleanup封装自动cancel的fetch函数

前言 在欧阳的上一篇 这应该是全网最详细的Vue3.5版本解读文章中有不少同学对Vue3.5新增的onWatcherCleanup有点疑惑&#xff0c;这个新增的API好像和watch API回调的第三个参数onCleanup功能好像重复了。今天这篇文章来讲讲新增的onWatcherCleanup函数的使用场景&#xff1a;…

《 C++ 容器全景指南:五 》深入探索 C++ 标准库中的 stack 与 queue 容器适配器

1、引言 1.1、容器适配器的概念与应用 容器适配器&#xff08;Container Adapters&#xff09;是 C 标准库提供的一种特殊容器&#xff0c;它不是一种独立的容器&#xff0c;而是对其他标准容器的封装&#xff0c;用来实现特定的数据结构如栈&#xff08;stack&#xff09;和…

【信创】麒麟KOS上安装使用网络抓包工具Wireshark

原文链接&#xff1a;【信创】麒麟KOS上安装使用网络抓包工具Wireshark Hello&#xff0c;大家好啊&#xff01;今天给大家带来一篇关于如何在麒麟桌面操作系统上安装和使用Wireshark的文章。Wireshark是一款强大的网络协议分析工具&#xff0c;广泛应用于网络故障排查、网络流…

Makefile学习总结

Makefile学习总结 目录 Makefile学习总结1. Makefile介绍2. Makefile规则3. Makefile文件里的赋值方法4. Makefile常用函数4.1 字符串替换和分析函数4.2 文件名函数4.3 其他函数 5. Makefile使用示例6、多级目录通用Makefile Demo6.1 一般通用Makefile的设计思想6.2 Demo分析 参…

DAY73

作业 pro文件&#xff1a; QT texttospeech 头文件&#xff1a; #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QPushButton> //按钮类 #include <QLabel> //标签类 #include <QLineEdit> //行编译器类 #include…