在linux上进程是非常重要的知识点,今天我自我发表浅见。
当在linux上编译完毕一个源文件生成可执行程序,这个时候这可执行程序只能称为普通文件,还不能定义为进程,在加载在内存中后才可称为进程,那么我们可以把程序认为是进程吗?不是这样的,因为进程包含可执行程序,属于他们是属于包含关系,可以这样表示:进程>可执行程序
概念图所以进程是包含可执行程序但不等于可执行程序,而是等于可执行程序加上其他的一些东西。
进程是由程序控制块(PCB)、程序段、数据段组成。
PCB: 管理进程。
程序段:程序代码存放的位置。
数据段:程序运行时使用、产生的运算数据。如全局变量、局部变量、宏定义的常量就存放在数据段内。
这里我们先看个东西
惊奇的发现,在磁盘上的可执行程序比该进程在内存小,这是什么情况呢?
这里我们要知道,内存空间是有限的,加载到内存上的可执行程序并不是一股脑将所有在磁盘上的数据都加载到内存中,为了有效利用空间,那么在加载可执行程序数据的时候会甄别主要数据加载到内存中进行操作,比如二进制代码段等较为主要的信息,而比如文件上次修改时间,文件的对应用户权限信息,创建时间等等无关运行的数据都不会加载到内存中,这样进程的大小比可执行程序大小要小。
这样就解释通了为什么外存上的可执行程序比内存上的进程要大了
打个比方,在家里3个孩子,那个孩子学习好不需要搞个人员名单再去奖励他,而在学校里可能有几万名学生,让校长奖励最好的同学,如果没有人员名单数据信息的话,找到最好同学成绩也许只能等上几个月才能甄别了,PCB就像人员数据信息表一样,每个人都有属于自己的信息表,而每个进程都有属于自己的进程数据信息,这里面有代码有,标识符pid,记账信息,有任务状态,有上下文数据,内存指针,有指向其他PCB的指针等等
我们先了解CUP对进程的工作原理:
CUP访问进程的时候,并不是直接访问数据代码,而是访问PCB,就像校长找学生,都会看看他的基本信息根据信息里的电话号码打电话叫该学生过来而不是自己去一个一个查数据,这样的效率十分的低下。
我们将进程的基本数据汇总做个表格,表格里存放的是关于该进程的基本数据,这个表格就叫做进程控制块(PCB),里面保存了各种数据各种指针,所有CPU是通过PCB再去访问载入内存的代码,而不是直接访问载入内存的代码。
。我们有多个进程,就像有几万个人的数据表格,我们要把这些数据钉在一起,方便增删查改,而多个进程控制块也是一个道理,要将他们都关联起来,这个时候就衍生了数据结构这门课程。
这里我们假设全部PCB以双链表相互关联,这个时候CPU只需要找到链表的头节点就可以访问整个链表了
这样的数据结构就让cpu快速的遍历了所有的进程。
我们来介绍一下PCB中的一些重要的内容:标识符pid,记账信息,有上下文数据,内存指针,优先级信息
pid:如同身份证号码一样,在可执行程序加载内存中成为进程后,在PCB上都会有一个pid的数据,它具有唯一性,同时运行的进程pid都是绝对唯一的,哪怕创建子进程,子进程也是有自己的pid
记账信息:这里的记账信息记录可能包括,本次运行时间数据,以及以及运行的时间数据,以及运行时间限制,这里的时间限制可以查看我写的另一文章:(13条消息) 不让CPU偷懒_云的小站的博客-CSDN博客。这时保证了每个进程占用cpu资源的时间都公平合理。
内存指针:这个是记录着数据段,堆区,栈区,代码段,内存映射区等等的位置。
优先级:排队总是有先后,在进程中也有着先后顺序
程序计数器:程序即将被执行的下一条语句。
这里我们要重点理解什么是上下文数据
并不是上一个进程下一个进程的的数据,而是在当前进程切换前已经运行的数据信息,打个比方当前进程运行到了第200行,这个时候该进程切换到其他进程,这个时候我们需要已经运行到200行产生的数据,存放起来,应该存放在哪里呢?
如果存放在cpu中那么就要扩大3级缓存,寄存器的大小,如果是这样,那么有许多进程切换时候都需要将这些数据存放起来以方便下次使用CPU资源的时候可以立刻调到这些数据,但是如果存放在CPU资源那么将要增大 cpu附近存储硬件的大小,我们知道约靠近cpu的存储单位价格约昂贵,如果普通的人买个电脑光光是cpu就花费几万元,这是十分不明智的,所以上下文数据不该存放在CPU上。
如果放在其他进程内,如果其他进程在运行完后就结束进程了,这个时候会销毁里面的临时数据,如果保存了其他进程上次运行的数据将会一同销毁,如果该程序还未结束,再次分配cpu资源的时候将找不到上次运行的位置,将发生错误。
应当放在自己进程中,这样在下次分配资源的时候就可以立刻准确的找到自己上次运行到位置和相关数据信息了。
自己制造,自己带走