进程的定义:进程是具有独立功能的程序关于某个数据集合上的一次运行活动,是系统进程资源分配和调度的独立单位。进程又称为任务。
进程的特点:
程序的一次执行过程
是正在运行程序的抽象
将一个CPU变幻成多个虚拟CPU
系统资源以进程为单位进行分配,如内存、文件等,每个进程具有独立的地址空间
操作系统将CPU调度给需要的进程
进程状态分类:
三状态:运行、就绪、等待/阻塞
五状态:创建、运行、就绪、等待、终止
七状态:创建、运行、就绪、就绪挂起、等待、等待挂起、终止
进程队列:
操作系统按状态分类对每一类进程创建一个队列或多个队列
队列元素为对应状态的进程的PCB
随着进程状态的不断改变,一个进程的PCB从一个队列转移到另一个队列
进程的创建:
为进程分配一个唯一标识和一个进程控制块(PCB)
为进程分配地址空间
初始化进程控制块
设置相应的队列指针,如将进程加入到就绪任务队列
UNIX中的主要进程控制操作:
fork() - 通过复制调用进程来创建新的进程
exec() - 通过用一段新的程序代码覆盖原来的地址空间,实现进程执行代码的转换
wait() - 提供初级进程同步操作,能使一个进程等待另一个进程的结束
exit() - 用来终止一个进程的运行
UNIX中fork的实现:
为子进程分配一个空闲的进程描述符
为子进程分配唯一标识pid
以一次一页的方式复制父进程的地址空间 (Linux对此项进行了优化,采用写时拷贝技术Copy On Write,父进程只将地址空间的指针传给子进程并将地址空间设置为只读(这里应该是说设置子进程对地址空间的权限为只读吧),当子进程需要向地址空间执行写入操作时,才为子进程开辟相应的空间并将其需要的内容放进去(开辟的地址空间大小应该是写入的目的空间所占的页大小吧))
从父进程处继承共享资源,如打开的文件和当前目录等
对子进程返回标识符0,对父进程返回子进程的pid
对进程的其他讨论:
进程与程序的区别:
进程更能准确地刻画并发,而程序不能
程序是静态的,而进程是动态的
进程是有生命周期的,有诞生有消亡,是短暂的;而程序则相对来说是长久的
一个程序可对应多个进程——一个程序可以被多个进程使用
进程具有创建其他进程的功能
比喻:进程好比是做菜的过程,而程序是一道菜的食谱
关于进程地址空间的一个问题:有这样一个程序:声明一个全局变量val并在main函数中将该变量的地址打印到终端。执行该程序2次并通过argv赋予val不同的值,于是便产生2个进程,此时在屏幕上可以看到一个出乎意料的结果——两个进程所打印出来的val的地址是相同的。这里不禁要想:难懂是两个进程共用了这个全局变量?但是两个进程给val设置的值是不同的啊!实际上,两个进程分别运行于各自的地址空间,并且各自的val也位于各自的地址空间内,而之所以两个进程的val地址相同,是因为所用的地址表示方式是虚拟地址,或者叫作逻辑地址,是在进程地址空间中的相对位置,而由于两个进程所运行的函数相同,因此他们的地址空间内部安排也相同。地址空间分为内核地址空间和用户地址空间,用户进程位于用户地址空间中。一个进程的地址空间内包含有:代码段、数据段、堆、栈,另外堆和栈之间的空间用于存放共享库和内存映射文件等。
进程映像:对进程执行活动全过程的静态描述。有进程地址空间内容、硬件寄存器内容与该进程相关的内核数据结构、内核栈组成。进程映像是一个进程的快照。
为什么引入线程的概念?
应用的需要 ——如web服务器接收请求和查找网页文件的并发需求
开销的考虑——相比于进程,线程开销较小,主要体现在如下三点:(1)创建一个线程花费时间少;(2)线程间切换花费时间少;(3)线程间通信无需调用内核(同一进程中的线程共享文件和变量)
性能的考虑——在多处理器条件下,多个线程可是实现真正的并发,从而提高性能???与后面提到的线程的缺点相矛盾啊
引入线程后,CPU调度的最小单位变为了线程,于是便有:“进程是资源分配的最小单位,线程是CPU调度的最小单位。”
线程的实质:线程有时称为轻量级进程,是进程中的一个运行实体,是CPU调度单位。
线程的属性:
有标识符ID
有状态及状态的转换
线程切换时需要保存上下文
有自己的栈和栈指针
共享所在进程的地址空间和其他资源
可以创建和撤销另一个线程——程序一开始运行时就是一个单线程
线程的实现:线程的实现主要有以下三种方式:用户级线程(UNIX)、内核级线程(Windows)、混合模型(Solaris),这里主要说一下用户级线程:
在用户空间建立线程库,提供一组管理线程的过程
由运行时系统完成线程的管理工作(操作、线程表),而内核只管理进程,它并不知道线程的存在
线程切换不需要进入内核态——这与“线程是CPU调度的最小单位”的说法并不矛盾,线程切换需要改变的CPU状态,这里说的是不需要内核的参与
可重入程序的概念:可被多个进程同时调用的程序,是纯代码的,即执行过程中自身不改变,数据区由调用它的进程提供(不依赖全局变量之类的数据)
posted @
2020-06-23 17:28
凉风SK
阅读(
199 )
评论()
编辑
收藏
举报