理解进程概念—2
Posted 麋璐
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了理解进程概念—2相关的知识,希望对你有一定的参考价值。
紧接上一篇文章,我们已经铺垫了很多有关冯诺依曼体系结构,操作系统的概念。那么接下来,我们要了解有关进程概念和进程状态的相关知识。(注意:进程的概念理解起来会比较困难,希望大家可以反复观看,最好可以自己总结)
什么是进程概念??
进程概念:最简单的理解,就是运行中的应用程序。
应用程序:就是程序员所写的代码程序。
代码程序:一堆硬盘上的固定指令,运行程序就是让cpu处理程序指令
运行程序:首选要将程序从硬盘上加载到内存中(冯诺依曼体系结构),cpu从内存指定位置开始处理。
我们在使用电脑时,可以按ctrl+alt+点,然后点击任务管理器看到进程,下面就是我们电脑正在运行的程序
那么问题来了,当我们有很多个程序在运行时,而cpu只有一个该怎么办??
接下来我们要介绍两个运行机制:并发和并行
并发:轮询处理,循环一个一个处理
并行:同时运行
接下来大家肯定以为cpu的运行程序会是并行的吧,这样就很好的解释了同时执行很多程序的原因了。实则不然
接下来我将介绍cpu的分时机制:当我们有多个程序同时运行时,cpu(单核)只有一个,也就意味着同一时间只能处理一个程序;所有cpu的分时机制就是,将cpu对于人物的处理进行划分,让每个程序的指令和数据在cpu上只运行很短的一段时间(时间片),时间片运行完了就切换下一个程序。只要我们切换足够快,我们就认为它在同时运行。(就像比画片,我们以很高的速度播放,就可以形成动画)
那么这个时候,又有一个问题:由于我们的cpu是并发运行,那么,当我们在运行完360浏览器后,循环再去运行360浏览器时;我们如何知道上一次程序运行到哪里了??
因为程序是并发运行的,所以我们的系统必须能够知道每个程序要运行的代码和数据在内存的哪个位置,并能够知道每个切换时运行到哪里了,下一次该从哪里继续向下。
因此,实际上操作系统对每个程序的运行,都进行了一个描述,描述了当前程序在内存的位置,以及切换时候的上下文数据信息,归根结底描述的是整个程序的运行信息。这个运行信息就是—pcb—进程控制块,操作系统就是通过这个描述信息实现对于程序的运行调度管理。(其实可以把它理解为一个实时改变的指针,拿链表距离,遍历到哪里,指针移动到哪里,并且可以通过指针实时访问)
所以现在我们可以理解:什么是进程??
进程就是一个运行中的程序,或者说在操作系统的角度,进程实际上是一个系统对于程序动态运行的描述,通过这个描述操作系统才能实现对于程序运行的管理。
而这个描述就是进程控制块—PCB,在linux下是一个task_struct结构体。描述的信息有:内存指针,上下文数据,程序计数器,进程状态,IO信息,记账信息等等
上面的红字是对进程概念的总括,我们之后演示进程信息和很多相关操作都会在linux下运行,下面我要讲解的是进程状态。(其中会涉及到很多概念,希望读者可以理解并记忆)
首先我们从一个例子开始着手:A同学昨天去包夜机了,第二天想睡觉不想被打扰,一次给床头贴了一张纸条:不想被打扰,别叫我。
进程状态:就是告诉操作系统,如何去调用程序,让程序更好的运行(也就是上面的别打扰我)
课本上的描述:1.就绪—拿到时间片就能运行的状态 2.运行—正在cpu上运行的程序 3.阻塞—当前不需要调度运行的程序
在linux下的进程状态:
1.运行态-R:包含了就绪和运行,指的是正在运行的和拿到时间片久能运行的都是运行——正在睡觉
2.可中断休眠态:休眠态,一种暂时不需要被调用运行的状态(休眠态可以被打断进入运行态或者条件满足自动唤醒进入运行态)——老师找A同学,A同学立马醒了
3.不可中断态:休眠态,一种暂时不需要被调度的运行状态(休眠不可被打断)——睡不醒
4.停止状态:一种能够被调用,但什么都不做的状态(植物人状态)
5.僵尸态:进程运行退出了,但是资源有没有完全被释放的状态(不可逆转)
僵尸进程:僵尸态的进程,退出了但是资源没有完全释放的进程,是一种待处理状态。危害:资源泄漏(占据内存没有完全释放,一个用户创建的进程数量有限)
僵尸态是非常危险的,就好比我们写C代码,malloc开辟的空间没有及时释放,会发生内存泄漏。
举个例子:就好比A同学意外死亡了,赶到场的警察不能直接把人拉到火葬场火化,必须通知其parent认领;但是可能出现parent手机关机,但现场已经开始清理,知道清理结束,其parent都没有收到消息,尸体也一直存放着。
问题来了,我们如何解决僵尸进程呢??
我们可以将其parent杀死(也就是A是孤儿),那么尸体就可以直接火化了(毕竟尸体就是给parent保留的)
其次,我们如何避免僵尸进程:进程等待(下面会将到)
接下来简单介绍两个进程指令:ps -ef —查看简单信息和ps -aux—查看很多信息
top—查看cpu使用率
当我们打出下面的命令可以看到连个ID
PID和PPID,PID是你代码进程的ID,PPID是父进程
杀死进程ID:kill pid—普通杀死 ,kill -9 pid—强制杀死
我们在终端运行的指令或者程序,他们的父进程都是shell—bash进程,而这个进程人家作为父进程是非常负责任的,一旦子进程退出,立刻就回去处理,因此一般情况下,我们所运行的程序退出不会成为僵尸进程。
那么上述讲了这么多,什么是父进程??什么又是子进程??
简单来讲,就是进程A创建了进程B,A就是B的父进程
接下来我们来演示如何让父进程不负责任,这里我们要使用一个新的函数
pid_t fork(void);——创建一个子进程
通过复制调用一个进程,实现创造一个新进程(进程就是pcb,linux下就是task_struck结构体)
可以理解:创建子进程就是创建一个新的结构体,复制父进程就是复制了父进程pcb中的大部分信息(内存指针,上下文数据.....)
复制内存指针意味着子进程运行的程序和父进程一样。
复制了上下文数据意味着运行当前位置一样,在创建子进程之后,两个进程都会从创建子进程之后运行相同的代码,我们来用代码给大家说明:
运行结果:
子进程就会从创建后开始执行代码
从上述描述可以知道,父子进程的代码和位置都一样,那么怎么区分父子进程呢???为什么要创建子进程呢???
创建子进程,父子运行功能相同,在大量任务处理中,多个人处理总比一个人处理来的快——人多力量大。让子进程运行另一段代码,也就是让父子进程功能不同,让子进程处理任务,父进程只管命令,——危险的工作让子进程来,父进程安全。
如何区分返回值:可以查看函数的返回值:
1.父进程返回值大于0 2.子进程返回值等于0 3.出错返回-1
那么现在又有疑问了,为什么fork一个变量会有两个不同的值??
简单来说,就是pid在父子进程各有一个不同的返回值,只是从代码上看,只有一个。
我们来用代码举个例子:
从图中我们也不难看出,在全局变量g_val=10的情况下,只改变child的g_val不会改变parent的g_val。
最后我们来总结一下:僵尸进程:子进程先于父进程退出,退出前通知了父进程,但父进程没有处理子进程的退出,则子进程资源无法被完全释放。
危害:资源泄漏
处理:退出父进程; 避免:进程等待
孤儿进程:父进程先于子进程退出,子进程会成为孤儿进程
以上就是今天给大家带来的进程概念和进程状态的全部内容,如有不足,希望大家可以自行查阅;今天的内容就到这里,希望大家可以反复推敲。
以上是关于理解进程概念—2的主要内容,如果未能解决你的问题,请参考以下文章