1. 程序和进程
程序:指的是编译好的二进制可执行文件,在磁盘上,不运行的程序不占用系统资源(CPU,内存,打开的文件,设备,锁...)。
进程:进程是一个抽象的概念,与操作系统原理联系紧密。进程是活跃着的程序,占用系统资源,在内存中执行(程序一旦运行,就会产生进程)。
例子:程序--->剧本 进程--->戏(舞台、演员、道具)
同一个剧本可以在多个舞台同时上演,同样的道理,同一个程序也可以加载为不同的进程(彼此互不影响)。同时打开两个终端,各自都有bash,但是两个bash的ID不同。
2. 并发
并发:在操作系统中,一个时间段中有多个进程都处于已经启动到运行完毕之间的状态,但是任何一个时间点上都只有一个进程在运行。
例如:电脑可以边听歌边上网,这就是因为并发,它们是两个进程。
3. 并发程序设计:
在计算机内存中同时存放几道相互独立的程序,它们在管理程序的控制之下,相互穿插运行,多并发程序设计必须有硬件基础作为保证。
时钟中断就是并发程序设计模型的理论基础,在并发时,任意进程在执行期间都不希望放弃CPU,因此系统需要一种强制让进城让出CPU的手段,时钟中断有硬件基础作为保障,对进程而言是不可抗拒的。操作系统中的中断处理函数,负责调度进程执行。
在并发程序设计中,多个进程轮流使用CPU(分时复用CPU资源)。而当下常见的CPU为纳秒级,一秒可以执行大约10亿条指令,由于人眼的反应速度是毫秒级,所以可以看做是在同时运行。实质上,并发是宏观上并行,微观上是串行的。
4. 进程控制块PCB
每一个进程在内核中都有一个进程控制块PCB来维护进程相关的信息,Linux内核的进程控制块是task_struct结构体。
在/usr/src/linux-headers-4.10.0-28/include/linux/sched.h文件中可以查看struct task_struct结构体的定义。结构体内部的成员很多,我们只需要掌握一部分就可以了。
进程id:系统中每一个进程都有唯一的进程id,在C语言中用pid_t类型来表示,实际上是一个非负整数。
进程的状态:有就绪、运行、挂起、停止等状态。
进程切换的时候需要保存和恢复一些CPU寄存器。
描述控制终端的信息。
当前工作目录。
umask掩码。
文件描述符,包含了很多指向file结构体的指针。
和信号相关的信息。
用户id和组id。
回话和进程组。
进程可以使用的资源上限。
5. 进程状态
一般来说,一个进程在它的生命周期中有三种状态,分别为就绪(ready)、执行(execute)、等待(waiting),一个进程在穿件初期处于“进入”状态,在运行完终止后处于“完成”状态。
就绪-----进程具备运行条件,但尚未占用CPU,即进程已经拥有除CPU之外运行所需要的全部资源。
执行-----进程占用CPU。
等待-----进程由于等待某一事件不能享用CPU,即进程除CPU之外还等待获取其他资源。
6.状态转换
(1)进程状态变化的原因
1.CPU调度(低级调度):CPU调度按照某种原则从就绪队列中调度一个进程到CPU上运行,该进程就从就绪态转变成运行状态;与此同时,原来正在运行的进程就从运行状态转变成就绪态,这两种转变是同时发生的。
2.进程在运行过程中需要等待某一事件,例如:等待分配某一资源,等待I/O操作完成。一个进程在需要等待某一事件时主动退出CPU,并使自己处于阻塞状态,引起状态变化。
3.如果进程所等待的时间已经发生,例如:一次I/O完成了,于是进程就被解除阻塞状态,变成就绪状态。
(2)进程基本状态转换图
(3)进程状态转换的说明
1.一个进程在任何一个指定的时刻必须而且只能处于一种状态。
2.进程之间的状态转换并非都是可逆的,进程既不能从等待变为运行,也不能在就绪变为等待。
3.进程之间的状态转换并非都是主动的,很多情况下都是“被动的”。事实上,只有运行到等待的转换是主动的(主动调用调度管理程序),其他的都是“被动的”。例如,从执行到就绪,通常是时钟中断引起的,从等待到就绪,是一个进程把另一个进程唤醒。
PS:有哪里写的不对的地方请指正,大家互相学习。