Linux—进程学习-01

目录

Linux---进程学习---1

1.冯诺依曼体系结构

冯·诺依曼提出了电子计算机系统制造的三个基本原则,即采用二进制逻辑、程序存储执行以及电子计算机系统由五个部分组成(运算器控制器存储器输入设备输出设备,其中运算器与控制器又共同组成为中央处理器CPU),这套理论被称为冯·诺依曼体系结构。

我们常见的计算机,如笔记本。我们不常见的计算机,如服务器,大部分都遵守冯诺依曼体系

截至目前,我们所认识的计算机,都是有一个个的硬件组件组成

输入单元:包括键盘, 鼠标,扫描仪, 写板等

中央处理器(CPU):含有运算器和控制器等

输出单元:显示器,打印机等

关于冯诺依曼,必须注意几点

存储器指的是内存!,一定要注意!

磁盘和硬盘既可以是输入设备也可以是输出设备

不考虑缓存情况,这里的CPU能且只能对内存进行读写,不能访问外设(输入或输出设备)

外设(输入或输出设备)要输入或者输出数据,也只能写入内存或者从内存中读取。

总结一句话,所有设备都只能直接和内存打交道

**对冯诺依曼的理解,不能停留在概念上,要深入到对软件数据流理解上。比如:从你登录上qq开始和某位朋友聊天开始,数据的流动过程。**从你打开窗口,开始给他发消息,到他的到消息之后的数据流动过程。如果是在qq上发送文件呢?

那发文件呢?

其实也是一样的,只不过输入设备不在是键盘,而是磁盘 ,因为文件是存储在本地的磁盘中的,将文件从磁盘传输到内存,经过cpu处理之后,传输给网卡和显示器等输出设备,网卡通过网络将文件数据传输到另外一个用户的输入设备---网卡上,然后再加载到内存中,经过cpu的处理之后,传输给输出设备显示器。[此时用户一般可以选择下载到本地,即将文件从内存中传输到输出设备---磁盘上]

2.操作系统

2.1操作系统的概念

操作系统的概念:

任何计算机系统都包含一个基本的程序集合,称为操作系统(OS)。笼统的理解,操作系统包括:

  1. 内核(进程管理,内存管理,文件管理,驱动管理)

  2. 其他程序(例如函数库,shell程序等等)

操作系统的本质就是一个对软硬件资源进行管理的软件

2.2操作系统的目的

其目的就是:

  • 通过对软硬件资源的合理的管理(手段),给用户创造一个良好的(稳定的,高效的,安全的)运行环境(目的)

2.3如何理解管理

操作系统是管理者,那谁是被管理者------其实是软硬件资源,下面是一个图,方便理解。

对于操作系统是如何对软硬件进行管理的理解图,有一个例子可以方便理解:

就像校长就是学生的管理者,校长不需要去接触每个具体的学生,但是仍然能够对学生进行管理,就是通过拿到学生的所有具体的数据,以数据的变化为依据,进行对学生进行管理的重大决策。

经过上图的理解,可以总结出------管理的本质就是对数据继续管理

那管理者是如何不断的拿到被管理者的数据,并根据数据的变化来下达相应的决策,对被管理者进行管理的呢?

这中间就还需要引出一个执行者的概念。

如果是在学校里,执行者可以是辅导员,可以是班长等其他位置,这里就当做辅导员。

如果是在操作系统中,若被管理者是硬件,那么执行者就是驱动

管理者(OS/校长)具体来说是如何管理被管理者的呢?

所有的管理本质的逻辑都是------先描述、再组织【也就是面向对象思维】

将被管理者的数据描述成一个类,然后再将类的对象用数据结构组织起来【将一个个类的对象用某个数据结构存储起来】,通过这个数据结构的一些算法【比如找到增删查改】来对数据进行管理

总结

计算机管理硬件

  1. 描述起来,用struct结构体

  2. 组织起来,用链表或其他高效的数据结构

2.4计算机软硬件体系的理解

此时有一个问题:**操作系统是不相信用户的,它不会将自己底层的进程管理、文件管理等、以及底层管理的数据开放给用户进行访问。**不然用户如果操作错误,就会导致操作系统崩溃。但是操作系统又需要给用户提供各种服务。不然用户怎么知道自己的硬件是什么情况呢?自己的文件什么情况等。

因此操作系统给用户提供了许许多多的接口来给用户使用。比如用户想往磁盘中存储一些数据,用户是不能自己往磁盘输入数据的,只能将这个申请提交给操作系统的接口,经过操作系统的判断之后,才会往磁盘输入数据。

就像我们不能直接拿钱去将钱存到银行的仓库中,只能交由银行的人员来完成这个操作一样

上面提到的这个操作系统的接口一般叫做系统调用

如果是Linux系统的系统调用,其实就是调用c式的接口、因为Linux系统是由C写的,也就是说系统调用其实就是OS提供的一个C语音编写的函数的调用

但是如果让用户直接去使用系统调用的话,也是不太好的,因为这要求用户对操作系统有一定的了解,不然是无法使用的、因此就会有一些上层的软件,比如指令操作(shell)和编程操作(c/c++)、来帮我们使用系统调用

下面是举例:

在shell中,我们输入ls或者touch等指令,其实都是通过调用shell的接口,这个接口和系统调用会有关系,因此最终还是在调用系统接口来完成对硬件的访问。比如ls就是将这个文件的内容全部输入,那不就需要读取磁盘内的空间并输出到显示器吗,touch指令也需要在磁盘中创建一个空间用于存放新建文件。这需要向磁盘空间输入数据,最终也是系统调用完成的工作、

在写c/c++代码的时候,printf和cout是调用库函数,库函数内部会有系统调用。最终仍然是通过系统调用实现的向显示器(硬件)输出

对于上面描述的计算机软硬件体系可以用一个图片来总结:

这里最底层的硬件需要了解冯诺依曼体系结构、

驱动程序是执行者,它执行操作系统的管理决策,并将硬件的数据变动交给操作系统,便于操作系统管理、

操作系统会将驱动程序先描述成一个类,并用如链表的数据结构将其组织起来、方便做出一个个对外界提供服务的系统接口、也就是系统调用

而在我们写代码或者输入指令的时候,涉及对硬件的访问,都是通过库函数来帮助我们使用系统调用,进而访问硬件、

2.5系统调用和库函数的概念

在开发角度,操作系统对外会表现为一个整体,但是会暴露自己的部分接口,供上层开发使用,这部分由操作系统提供的接口,叫做系统调用

系统调用在使用上,功能比较基础,对用户的要求相对也比较高,所以,有心的开发者可以对部分系统调用进行适度封装,从而形成库,有了库,就很有利于更上层用户或者开发者进行二次开发。

3.进程

3.1进程是什么

进程------一个被加载到内存的程序

内核观点:担当分配系统资源(CPU时间,内存)的实体。

3.2管理进程

首先程序是一个文件,因此,程序想要被运行,根据冯诺依曼体系结构,存储程序的文件必须要被加载到内存中。然后再被cpu计算,运行程序。但是很多时候,被加载到内存上的程序非常多、

这个时候被加载到内存上的程序非常多,此时就会有很多问题,先运行那个程序?程序的在内存的位置如何分配?那些程序执行过?那些程序没有执行过?有些执行完的程序要销毁释放,有些程序需要多执行几次等等问题。

因此操作系统为了更好的管理这些被加载到内存的大量程序文件,就将加载到内存的程序称作进程,然后管理这些进程。如何管理呢?

前面说了,管理的逻辑就是先描述、再组织。

因此操作系统对进程的管理自然也需要先描述、再组织

3.2.1描述进程-PCB

要相对进程进行管理,需要先将进程描述起来。如何描述呢?

在描述的时候,需要将进程其描述成一个类或者结构体。这个类和结构体中存放着进程的所有属性。

操作系统会用PCB来描述进程

  • 进程信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合。

  • 进程控制块称之为PCB(process control block),Linux操作系统下的PCB是: task_struct

其实在Linux下的进程控制块(PCB)就是一个结构体,这个结构体放着进程的所有属性【比如进程的id,进程的优先级,进程的状态,进程的地址、以及各自属性等等】

要注意:这里所说的进程的属性,都是操作系统自己添加的,原本被加载到内存的可执行代码文件是没有这些进程属性的,它只有自己写的代码和数据逻辑

因此每一个可执行程序被加载到内存的时候,操作系统都会将其作为进程并将该进程的所有属性放到PCB中。

将进程描述成PCB之后,就要将PCB组织起来,方便管理

3.2.2组织进程

当内存中有多个进程的时候,就会存在多个进程控制块(PCB),操作系统就会将其用数据结构联系起来,将多个进程控制块用链表之类的数据结构联系起来。这样就实现了组织

这样组织起来了之后,如果cpu需要找到优先级最高的进程来执行,就只需要遍历进程控制块(PCB)的链表,找到优先级最高的进程,并执行就可以了。

如果进程执行完毕需要删除释放,只需要遍历PCB的链表,找到状态为死亡的进程,然后将其代码从内存释放出去,然后删除对应的PCB即可。

3.2.3总结

操作系统对进程管理,不是对进程本身进行管理,而是对进程控制块(PCB)进行管理、

如果是用链表将PCB组织起来,那么对进程管理就转化成了对链表的增删查

内核数据结构 用数据结构将内核结构体(task_struct)组织起来 -> 内核结构体 struct task_struct -> 内核对象 task_struct的对象->将该结构和你的代码和数据关联起来 ->先描述,在组织的工作
进程 = 内核数据结构(task_struct) + 进程对应的磁盘代码

linux内核的部分PCB(task_struct)的源代码:

这个结构体有300多行。比我在linux写的代码都多了

3.3查看进程

  • 大多数进程信息可以使用top和ps这些用户级工具来获取

下面是个例子,当ProCessOn代码正在执行的时候,可以输入ps ajx | grep 'ProCessOn'来抓取这个进程是否存在

如果想让抓取的进程的信息带上标题可以输入ps ajx | head -1 && ps ajx | grep "ProCessOn"

  • 进程的信息可以通过 /proc 系统文件夹查看

输入ls /proc

如果要获取PID为1的进程信息,需要查看 /proc/1 这个文件夹。

注意:

通过/proc来查看进程,这是一个内存级别的目录,可以显示当前正在运行的所有进程的pid,如果一个新的进程被创建,pid号是24641,那么在/proc目录也会出现一个24641的目录,可以进行查看,里面会有该进程的属性信息、

4.与进程有关的系统调用

  • getpid()

这个是c语言自带的接口,可以实现系统调用,拿到当前进程的pid

pid_t其实就是一个整形类型,按照整形使用即可

这里我写了个死循环程序

执行结果如下:

在另外一个窗口抓取进程

如果想要杀死进程,就输入kill -9 进程pid即可

  • getppid()

这个的作用就是获取父进程的pid

当我们运行多几次程序我们就会发现,进程本身是会变的,因为每次被加载到内存,操作系统都会为该进程重新分配pid。

但是父进程是不会变得,我们抓取一下这个父进程pid就知道了

可以看到父进程本身是bash,也就是shell本身

如果将该进程kill掉,那么就会直接退出这个命令行解释器。

  • 在命令行上运行的所有程序,其都是子进程,父进程一般情况下都是bash

这样有个好处,子进程有问题不会影响到父进程,父进程可以安全的运行下去

现在又有了一个新的问题,子进程是如何创建出来的,又是如何运行起来的呢?

等到学习进程控制就会明白了。

相关推荐
Dlwyz3 分钟前
问题: redis-高并发场景下如何保证缓存数据与数据库的最终一致性
数据库·redis·缓存
岳不谢13 分钟前
VPN技术-VPN简介学习笔记
网络·笔记·学习·华为
编程修仙19 分钟前
Collections工具类
linux·windows·python
海害嗨26 分钟前
阿里巴巴官方「SpringCloudAlibaba全彩学习手册」限时开源!
学习·开源
芝麻团坚果35 分钟前
对subprocess启动的子进程使用VSCode python debugger
linux·ide·python·subprocess·vscode debugger
写点什么啦42 分钟前
[debug]不同的window连接ubuntu的vscode后无法正常加载kernel
linux·vscode·ubuntu·debug
wellnw1 小时前
[ubuntu]编译共享内存读取出现read.c:(.text+0x1a): undefined reference to `shm_open‘问题解决方案
linux·ubuntu
如意机反光镜裸1 小时前
如何快速将Excel数据导入到SQL Server数据库
数据库
不爱学习的YY酱1 小时前
【操作系统不挂科】<CPU调度(13)>选择题(带答案与解析)
java·linux·前端·算法·操作系统
DC_BLOG1 小时前
Linux-Nginx虚拟主机
linux·运维·nginx