Linux(进程)
- 1. 冯诺依曼结构体系
- 2 . 操作系统(OS)
- 3.进程
- task_ struct内容分类
- 查看进程
- 查看PID以及PPID
- fork()
- Linux操作系统进程的状态
- 僵尸进程
- 孤儿进程
- 进程优先级
- 其他概念
1. 冯诺依曼结构体系
冯·诺依曼结构也称普林斯顿结构,是一种将程序指令存储器和数据存储器合并在一起的存储器结构。程序指令存储地址和数据存储地址指向同一个存储器的不同物理位置,因此程序指令和数据的宽度相同。
特点:
现代计算机发展所遵循的基本结构形式始终是冯·诺依曼机结构。这种结构特点是“程序存储,共享数据,顺序执行”,需要 CPU 从存储器取出指令和数据进行相应的计算。 主要特点有:
(1)单处理机结构,机器以运算器为中心;
(2)采用程序存储思想;
(3)指令和数据一样可以参与运算;
(4) 数据以二进制表示;
(5)将软件和硬件完全分离;
(6) 指令由操作码和操作数组成;
(7)指令顺序执行。
存储器就相当于内存,而输入设备就例如:键盘,摄像头,话筒,磁盘…输出设备例如:显示器,磁盘,音响…中央处理器(CPU):包含运算器,控制器等。
- 那么为什么会有冯诺依曼结构体系呢?
在操作系统中,每个部分对于数据处理效率是不一样的:CPU > 内存 > 磁盘 > 光盘 > 磁带;CPU是不会直接和外设进行交互的,这样就会拖慢效率,就像木桶效应一样,永远是以最低的缺口为标准,CPU要处理数据,就需要将外设的数据加载到内存当中,然后CPU再从内存中读取。
2 . 操作系统(OS)
任何计算机系统都包含一个基本的程序集合,称为操作系统(OS),笼统的理解,操作系统包括:
内核(进程管理,内存管理,文件管理,驱动管理)。
其他程序(例如函数库,shell程序等等)。
操作系统存在的目的就是给用户提供一个稳定,安全,简单的执行环境。因为用户是不可能直接对某些程序进行访问的,不安全也过于复杂,操作系统就很好的解决了这些问题。
3.进程
进程 = 对应的代码和数据 + 对应的PCB结构体,在Linux系统下运行一条命令,./XXX的时候就是在系统层面创建了一个进程,Linux下管理进程的方法:先描述,在组织。
PCB(进程控制块):进程的属性被存放在PCB 中。
在Linux下描述进程的结构体(PCB)叫task_struct,task_struct是Linux内核的一种数据结构,它会被装载到RAM(内存)里并且包含着进程的信息。
task_ struct内容分类
标示符: 描述本进程的唯一标示符,用来区别其他进程。
状态: 任务状态,退出代码,退出信号等。
优先级: 相对于其他进程的优先级。
程序计数器: 程序中即将被执行的下一条指令的地址。
内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针
上下文数据: 进程执行时处理器的寄存器中的数据[休学例子,要加图CPU,寄存器]。
I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。
其他信息
查看进程
这些数字其实是某一进程的PID,对应文件夹当中记录着对应进程的各种信息。我们若想查看PID为1的进程的进程信息,则查看名字为1的文件夹即可。
使用ps命令可以查看所有进程信息:
查看某一个进程的信息:
查看PID以及PPID
fork()
fork有两个返回值,给子进程返回0,给父进程返回子进程的pid,fork之后,代码是父子共享的,需要注意的是,父子进程虽然代码共享,但是父子进程的数据各自开辟空间(采用写时拷贝)。在fork内部,父子会各自执行自己的return语句,子进程的内部属性是以父进程为模板的:
注意:使用fork函数创建子进程后就有了两个进程,这两个进程被操作系统调度的顺序是不确定的,这取决于操作系统调度算法的具体实现。
Linux操作系统进程的状态
- 新建:字面意思,发生是一瞬间的事情
- 运行:task_struct结构体在运行队列中排队,叫做运行态。
- 阻塞:等待非CPU资源就绪,阻塞状态。
- 挂起:当内存不足的时候,OS通过适当的置换将进程的代码和数据到磁盘,这就是挂起状态。
- R运行状态(running): 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。
- S睡眠状态(sleeping): 意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠(interruptible sleep))。
我们可以杀掉该进程:
- D磁盘休眠状态(Disk sleep)有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。一个进程处于深度睡眠状态(disksleep),表示该进程不会被杀掉,即便是操作系统也不行,只有该进程自动唤醒才可以恢复。
例如:某一进程要求对磁盘进行写入操作,那么在磁盘进行写入期间,该进程就处于深度睡眠状态,是不会被杀掉的,因为该进程需要等待磁盘的回复(是否写入成功)以做出相应的应答。(磁盘休眠状态)
- T停止状态(stopped): 可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行。
在发送命令该进程又可继续执行:
- X死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里看到这个状态。
僵尸进程
- 僵死状态(Zombies)是一个比较特殊的状态。当进程退出并且父进程(使用wait()系统调用)没有读取到子进程退出的返回代码时就会产生僵死(尸)进程。
- 僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。
- 所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态
僵尸进程的危害
- 僵尸进程的退出状态必须一直维持下去,因为它要告诉其父进程相应的退出信息。可是父进程一直不读取,那么子进程也就一直处于僵尸状态。
- 僵尸进程的退出信息被保存在task_struct(PCB)中,僵尸状态一直不退出,那么PCB就一直需要进行维护。
- 若是一个父进程创建了很多子进程,但都不进行回收,那么就会造成资源浪费,因为数据结构对象本身就要占用内存。
- 僵尸进程申请的资源无法进行回收,那么僵尸进程越多,实际可用的资源就越少,也就是说,僵尸进程会导致内存泄漏。
孤儿进程
父进程先退出,那么将来子进程进入僵尸状态时就没有父进程对其进行处理,此时该子进程就称之为孤儿进程。当出现孤儿进程的时候,孤儿进程会被1号init进程领养,此后当孤儿进程进入僵尸状态时就由int进程进行处理回收。
进程优先级
什么是进程的优先级?
优先级实际上就是获取某种资源的先后顺序,而进程优先级实际上就是进程获取CPU资源分配的先后顺序,就是指进程的优先权(priority),优先权高的进程有优先执行的权力。
优先级存在的原因?
优先级存在的主要原因就是资源是有限的,而存在进程优先级的主要原因就是CPU资源是有限的,一个CPU一次只能跑一个进程,而进程是可以有多个的,所以需要存在进程优先级,来确定进程获取CPU资源的先后顺序。
- UID : 代表执行者的身份。
- PID : 代表这个进程的代号。
- PPID :代表这个进程是由哪个进程发展衍生而来的,亦即父进程的代号。
- PRI :代表这个进程可被执行的优先级,其值越小越早被执行。
- NI :代表这个进程的nice值。
PRI and NI
-
PRI也还是比较好理解的,即进程的优先级,或者通俗点说就是程序被CPU执行的先后顺序,此值越小进程的优先级别越高。
-
NI就是我们所要说的nice值了,其表示进程可被执行的优先级的修正数值。
-
PRI值越小越快被执行,那么加入nice值后,将会使得PRI变为:PRI(new)=PRI(old)+nice。
-
这样,当nice值为负值的时候,那么该程序将会优先级值将变小,即其优先级会变高,则其越快被执行所以,调整进程优先级,在Linux下,就是调整进程nice值。
-
nice其取值范围是-20至19,一共40个级别。
需要强调一点的是,进程的nice值不是进程的优先级,他们不是一个概念,但是进程nice值会影响到进程的优先级变化。可以理解nice值是进程优先级的修正修正数据。
查看进程优先级信息
用top命令更改已存在进程的nice
输入top命令,动态显示进程资源占用内存的情况:
使用top命令后按“r”键,会要求你输入待调整nice值的进程的PID:
输入进程PID并回车后,会要求你输入调整后的nice值:
在这儿我们输入20,最终PRI就会变成99:
其他概念
- 竞争性:系统进程数目众多,而CPU资源只有少量,甚至1个,所以进程之间是具有竞争属性的。为了高效完成任务,更合理竞争相关资源,便具有了优先级。
- 独立性: 多进程运行,需要独享各种资源,多进程运行期间互不干扰。
- 并行: 多个进程在多个CPU下分别,同时进行运行,这称之为并行。
- 并发: 多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发。