cpu是一个只可以执行指令,不是cpu要打印而是我们要打印,然后编译成指令再给cpu,再通过操作系统进行操手
进程状态:
为什么会有这些状态?
进程的多状态,本质都是为了满足未来不同的运行场景
有那些状态?
运行 新建 就绪 挂起 阻塞 等待 停止 挂机 死亡 .......
1、普遍的操作系统的层面如何理解上面的概念
在cpu内核中有一个cpu还有一个运行队列,在磁盘上的可执行文件加载到内存中成为进程,其实本质是将可执行文件的代码和地址加载到内存中CPU为了方便管理将其封装成 PCD(process conduct block){//进程属性 // 可执行程序的代码和地址} ,这些进程控制块是由cpu中的运行队列(runqueue)管理
OS系 统的宏观概念图
运行状态:不是在cpu中运行才叫状态,只要在运行队列中就叫状态了,因为cpu的计算很快,所以进入到runqueue就叫运行状态
结论:
看下方的图:
如果有一个进程Fwrite在cpu里,这个进程是要磁盘写入
解释:cpu的运行状态是R,磁盘的状态不是R,是阻塞
cpu的速度很快,要等待磁盘启动,所以进程要等待硬件资源会进入阻塞状态
根据冯诺依曼体系cpu运行的快,硬件慢,是如何平衡的呢?
硬件也有对应的硬件结构体
虽然磁盘很慢,但是进程或多或少都要访问,而且硬件的数量很少(只有一次磁盘),当磁盘的中已经有进程了,cpu在处理进程Fwrite时,是要等待吗?不是,因为cpu很快,不可能会等一个进程的,而是将Fwrite进程pcd链接到磁盘中的wait_queue中等待,将R状态改为阻塞状态,当磁盘中的进程运行完了,到Fwrite时,磁盘会告诉操作系统,再将Fwrite pcd从磁盘中的等待队列wait_queue中添加链接到cpu的运行队列中等待执行
那下一次执行一定是fwrite pcd吗?
是的,磁盘执行的一定是fwrite,为什么因为cpu运算比硬件快很多,会很快将所有进程进行执行,如果出现阻塞,就是该硬件已经有进程调用时,会进入阻塞状态添加进该进程的等待队列,当有空闲时会通知操作系统,将队列(先进先出)的第一个进程加入到cpu的运行队列进行执行
阻塞状态就是某种进程等待某硬件资源
挂起状态:
当进程阻塞时,且内存空间已经满了,OS系统会帮我们节约内存的空间所以就会将阻塞进程加载进来一部分,加载到磁盘的某一个空间上保存着,这个叫内存数据的换入换出,但是该pcd还在内存中的硬件的等待队列(因为是阻塞等待某个硬件资源,反证知道pcd还在内存中不是释放了)此时的pcd为挂起状态,当到该进程运行时会将那一部分的数据加载回来。
阻塞vs挂起
阻塞不一定是挂起,挂起一定是阻塞
-----------------------------------------------------------------------以上是宏观的----------------------------------------
Linux是如何做的呢?
准备实验:
运行:
这就是Linux进程的R状态
----=========================================================================
s (休眠) 阻塞状态一种
其实Linux的sleep状态就是上面所说的阻塞状态,因为要调用printf要访问到外设,外设是属于硬件,cpu计算很快,硬件很慢,这个进程一直要访问外设,所以要等待外设IO,一直调用显示屏外设对应的硬件在cpu的运行队列和硬件中的等待队列中来回移动,所以Linux系统会将其为s(阻塞)
99%的时间是等待外设,1%计算
=========================================================================
暂停状态
已经学过kill -9 杀死进程
现在学习第18和19 进程继续和进程暂停
T状态会导致前台进程变成后台进程
可以由ctrl + c结束进程
无法Ctrl+c结束进程,需要手动 kill -9 【编号】
挂起状态是os内部处理的,是看不到的
D状态:深度睡眠
在高IO的状态下才会产生,
另外一种睡眠状态是uninterruptible sleep,处在这种状态的进程不接受外来的任何信号,这也是为什么之前我无法用kill杀掉这些处于D状态的进程,无论是”kill”, “kill -9″还是”kill -15″,因为它们压根儿就不受这些信号的支配。
进程为什么会被置于uninterruptible sleep状态呢?处于uninterruptible sleep状态的进程通常是在等待IO,比如磁盘IO,网络IO,其他外设IO,如果进程正在等待的IO在较长的时间内都没有响应,那么就很会不幸地被 ps看到了,同时也就意味着很有可能有IO出了问题,可能是外设本身出了故障,也可能是比如挂载的远程文件系统已经不可访问了,我这里遇到的问题就是由互斥锁引起的,比如说我开了8个进程同时访问一个io,访问的时候势必会加锁来保护资源,那么,当一个进程正在访问的时候,其他进程如果在等待锁,那么就会进入disk sleep,当你执行kill,它不会立即响应,当锁满足条件的时候才可能响应信号。
引用Linux进程睡眠状态disk sleep-CSDN博客
DD命令
———————————————————————————————————————————
在进程的生命周期中,有些进程是属于计算密集型的,非常依赖cpu资源,所以一般都是R状态。
有些进程是io密集型的,在和外设基础如写的printf cin cout 文件级别的访问文件,这些进程一瞬间就跑完了,都是在等待外设资源,所以一般都是s(休眠)就是阻塞
t状态
t也是暂停tracing stop,是进程停下来等待你的指令,进行下一步操作
z状态:僵尸进程
感性认识:
进程被创建出来就是为了完成任务,1.要知道它完成的如何? 2.可以不关心结果,但是不可以没有结果
z状态:进程退出时,不能立即释放该进程对应程序对应的资源!保存一段时间,让父进程或者OS进行读取
简单来说就是进程退出了,但是没有被回收(父进程/OS)--》创建子进程,让父进程不要退出,而且什么都不做,让子进程正常退出
一个进程被释放,只是进程的数据和代码被释放了,但是pcb对象的信息没有被释放等待父进程进行回收
所以不回收僵尸进程就会造成内存泄漏
所以状态先变成z然后瞬间变成x(dead)
进程的危害:
孤儿进程:
while : ; do ps axj | ps axj && head -1 | grep (myprocess 要筛选的进程名) | grep -v grep sleep 1 (睡眠1秒); done
//循环查看进程
()为解释
为什么父进程被杀了没有变成僵尸进程z?
因为父进程还有父进程,别人的父进程回收了pcb对象的资源
人家的父进程负责。
2、编号为1的进程是什么?
systemd是系统是bash是编号为1的进程
父进程肯定有情况是比子进程先挂掉的情况
进程优先级:
1、什么叫做优先级
其实就是权限,决定先执行还是后执行的问题
2、为什么会存在优先级?
因为资源太少
3、Linux优先级特点
很快,其实优先级的本质就是pcb里面的一个整数数字(eg:1、2、3)
Linux中的权限就是PRI其实就是priority优先权
NI表示的单词是nice 范围【-20,19】nice是有上限的为了防止进程过度抢占cpu的资源
新权限=PRI + NI决定的(注意:每一次改nice的值都会将PRI都是从80开始的)
观察上图发现PRI的初始都是80
在shell命令行输入sudo top
然后后输入r进入下面界面
输入要修改的进程id然后就可以修改NI的值
进程的其他概念:
进程切换
cpu上有一套寄存器(不是一个,有很多,知道分为用户可见和不可见),知道寄存器可以存储数据就可以了。
有一个进程,它是保存着pcb的地址,所以它可以找到该pcb的数据和代码
有一个寄存器叫 【PC:Program Counter,有些叫eip是通用寄存器,但是有特殊用途,用来指向当前运行指令的下一条指令】
PC指针和SP指针-CSDN博客
那些突然想到的问题---EIP和PC的区别_cpu中的eip寄存器-CSDN博客
cpu永远在做三件事 取指令、分析指令、执行指令
注意:在调用函数时,函数内定义的变量是随着函数的结束而结束的,函数内变量的值是通过cpu的寄存器来保存临时变量的值,通过寄存器完成传递
当进程被剥离时,保存自己的临时数据到自己的进程里时,叫上下文保护,因为下一次还要运行,然后重新排队
当再次回到cpu时,将保存的数据恢复,叫上下文恢复,继续运行,这个过程就完成了一次进程切换
这个数据是cpu寄存器内的数据不是寄存器
环境变量:
可以,就是命令就是一种指令
为什么都是可执行程序,为什么自己写的可执行要带路径?如:./myprocess
为什么ls它们不要呢?
因为要执行一个程序就要先找到这个程序,所以我们的程序要带 . / 这个是当前路径的意思,要找到相对路径。
那系统中的程序如ls、ll、、、、这些不用路径吗?这些也需要路径,只是系统已经配置好这些路径了
/usr/bin 系统默认指定安装路径
那将我们写的可执行的程序复制到/usr/bin下,不带路径运行,但是不推荐,因为我们写的程序并没有测试,会污染系统默认的指定池
sudo cp myprocess /usr/bin/
$PATH:系统默认搜索路径
在每一个冒号后面进行检索,路径中存在程序就可以执行
所以我们可以将我们写的程序的路径写入&PATH
export 导入环境变量的指令
export PATH=/home/test_110/106/lesson13 //不要这样写,这样写会将原来PATH中的路径都覆盖掉了
export PATH=&PATH:/home/test_110/106/lesson13 //正确写法
我们系统的指令为什么可以被找到因为环境变量path里默认就带了系统的默认路径搜索
如:which底层实现就是用path去找一个一个的指令路路径
env //可以查看所有的环境变量