Linux 进程概念和状态

目录

一、冯诺依曼体系结构

二、操作系统

1.概念

2.理解操作系统的管理

硬件和管理

为什么要有操作系统

三、进程的概念

PCB:

进程的删除和子进程的创建

删除

创建子进程

四、进程的状态

七种状态:

实验查看部分状态:

R:

S:

D:

T/t:

Z/X:

运行状态

阻塞状态和阻塞挂起状态


一、冯诺依曼体系结构

我们在使用计算机本质上都是对数据进行处理,将数据输入到计算机,计算机在输出到一些设备上让我们看到。计算机在处理这些数据上都基本遵循着冯诺依曼体系。

输入设备:键盘、鼠标、磁盘、网卡、话筒...

存储器:内存

中央处理器:cpu

输出设备:显示器、声卡、磁盘、网卡...

这个过程就是对数据的流动加工,先将数据输入到输入设备中,输入设备再拷贝到存储器上,存储器将数据给运算器来进行基本运算处理数据,再把加工后的数据返给存储器,由存储器给输出设备。整个过程都是由控制器来控制的。我们都知道cpu是非常快的,但它容量很小,它也是计算机最重要的部分。

'

上图总结一下就是距离cpu越近,成本越高,容量越小。

存储器的作用:

体系中存储器起到的作用就像一个巨大的缓存。如果没有它,处理数据时就是外设(输入输出设备)把数据给cpu,但外设的速度又是特别慢的,cpu是很快的,这就导致数据的流动是一点一点流,cpu一点一点的处理数据,整体效率就很低。有了存储器,内存就会先将这些数据存起来,等达到一定要求时再给cpu让其运算,返给内存后,等到输出设备需要时再给它。这时的运算效率就成了内存到cpu,比外设到cpu快很多。

如果我们有钱也可以将内存和硬盘都换成cpu,不过那样的电脑就要几百万,所以内存和硬盘的存在也是计算机价格低的原因。

体会冯诺依曼体系的运行方式:

1.程序的运行

一个程序包含代码和数据,我们要通过代码运算数据就需要cpu来实现,这期间程序是一直在内存上的,我们使用输入设备将数据给内存上的程序在由cpu加工。这也像我们写代码一样,开辟的变量都是在内存上,最后通过内存由cpu去执行代码对数据进行加工得出结果,再由内存返给显示器让我们看到。

2.网上聊天

假如你和一个朋友在使用qq聊天,你给他发"在吗",可能为了保证数据的安全需要对数据加密,就要cpu的处理,从输入设备输入到内存,cpu在处理数据。使用qq需要网络,输出设备就必须能和网路建立联系,所以要将数据流到网卡上,中间还有网路的处理这里先不管。朋友的电脑就是从输入设备(网卡)上拿到加密的"在吗",将数据给内存,再到cpu解密返给内存,内存在给到输出设备(显示器)让朋友看到。

二、操作系统

1.概念

操作系统是一款软件,对软硬件资源管理的软件。在电脑开机时,等待一段时间显示器才会显示内容,这段时间就是在等待操作系统的启动。

广义认识:操作系统内核和操作系统外壳周边程序(对操作系统的使用方法)

狭义认识:操作系统内核。

2.理解操作系统的管理

操作系统结构示意图(层状结构):

硬件和管理

先来了解一下对硬件的管理,硬件都是有自己的属性,属性是用来描述硬件的状态及一些相关信息,就像写的通讯录存储人的信息,不过只会存储需要的信息,比如姓名、年龄、电话等等。

拿鼠标来举例,我们在更换鼠标的时,链接上新鼠标,右下角就会提示正在安装驱动程序,过一段时间新鼠标才可以使用。因为不同的鼠标都有不同的厂商,属性是略有不同。操作系统不可能有所有鼠标的属性数据,所以这些硬件的数据就要有厂商来提供接口,让操作系统拿到数据并可以修改数据。这些接口就是驱动程序,操作系统使用驱动管理来对接驱动程序对硬件进行管理

linux操作系统是使用c来写的,对硬件属性的描述,就可以使用struct来封装。硬件的属性有相同的地方,如厂商、电流大小等,不同的有状态以及功能,只用有相同处就可以使用数据结构进行管理,假如这里是用list对硬件进行链接,那我们对硬件进行管理就是对list进行增删查改。这种方式同样的适合其他的管理,例如文件管理,我们对目录下的增删查改。所以操作系统内是有着大量的数据结构进行管理工作的。

总结一下:管理某些东西我们要先描述他们的属性,在将它们放到一起组织起来(例如数据结构)。管理 == 先描述,再组织

为什么要有操作系统

再回到鼠标,我们现在准备完cs2,但感觉鼠标太快了,查看鼠标属性发现DPI是1200。现在要将DPI改成800,我们只需要将1200的选项改为800,操作系统就会对鼠标进行修改。这个过程中操作系统和鼠标的关系是管理者和被管理者,我们和操作系统的关系是甲方和乙方。我们作为甲方是不懂如何管理被管理者,所以需要一个人(操作系统)帮我们管理被管理者,我们就只需要拿到被管理者的属性,想修改才什么告诉乙方就行。

可是乙方也知道我们不懂管理,我们要是随便修改数据,乙方后面还怎么管理?数据已经乱了,此时乙方拿了份合同让我们签了,上面有对我们的限制,不让我们直接去操作系统修改数据,必须使用操作系统的调用接口才能让安排它做事。

这个系统调用接口就是操作系统给的一些函数,让我们使用函数来使用操作系统。这对于会c语言和了解系统的人还能使用,可那些不会的人就不能了,所以就有了用户部分。用户操作系统提供了shell外壳、lib(c/c++标准库)和部分指令,用户提供了指令操作mkdir、touch、ll等,还有我们熟悉的window的图形化界面。

总结一下:我们现在在来看操作系统,它在计算机中有着承上启下的作用,向下对软硬件资源进行管理(手段),向上为用户提供了一个良好(稳定的,安全的,高效的)的运行环境(目的)。

三、进程的概念

我们在使用window打开浏览器、微信等软件,其实就是在执行一个exe的可执行文件,执行文件时就会创建一个进程来控制程序的运行。

当我们结束到文件所对应的进程,执行的文件也将会不在执行。

在Linux中也是同理,当我们运行一个可执行程序,它就会生成进程。

ps -axj:查看进程

ps -ajx查看的进程过多,可以使用 | grep [文件] 搭配查看。

上面可以看到./test.exe确实在进程里,下面的test.exe是grap的进程,之前说过指令本身也是可执行文件,只要是可执行文件在执行时都会有进程。

刚刚也看到了进程是可以同时存在多个的,操作系统自然要对进程进行管理(先描述,再组织),那是在什么时候创建的进程呢?

PCB:

进程信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合, 这个集合就是PCB。课本上称之为PCB(process control block)。在Linux中PCB被称为**tesk_struct,**它会被装载到RAM(内存)里并且包含着进程的信息.

我们上面已近了解了冯诺依曼体系,根据这个体系,要想运行程序,就要先将程序的数据和代码加载到内存当中再由,内存交给cpu让其计算。进程显然就是对这些程序的数据和代码进行处理,在它们加载到内存后,操作系统就要对它们进行管理,为每个程序创建一个PCB的结构体来描述,里面放着程序的所有属性,指向对应的代码和数据的指针,以及存放下一个进行的指针(假如用list来组织)。这时想让cpu运算哪个程序将它的PCB给cpu就可以了。

操作系统也是一款软件,它也要遵循冯诺一曼体系,电脑启动时就会加载到内存中,不过它是没有进程的。

总结一下:进程 == PCB+自己的代码和数据。Linux下就是tesk_struct+自己的代码和数据。

test_struct内容分类:

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

进程的删除和子进程的创建

删除

写一个死循环

Ctrl+c:在用户层面终止程序

kill -9 [pid]

**pid就是标识符,是tesk_struct的一员用来描述本进程的唯一标示符,区别其他进程。**在ps -ajx下可以看到。

运行程序,查看他的pid,ppid是他的父进程,每个进程都是由他的父进程创建的。

kill -9 22358,删除进程。

创建子进程

fork:创建一个子进程,当前程序是子进程就返回0,是父进程就返回子进程的pid.

getpid:查看当前进程的pid

getppid:查看当前进程的父进程pid

代码:

执行结果:

这个fork创建子进程会继承父进程从fork开始下面的所有代码,从上面的代码就可以看出,因为id值的不一样父子进程分别执行了不同结果的数据。

总结一下:fork创建的子进程是有自己的tesk_struct的(他有自己的pid),代码上是继承父进程fork以下包括fork那行的所有代码,数据上因为fork的返回值不同所以和父进程输出的结果是不一样的。

四、进程的状态

七种状态:

  • R:运行状态
  • S:浅度睡眠状态
  • D:深度睡眠状态
  • T/t:暂停状态
  • Z:退出状态
  • X:死亡状态

实验查看部分状态:

R:

代码:

查看运行test.c时进程的信息:

 while :; do ps ajx | head -1 && ps ajx | grep test.exe | grep -v grep; sleep 1; done

命令行执行上面的命令可以循环查看程序的进程,这里查看的是test.exe,修改test.exe就可以查看其他程序进程。

运行进程后cpu执行代码,它进入循环后一直在执行while,进程的PCB一直在cpu的队列中(每个cpu都有一个自己的队列,来让进程轮流调用cpu),这时这个进程就是R状态。+代表是前台运行,没有则是后台。

S:

代码:

运行时进程的信息:

这段代码使用了printf,cpu在执行printf时需要调用显示器的资源,进程在等待外设资源就绪时就是S状态。显示器是外设,外设的速度是比cpu慢许多的,所以在这进程运行的大部分时间都是在调用显示器资源,R状态只会停留很短的时间。

D:

D状态的场景是很难造的,这里就简单说明一下。

场景:一个进程在给磁盘写入1G的数据,这时操作系统发现内存严重不足,Linux操作系统有权杀掉进程来释放空间,它就将这个正在等待磁盘写入数据的进程杀掉了。磁盘写着写着数据发现进程没了,磁盘就不知道要怎么处理这些数据,可其他进程也要调用磁盘,磁盘就不会处理这些未写完的数据,这就造成了数据的丢失还暂用了空间。

操作系统为了解决这个问题就创建了D状态(深度睡眠,不可被系统杀掉),解除D状态只能等进程自己醒来(数据传完)或重启/断电。

T/t:

让进程暂停需要kill命令,kill是一个向进程发送信号的命令。

kill -l:查看所有信号

kill -19:暂停进程

kill -18:解除暂停

解除暂停后进程会成为后台进程,只能kill -9杀掉进程,Ctrl+c无法杀掉。

Z/X:

代码:

运行后杀掉子进程:

杀掉子进程发现子进程依旧存在,进入了Z状态。进程在被杀掉后会先清楚掉程序在内存中的代码和数据,test_struct不会被删除,它会生成退出信息等待父进程来读取,读取后再进入X状态清楚这个程序的test_struct。这个过程就像你让一个朋友帮你做了件事,他在做完后会告知你一声这件事完成的状态。

上图,杀掉子进程后,因为父进程在运行没有去读取子进程的退出信息,子进程就成了Z状态,这个进程也被称为僵尸进程。

僵尸进程的危害:当父进程死亡后,子进程变为僵尸进程就可能会一直存在,导致内存泄漏,因为没有父进程读取它。OS(操作系统)为了解决这个问题,就将没有父进程的子进程(也称孤儿进程)让1号进程(OS本身)领养。

在操作系统内部还细分了很多种状态:

这里只介绍运行、阻塞和阻塞挂起状态。

运行状态

运行状态就是R,只要进程进入cpu的队列中就是运行状态。上面查看S状态使用了while写了死循环,但cpu在跑进程时不可能因为遇到死循环就只跑这一个进程,所以这里的问题就是cpu是如何进行多个进程的同时调用?

时间片:进程的PCB内都有自己的调度信息,里面有个时间片,cpu会根据时间片让进程使用多长时间,时间到了重新进入queue排队。

但进程重新进入queue去调用cpu不可能让cpu从头再开始运行代码。这时就需要寄存器了,每个cpu内都有寄存器,用来存储进程调用cpu的状态,进程需要重新进入queue时,会保留上一次进入cpu结束时寄存器的内容,也就达到再次使用CPU可以延续上次使用状态的效果。(这是OS教材调度算法的一种,Linux不是这样调度的)。

CPU寄存器的信息也程为上下文数据,在进程的切换时最重要的就是保护上下文数据。要注意的是寄存器 != 寄存器内容,寄存器是硬件,寄存器内容是数据。

阻塞状态和阻塞挂起状态

阻塞:S和D状态都是等待外设的资源就绪,外设内也有自己的queue来让进程调用,进程等待外设就会将自己的task_struct放到外设的queue内,这时进程就是阻塞状态,调用完后外设再回到cpu的queue内变成运行状态。

挂起:磁盘在内有一块swap分区,当内存特别吃紧时,有的进程是阻塞状态,OS就会将这个进程的代码和数据放到分区中,结束阻塞状态时会将数据和代码拿回内存。代码和数据在分区时就是挂起状态,不过挂起通常是伴随阻塞状态一起的,被称为阻塞挂起状态。

相关推荐
冷曦_sole1 分钟前
linux-21 目录管理(一)mkdir命令,创建空目录
linux·运维·服务器
最后一个bug2 分钟前
STM32MP1linux根文件系统目录作用
linux·c语言·arm开发·单片机·嵌入式硬件
聚名网4 分钟前
服务器如何划分空间?
运维·服务器
卫生纸不够用21 分钟前
子Shell及Shell嵌套模式
linux·bash
world=hello34 分钟前
关于科研中使用linux服务器的集锦
linux·服务器
枫欢38 分钟前
将现有环境192.168.1.100中的svn迁移至新服务器192.168.1.4;
服务器·python·svn
华纳云IDC服务商39 分钟前
如何自动解决服务器弹性伸缩问题?
运维·服务器
Chloe.Zz1 小时前
Windows系统上创建Flask服务器
服务器
soragui1 小时前
【ChatGPT】OpenAI 如何使用流模式进行回答
linux·运维·游戏