进程的初步认识

目录

一、硬件方面介绍

1.冯诺依曼体系结构

2.存储分级

二、软件 方面

1.操作系统是一款进行管理的软件,它可以管理硬件也可以管理软件

2.操作系统如何管理?

三、进程 

1.概念

总结

四、linux中对进程的管理 

1.task_ struct内容分类

2.查看进程

 3.通过系统调用获取进程标示符

4.知识补充

5.一些信号

6.通过系统调用创建进程-fork

1.对于fork返回值有两个的解释

2.如何做到一个函数返回两次? 

3.一个变量如何储存两个值?

4.父子进程谁先运行呢?

 bash

7.进程状态 

1.运行

2.阻塞

3.挂起

8.linux下状态 

 R运行状态(running):

S睡眠状态(sleeping):

知识补充 

D磁盘休眠状态(Disk sleep)

T停止状态(stopped):

X死亡状态(dead): 

Z僵死状态(Zombies)

孤儿进程

9.进程内的访问

10.进程优先级

1.优先级是什么?

2.为什么要有优先级

3.linux中的进程优先级

4.用top命令更改已存在进程的nice:

5.优先级的工作原理

如何判断当前运行的那个队列是否为空 


一、硬件方面介绍

1.冯诺依曼体系结构

abcde都是独立的个体,所以各个单元必须要用“线”连接起来,称为总线,为图中红色

1.系统总线   连接运算器和控制器

2.io总线   连接存储器和输入输出设备

一个程序要运行必须先加载到内存,是因为冯诺依曼体系就是这样子规定的

2.存储分级

二、软件 方面

1.操作系统是一款进行管理的软件,它可以管理硬件也可以管理软件

笼统的理解,操作系统包括:
内核(进程管理,内存管理,文件管理,驱动管理)
其他程序(例如函数库,shell程序等等)

                                                                总体纵览图

操作系统存在的意义是通过管理好底层的软硬件资源,为用户提供一个良好的执行环境 

操作系统里面会有各种数据,但是操作系统不相信任何用户

因此为了保护自身数据的安全,也为了能够给用户提供服务,操作系统以接口的方式给用户提供调用的入口,来获取操作系统内部的数据。

这些接口是操作系统提供的,用c语言实现的,自己内部的函数调用---------系统调用(即上图的系统调用接口)

库函数(lib)vs系统调用

库函数和系统调用是上下层,调用与被调用的关系

所有访问操作系统的行为都只能通过系统调用完成,任何库函数只要试图访问操作系统或者硬件(软硬件资源),都需要经过系统调用

2.操作系统如何管理?

先描述后组织

管理者决策者    操作系统     类比校长

执行者               驱动程序             辅导员

被管理者            软硬件资源         学生

我们要管理学生,先得对学生的信息进行描述,例如学院  姓名  班级  专业等等

每个学生都可以转换成一个结构体

我们再将这些结构体进行组织,例如使用双向链表将每一个结构体进行连接

那么我们对学生的管理就转换成对链表的增删查改了

在操作系统中任何管理对象,最终都可以转化成为对某种数据结构的增删查改

三、进程 

1.概念

一个已经加载到内存中的程序,被称为进程,也被称为任务

可以理解成,正在运行的程序,叫做进程

而一个操作系统不仅仅只能运行一个进程,可以同时运行多个进程,因此我们也必须将进程管理起来,如何管理呢?先描述再组织。

进程 = 内核PCB数据结构对象+ 我们自己的代码和数据

                     这个数据结构对象

                     描述这个进程的所有属性值

任何一个程序在加载到内存的时候,形成真正的进程时,操作系统要先创建描述进程的结构体对象----PCB  (process ctrl block 进程控制块),PCB就是一个进程属性的集合

这个集合就是一个struct结构体,里面包含例如:进程编号(PID)  进程的状态 优先级等等,根据进程的PCB类型,为该进程创建对应的PCB对象

我们只需要对PCB进行管理就可以管理这个进程,PCB中含有进程的各个属性,因此也顺理成章地会去记录代码和数据的位置,记录下指针。

(操作系统也是软件,所以开机时也会加载到内存中) 

在操作系统之中,对进程进行管理,就变成了对单链表进行增删查改

总结

计算机管理硬件
1. 描述起来,用struct结构体
2. 组织起来,用链表或其他高效的数据结构 

四、linux中对进程的管理 

Linux操作系统下的PCB是: task_struct

所以

在Linux中描述进程的结构体叫做task_struct。
task_struct是Linux内核的一种数据结构,它会被装载到RAM(内存)里并且包含着进程的信息

1.task_ struct内容分类


1.标示符: 描述本进程的唯一标示符,用来区别其他进程。
2.状态: 任务状态,退出代码,退出信号等。
3.优先级: 相对于其他进程的优先级。
4.程序计数器: 程序中即将被执行的下一条指令的地址。
5.内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针
6.上下文数据: 进程执行时处理器的寄存器中的数据[休学例子,要加图CPU,寄存器]。
7.I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
8.记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等

9.其它信息

2.查看进程

1.ps ajx(我们通常会搭配grep来使用)

COMMAND系统运行这个进程时是调用什么指令

2. ls  /proc

这个文件夹内的信息实际上是操作系统将内存中的进程进行可视化(因此这个文件夹里面的信息是动态变化的)

这些蓝色的数字就是相应进程的PID 

(同一个程序进行多次运行时,所产生的PID也会不同)

进入目录,里面存储的是该进程的一些属性,我们这里简单看一下cwd和exe

cwd (current work dir)后面的内容指的是:当前的工作目录

例如我们touch  文件名  来创建一个文件,当touch载入内存变成进程的时候会记录它启动时的工作目录,所以创建的文件在没有指定路径的时候,默认就会在当前路径下创建

exe  后的内容指的是:这个进程对应的文件是这个路径下的这个文件,即指针信息可视化

 3.通过系统调用获取进程标示符


进程id(PID)   使用getpid()
父进程id(PPID)使用getppid()

进程的pid也是它的属性,所以pid也在task_struct中存放

ppid在同一个终端下启动一般不会改变,所有子进程的父进程都是bash

4.知识补充

1.在底行模式下,使用!man也可以直接查询手册

2.多条不同指令可以在同一行进行输入,可以使用&&进行分隔,从左到右一次执行

5.一些信号

kill -9  PID 杀死对应pid的进程

6.通过系统调用创建进程-fork

fork可以创建子进程,即系统里多了一个进程,那么这个进程也需要有自己的task_struct和数据以及代码

因为子进程没有自己的代码所以一般而言,fork之后的代码,父子共享

1.对于fork返回值有两个的解释

  我们为什么要创建子进程呢?是因为我们想让父子进程做不同的事情,所以需要让父和子执行不同的代码块,为了实现这个功能,fork就具有了不同的返回值,对父进程返回子进程的pid(因为字进程查询父进程pid成本低,但是父进程无法准确查询子进程),对子进程返回0,如果失败就返回-1,所以我们可以使用if else来对代码进行分流

2.如何做到一个函数返回两次? 

我们可以猜测到fork函数内的大概功能

pid_t fork(void)

{

1.创建子进程pcb

2.填充子进程pcb相应内容

3.让父子进程共享同样的代码

......

此时由于父子进程都有独立的pcb了,他们都可以被cpu调度运行了

return ;

}

我们可以看到,return位于函数的最后,而此时函数的功能已经被实现,因此return的代码也被共享了

3.一个变量如何储存两个值?

首先我们需要知道进程之间是相互独立的

因为数据可能被修改所以我们不能让父子进程共享同一份数据(可以共享代码是因为运行时代码已经不会被修改了,不会影响进程间的独立性)

所以为了解决这个问题,字进程会进行写时拷贝,当子进程修改父进程的数据时,会重新开辟一块空间,因此当return 返回的值被写入父进程的数据时候,父进程的数据直接被修改,而系统会给子进程开辟一块空间用于储存另一个返回值

4.父子进程谁先运行呢?

由调度器决定,是不确定的

调度器会相对公平地调度

 bash

bash,即命令行解释器,它通过fork创建子进程,执行相应的指令,而它本身继续接收我们的指令,这就是fork创建的父子进程的实际应用

7.进程状态 

操作系统学科上的进程状态一般分为,运行,阻塞,挂起 

1.运行

操作系统会将已经准备好运行的进程放入运行队列中,操作系统根据顺序去调度这些进程,处于这个状态的进程就为运行状态:R 

一个进程并不是放上去一直到执行结束的,每一个进程都有一个叫时间片的概念,在一个时间段内所有的进程代码都会被执行,即并发执行

大量地把进程放到cpu上和拿下来的动作被称为进程切换

2.阻塞

操作系统会像管理进程一样管理硬件,每一个硬件属性的结构体中会存在一个等待队列, 如果进程想要读取某个硬件的数据,那么它就会被排在该硬件的等待队列中,这时候进程就处于阻塞状态,一直等待到硬件已经准备好了,然后这个进程就会被排到运行队列中

等待特定设备的进程,我们称该进程处于阻塞态

3.挂起

当操作系统内部的内存不够了,那么在阻塞状态的进程,它的代码和数据就会被换出到磁盘中(swap盘),等到程序准备好运行了,它的代码就又会被换入到内存中,代码和数据被换出状态下的程序就处于挂起状态

8.linux下状态 

static const char * const task_state_array[] = {
"R (running)", /* 0 */
"S (sleeping)", /* 1 */
"D (disk sleep)", /* 2 */
"T (stopped)", /* 4 */
"t (tracing stop)", /* 8 */
"X (dead)", /* 16 */
"Z (zombie)", /* 32 */
};

 R运行状态(running):

并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。


S睡眠状态(sleeping):

意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠
(interruptible sleep))

由于cpu的速度很快,所以一个进程有很大一部分时间是在等待i/o设备就绪,我们查询的时候基本上是处于S状态,但是当我们执行一个空语句,即例如

while(1)

此时程序不进行输入输出,它就一直处于运行状态了

所以S状态可以对应阻塞状态

知识补充 

如果程序处于  例如S+ R+的状态那么说明该程序在前台运行,这时候我们就不能继续在命令行解释器输入指令了,我们可以

./test.exe  &

这样程序就会转为到后台运行,状态后的加号也会消失,这种进程只能使用kill来杀死

D磁盘休眠状态(Disk sleep)

有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。

在等待期间这个进程不能被杀死,对应的也是阻塞状态

T停止状态(stopped):

可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可

以通过发送 SIGCONT 信号让进程继续运行。

kill -19 暂停进程,暂停之后进程状态就会变成T

kill -18继续进程  进程继续后会转为后台运行

T状态有自己的应用场景,可能是要等待资源也可能是单纯被其它进程控制了

例如我们使用gdb调试进程时,运行某个程序并且在某个位置打上断点,进程在该代码处停止的状态就处于t状态,(t和T区别不是很大,暂时可以理解为同一种状态)

X死亡状态(dead): 

这个状态只是一个返回状态,你不会在任务列表里看到这个状态

Z僵死状态(Zombies)

是一个比较特殊的状态。当进程退出并且父进程(使用wait()系统调用,后面讲)
没有读取到子进程退出的返回代码时就会产生僵死(尸)进程
僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。
所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态 

如果处于Z状态的程序没有被读取,僵尸进程会一直占用内存,但不会继续运行,会造成内存泄露

孤儿进程

当一个子进程的父进程被终止(在代码中使用exit(0)),但是子进程继续运行,那么子进程的父进程会被更改为1进程,即操作系统 ,因为如果子进程不被托管,在子进程运行结束后就不会被回收了

(如果将父进程直接ctrl+c终止,那么在父进程被回收的一瞬间,子进程在将父进程更改为操作系统后,子进程也会被回收)

9.进程内的访问

某个进程,它的pcb信息可以储存多种用于访问不同数据结构的指针,也就是说一个进程可以被存放在链表中也可以同时被存放在多叉树等等中。

下面我们简单讲一下进程如何相互访问,下是三点前提信息

1.这是一个双链表的结构体,我们现在有一个struct node* 类型的start变量,储存了第一个进程的一个地址

2.这个进程指向的是link

3.link节点内是指向 前后进程的指针

首先我们假设地址0是一个task_struct*类型的一个指针

(task_struct*)0

我们让它指向它的结构体内的link

(task_struct*)0->link

我们再将其取地址,得到的就是link与结构体的地址(即结构体最开始的那个变量的地址)之间的地址差,因为结构体地址为0。

&(task_struct*)0->link

因为我们现在已经有了一个结构体的link的地址,因此我们只需要将它的地址减去上面所算出的地址差,就找到了结构体的地址。(要使用int强转,转换成一个单纯数值的运算,而不是地址间的运算)

(int)start-(int)&(task_struct*)0->link

我们就得到了结构体的地址的数值,将其强转成task_struct*类型,即可访问该进程的其它内容了

(task_struct*)(int)start-(int)&(task_struct*)0->link

10.进程优先级

1.优先级是什么?

优先级是决定某个进程被访问顺序的一项属性。是一个[60,99]之间的一个数值

2.为什么要有优先级

因为资源是有限的,进程是多个的,因此进程之间具有竞争性,操作系统必须保证大家良性竞争,确认优先级

如果进程长时间得不到cpu资源,该代码得不到推进,进程就会面临饥饿问题。

3.linux中的进程优先级

我们使用ps-l指令可以看到

其中

PRI :代表这个进程可被执行的优先级,其值越小越早被执行
NI :代表这个进程的nice值

PRI即进程的优先级,或者通俗点说就是程序被CPU执行的先后顺序,此值越小,进程的优先级别越高
NI就是我们所要说的nice值了,其表示进程可被执行的优先级的修正数值,进程nice值会影响到进
程的优先级变化

程序一般的PRI值为80
当我们对程序进行修正,加入nice值后,将会使得PRI变为:PRI(new)=PRI(old)+nice
这样,当nice值为负值的时候,那么该程序将会优先级值将变小,即其优先级会变高,则其越快被执行
nice其取值范围是-20至19,一共40个级别

我们每次修改进程的优先级,PRI(old)都为80,当nice的值太大或者太小时,nice值会被限制在-20和19。

4.用top命令更改已存在进程的nice:

top
进入top后按“r”–>输入进程PID–>输入nice值 

(只有root才能更改优先级)

nice和renice也可以更改

5.优先级的工作原理

 

在运行队列中会存在两个指针数组,他们指向对应的对应的结构体,其中下标[100,139]对应[60.99] 的PRI的值,根据PRI值,我们将相应的task_struct链接上去,相同PRI值遵循先来后到的原则,类似于哈希表的处理办法

运行队列中有两个相同的数组,这里为了区分我们将其命名为,waiting和running,即当前run和当前wait,当running中的进程依次开始运行时,新进入运行队列的进程会被插入到waiting中,当running中的进程都运行完毕,他们两个的职能就互换,这样能够避免先进入但是PRI较大的进程一直处在队列的末尾得不到运行。

为了实现上述功能,两个数组的指针会不断被run和wait交换,这两个二级指针用于寻找当前run和当前wait的数组

如何判断当前运行的那个队列是否为空 

我们可以创建数组

char bits[5],里面有40个比特位,对应四十级优先级,每个比特位上的1与0表示该优先级所对应的进程队列里面是否有进程,当bits为0时,说明当前run的数组里面指向的进程都已经被运行完毕。

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

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

相关文章

现代信息检索笔记(四)——文档评分、词项权重计算及向量空间模型

目录 对搜索结果进行排序 目标 方案一:jaccard系数 方案二:tf-idf公式 长文本长度 向量空间模型小结 对搜索结果进行排序 排序式检索,如何高速求相关性R 目标 无关的不在上面相关度高的在前面 在链表中不出现的相关性为0&#xff0c…

PageCache页缓存

一.PageCache基本结构 1.PageCache任务 PageCache负责使用系统调用向系统申请页的内存,给CentralCache分配大块儿的内存,以及合并前后页空闲的内存,整体也是一个单例,需要加锁. PageCache桶的下标按照页号进行映射,每个桶里span的页数即为下标大小. 2.基本结构 当每个线程的…

如何使用uer做多分类任务

如何使用uer做多分类任务 语料集下载 找到这里点击即可 里面是这有json文件的 因此我们对此要做一些处理,将其转为tsv格式 # -*- coding: utf-8 -*- import json import csv import chardet# 检测文件编码 def detect_encoding(file_path):with open(file_path,…

Vatee万腾平台:智能生活的新选择

在科技飞速发展的今天,智能生活已经不再是遥不可及的梦想,而是逐渐渗透到我们日常生活的方方面面。Vatee万腾平台,作为智能科技领域的佼佼者,正以其创新的技术、丰富的应用场景和卓越的用户体验,成为智能生活的新选择&…

dc/dc_shell的keep和donot touch区别

donot touch和keep的区别 在半导体设计和综合工具中,donottouch 和 keep 属性通常用于指定综合和布局阶段的特定要求。sizeonly 是 keep 属性的一个可能值。以下是 donottouch 和 keep 属性以及 sizeonly 的区别和用途: donottouch: donotto…

rsync使用教程

1、rsync是什么 rsync是一个在Unix/Linux环境下常用的工具,Windows上可以通过一些替代工具或者使用Cygwin环境来实现类似的功能。Cygwin在安装过程中,选择需要安装的组件时确保选择了rsync和openssh(如果需要通过SSH连接到其他服务器进行备份)。rsync的简单使用如下: rs…

如何引流到私域最有效?

引流到私域最有效的方法通常包括以下几个策略: 1、内容营销: 优质内容创作:制作有价值、有吸引力的内容,如文章、视频、图文等,吸引用户关注。 SEO优化:通过搜索引擎优化,提高内容在搜索引擎…

带流水线的持续连接详解

流水线(Pipeline)的持续连接在网络编程中通常指的是一种能够保持连接持续开放,并允许多个请求在同一个连接上连续发送和接收的技术。这种技术在HTTP/1.1和其他一些网络协议中有应用,目的是提高网络通信效率和性能。HTTP的默认模式…

C++| STL之string

前言:最近在做LeetCode算法题,C字符串通常都是string作为输入,所以补充一下STL里面string。在介绍的具体使用的时候,会补充char字符串相关的进行对比。 string 创建大小和容量遍历字符串比较插入字符拼接字符串分配内存查找截取分…

Java 注入的几种方式

构造函数注入:构造函数注入是最常见的一种依赖注入方式。通过在组件的构造函数中接受依赖参数,并将其保存在私有字段中,可以实现依赖注入。这种方式简单直接,适用于必须的依赖和不变的依赖场景。 public class UserserviceImpl im…

vue学习笔记(购物车小案例)

用一个简单的购物车demo来回顾一下其中需要注意的细节。 先看一下最终效果 功能: (1)全选按钮和下面的商品项的选中状态同步,当下面的商品全部选中时,全选勾选,反之,则不勾选。 &#xff08…

51单片机嵌入式开发:2、STC89C52操作GPIO口LED灯

STC89C52操作GPIO口LED灯 1 芯片介绍1.1 芯片类型1.2 芯片系列说明 2 GPIO引脚寄存器说明3 GPIO操作3.1 GPIO输入3.2 GPIO输出3.3 GPIO流水灯3.4 Protues仿真 4 总结 1 芯片介绍 1.1 芯片类型 芯片采用宏晶科技品牌下的STC89C52RC单片机 选择STC89C52RC系列STC89C58RD系列单片…

Pycharm远程连接GPU(内容:下载安装Pycharm、GPU租借、配置SSH、将代码同步到镜像、命令行操控远程镜像、配置远程GPU解释器)

目录 windows下载安装pycharmGPU租借网站AutoDlfeaturize好易智算 GPU租借GPU选择选择镜像充值 然后创建镜像创建成功 复制SSH登录信息 远程进入镜像 在Pycharm中进行ssh连接新建SFTP配置SSH复制ssh根据复制的信息填写ssh配置测试连接 将代码同步到远程镜像上设置mappings将本地…

大语言模型与知识图谱结合发展方向

引言 在人工智能的发展历程中,大语言模型(LLM)的出现标志着一个重要的转折点。随着深度学习技术的突破和计算能力的提升,LLM以其前所未有的规模和复杂性,开启了迈向人工通用智能(AGI)的新浪潮。…

STM32利用FreeRTOS实现4个led灯同时以不同的频率闪烁

在没有接触到FreeRTOS时,也没有想过同时叫两个或两个以上的led灯闪烁的想法,接触后,发现如果想叫两个灯同时以不同的频率闪烁,不能说是不可能,就算是做到了也要非常的麻烦。但是学习了FreeRTOS后,发现要想同…

使用WinSCP工具连接Windows电脑与Ubuntu虚拟机实现文件共享传输

一。环境配置 1.首先你的Windows电脑上安装了VMware虚拟机,虚拟机装有Ubuntu系统; 2.在你的windows电脑安装了WinSCP工具; 3.打开WinSCP工具默认是这样 二。设置WinSCP连接 打开WinSCP,点击新标签页,进入到如下图的…

(杂文)参加WAIC 2024 所思所感

受华为广办的邀请,在领导要求下, 我还是在这个炎热的暑假通过一个接近凌晨两点落地的飞机连夜从北京来到了上海,去“睁眼看世界”。 区别于纯学术会议和CCF类的会议,WAIC 更加的平易近人,有更多的工业界同行&#xff…

【学术会议征稿】2024年工业自动化与机器人国际学术会议(IAR 2024)

2024年工业自动化与机器人国际学术会议(IAR 2024) 2024 International Conference on Industrial Automation and Robotics 2024年工业自动化与机器人国际学术会议(IAR 2024)将于2024年10月18-20日在新加坡隆重召开。会议将围绕…

三丰云评测:免费虚拟主机与免费云服务器的全面对比

三丰云是一家知名的互联网服务提供商,专注于虚拟主机和云服务器的服务。在互联网技术日新月异的今天,选择一个优质的云服务提供商至关重要。本次评测将重点对比三丰云的免费虚拟主机和免费云服务器,帮助用户更好地选择适合自己需求的服务。首…

0 TMS320F28379D 开坑

开坑原因 最近开始做实验,实验室的主控采用的是F2812FPGA,属于够用但不好用的状态。FPGA用于生成调制信号,DSP完成采样和控制。师兄师姐研究拓扑及调制策略,对驱动数量以及驱动逻辑有比较高的要求,因此不好脱离FPGA&a…