以Linux为例了解进程

在这里插入图片描述

  • 我最近开了几个专栏,诚信互三!
    ====> |||《算法专栏》::刷题教程来自网站《代码随想录》。|||
    ====> |||《C++专栏》::记录我学习C++的经历,看完你一定会有收获。|||
    ====> |||《Linux专栏》::记录我学习Linux的经历,看完你一定会有收获。|||
    ====> |||《C#专栏》::记录我复习C#的经历,深度理解查漏补缺,不定期更新。|||

什么是进程

根据教材介绍,进程被加载到内存上的程序,其实在进程被加载到内存上时,我们直接操作的不是进程所对应的内存空间,而是操作系统描述出的进程数据结构,被称为进程控制块(PCB),在Linux下,PCB(进程控制块)名为task_struct,所以进程根加易于理解的定义是:

进程 = 内核数据结构+运行在内存的可执行程序。

一个cpu只能运行一个进程,为了防止某个进程持续占据cpu,就出现了时间片概念

时间片:当进程被cpu运行的时间超过了某个值时,该进程会被直接退出。

“当前文件”再理解

在C语言中我们可以通过fopen函数来对文件进行操作,若我们已只写的方式打开文件,若该文件不存在,则会在”当前文件“下创建该文件,在C语言学习阶段,当前文件就被解释为源文件所在文件,在学习进程后,我们可以对当前文件进行详细解读。
在Linux下,每个进程都会在/proc目录下创建一个以进程pid命名的目录,在该目录中,展示了许多关于该进程的信息,其中存在一个cwd(当前工作目录)链接文件,该目录就是该进程所在的目录,我们可以修改该文件所指向目录。

系统函数chdir()。

所以所谓的当前文件其实就是进程所在的目录

Linux下与进程相关命令/系统函数

ps ajx,显示当前运行的所有进程。
kill [信号9] [进程pid],杀死标识符为pid进程。
系统函数pid_t fork(),创建一个子进程,进程创建后,代码共享。

Linux下如何创建/删除系统函数解释

系统函数fork(),会返回一个pid,对于父进程来说,fork返回子进程的pid,对于子进程开说,fork返回0。

1.对于父进程返回子进程的pid的原因是因为一个父进程可以有多个子进程,返回子进程的pid用于判别各个不同的子进程,而一个子进程只能有一个父进程,所以不用判别子进程属于哪个父进程。
2.fork能返回2个值的原因是因为,在fork内子进程就被创建完成了,之后的所有代码父子进程共享,所以能返回2个值。
3.创建子进程的本质其实是基本拷贝了父进程的进程数据内核,并且该内核依旧指向父进程的可执行程序。

kill
进程与进程之间是相互独立的,在杀掉子进程/父进程都不会影响其父进程/子进程。

进程属性及解释

PBC的属性有很多,如标识符,状态,优先级,程序计数器,io状态信息,内存指针,记账信息,上下文数据,主要介绍几个。

标识符

标识符(pid)是用来确定唯一的进程的一个整数,fork函数的返回值就是返回一个进程的标识符。

状态

进程一般有三种状态,运行,阻塞,挂起,这是操作系统层面的名字,在不同的操作系统中有些许不同,但都可以归为上述三种。
运行状态: 及某个进程被加入到cpu运行队列,单个cpu只能单词运行一个进程。
阻塞状态: 当进程需要某些信息时,进程则会被链到非cpu运行队列的队列中,及需要某种资源,则此状态被称为挂起状态。
挂起状态: 挂起状态比较罕见,若进程占用cpu的时间超过了时间片的时间,且当前内存压力较大,则该进程则会被拷贝到磁盘中,此状态被称为挂起状态。

运行状态的调度与执行(Linux为例)

Linux中使用一个字符指针数组来维护各种状态,Linux中的状态有。

R,S,D(深度睡眠),T(暂停),t(追踪暂停),z,x
在这里插入图片描述

R状态对应于运行,S,D,T,t这几种状态都可以归为阻塞状态,及需要某种资源,而z和x一个是僵尸状态,一个是进程的死亡状态,z状态是x状态的前导。


虽然父子进程在执行上没有关系,但是子进程要受到父进程的管理z状态就是因为父进程没有在子进程运行完后读取子进程的pcb数据,若子进程的父进程被销毁,则该子进程就变为了孤儿进程,孤儿进程会自动被操作系统所管理。

调度与执行

在解释Linux中的调度与执行前先要了解一些概念
1.进程之间是由竞争的,并且进程与进程之间执行是独立的。
2.并行:多个cpu去执行进程被称为并行。
3.并发:指单个cpu执行多个进程通过某种方法让多个进程可以多路运行。

对于计算机而言,任何资源都是有限的,所以就有了优先级的概念。

进程被分成了实时进程普通进程,他们都有自己的优先级,实时进程的优先级大于普通进程的,Linux中将实时进程的优先级分成了100个,普通进程分成了40个。
普通进程的优先级被一个变量PRI表示范围在[60-99]之间,优先级数值越小,优先级越大,但是我们在改变普通进程的优先级时改变的不是PRI值而是另一个变量nice[-20,19],PRI = PRI(old) + nice,而PRI(old)则是该进程的默认优先级,对于普通进程而言,默认优先级都是80。

对于计算机而言,我们希望所有的进程都可以获得计算机的资源,所以优先级不易设置的差距过大,导致某些进程无法享受到计算机资源。


有了优先级的补充,我们就可以更好的理解cpu对进程的调度过程。
cpu自己会维护一个运行队列runqueue,运行队列中最重要的组成部分如下图所示,我将讲解这些部分的作用,体会Linux系统进程调度的设计逻辑与思路。
在这里插入图片描述
运行队列中最重要的就是蓝框部分和红框部分,以及active指针和expried指针这2个指针分别指向运行队列和过期队列。,蓝,红框部分是由一个数组来维护的,一个叫运行队列,一个叫过期队列,queue[140]就是链接进程的,从0-140,0-99是实时进程,100个优先级,100-139是普通进程40个优先级。每个优先级队列都与进程的优先级有关。bitmap是一个哈希表,为了能在queue中快速查找非空优先级队列,bitmap是以每一比特位的0/1代表是否为空,由位数代表是那个优先级队列,nr_active代表进程的数量。
运行队列中只运行进程,其他新加入的进程/时间片消耗干净的进程会被维护在过期队列中,所以运行队列的进程一直在减少,而过期队列中的进程一直在增加,当运行队列中的进程全部结束时,则交换active和expried指针的值,让过期队列变为运行队列,运行队列变为过期队列。

上述方法的时间复杂度只有O(1),十分高效这就时Linux如何实现进程调度的。


进程的执行是在cpu中,cpu中有许多寄存器,它们有不同的功能,而与进程执行相关的寄存器是eip也就是pc指针。
当某一普通进程进程的时间片消耗完后,操作系统会将cpu中寄存器的值拷贝给该进程,以记录当前该进程的状态,同时pc指针指向下一个进程,下一个进程的记录会覆盖寄存器中的值,所以寄存器中只有当前进程的数据记录, 这个过程非常快,以至于在我们眼中所有的进程都是一起运行的。

程序计数器

cpu中存在多个寄存器,与程序计数相关的寄存器位eip/pc寄存器,当pc寄存器指向个进程,就代表某个进程当前正在被执行,而该寄存器中记录的是当前执行的指令的下一条指令。
在语言中,所谓的循环,条件判断,函数跳转,本质都是修改了pc寄存器。

  • 11
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值