进程、线程

1、定义

(1)一个具有一定独立功能的程序,在一个数据集合上的一次动态执行过程

(2)动态执行过程:源代码文件进行编译链接,变成了静态的可执行文件,只有当系统将这段程序调入到内存中去,CPU 执行一条条指令以及读取数据

2、组成

(1)程序的代码

(2)程序处理的数据

(3)程序计数器中的值,指示下一条将运行的指令

(4)一组通用的寄存器的当前值、堆、栈

(5)一组系统资源(如打开的文件)

(6)总之,进程包含了正在运行的一个程序的所有状态信息

3、程序、进程的关系

(1)程序是产生进程的基础,进程是程序功能的体现

(2)程序是执行的代码,进程是动态执行过程

(3)通过多次执行,一个程序可对应多个进程;通过调用的关系,一个进程可包括多个程序

(4)进程是 OS 处于执行状态程序的抽象:程序 = 文件(静态的可执行文件);进程 = 程序 + 执行过程(数据和和运行过程)

4、进程、程序的区别

(1)进程是动态的,程序是静态的

(2)程序是有序代码的集合,进程是程序的执行,进程有核心态 / 用户态

(3)进程与程序的组成不同:进程的组成包括程序、数据和进程控制块(即进程状态信息)

(4)进程是暂时的,是一个状态变化的过程;程序是永久的,可长久保存

5、特点

(1)动态性:可动态地创建、切换、结束进程;

(2)并发性:进程可以被独立调度并占用处理器运行(并发不是并行)

(3)独立性:不同进程的工作不相互影响,例如 OS 在内存管理的页表机制

(4)制约性:因访问共享数据、资源,或进程间同步而产生制约,需要操作系统协调执行顺序

6、并行、并发的区别

(1)并行:指在同一时刻,有多条指令在多个处理器上同时执行,所以无论是从微观还是从宏观来看,二者都是一起执行的

(2)并发:指在同一时刻只能有一条指令执行,但多个进程指令被快速的轮换执行,使得在宏观上具有多个进程同时执行的效果,但在微观上并不是同时执行的,只是把时间分成若干段,使多个进程快速交替地执行

 

进程控制块(PCB:Process Control Block)

1、定义:描述进程的数据结构,OS 管理控制进程运行所用的信息集合

2、作用

(1)PCB 是进程存在的唯一标志,每个进程都在操作系统中有一个对应的 PCB

(3)OS 用 PCB 来保存与该进程有关的各种状态信息、描述进程的基本情况以及运行变化的过程

3、使用过程

(1)进程创建时,生成该进程的 PCB

(2)进程终止时,回收该进程的 PCB

(3)通过对 PCB 的组织管理,来实现对进程的组织管理

4、三大类信息

(1)进程标识信息

如,本进程的标识(PID:唯一的进程 ID 号)、本进程的产生者标识(父进程 ID 号)、用户标识(UID)

(2)处理机状态信息保存区:保存进程的运行现场信息

用户可见寄存器:用户程序可以使用的顺序、地址等寄存器    

控制和状态寄存器:如程序计数器(PC),程序状态字(PSW)

栈指针:过程调用 / 系统调用 / 中断处理和返回时需要用到

(3)进程控制信息

调度和状态信息:调度进程和处理机使用情况,用于 OS 调度进程并占用处理机使用

进程间通信信息:进程间通信相关的各种标识、信号、信件等,这些信息存在接收方的进程控制块中

存储管理信息:指向本进程映像存储空间的数据结构

进程所用资源:进程打开、使用的系统资源,如打开的文件等

有关数据结构连接信息:与 PCB 相关的进程队列,进程可以连接到一个进程队列中,或连接到相关的其他进程的 PCB

5、组织

(1)链表(便于插删,用于通用 OS):同一状态的进程 PCB 为一链表,不同状态对应不同的链表:就绪链表,阻塞链表

(2)索引表(数组,不利于插删,使用于固定数目的进程,相对创建更快捷):同一状态的归入一个索引表(每一个索引指向 PCB),如,就绪索引表、阻塞索引表

 

进程状态

1、生命周期

(1)进程创建

(2)进程运行

(3)进程等待

(4)进程唤醒

(5)进程结束

2、进程创建

(1)系统初始化时,系统刚开始创建一个 INIT 进程,这个进程负责创建其他新的进程,这些新进程是用户请求创建的

(2)用户请求创建一个新进程

(3)正在运行的进程执行了创建进程的系统调用

3、进程执行

(1)创建好进程之后,放入就绪队列,等待调度

(2)内核选择了一个就绪的进程,让它占用处理机并执行

4、进程等待(阻塞)

(1)请求并等待系统服务,无法马上完成,比如,等待 OS 读取数据

(2)启动某种操作,无法马上完成,需要其他进程的协作

(3)需要的数据没有到达

(4)进程只能自己阻塞自己,因为进程自身才能知道合适需要等到某件事件的发生

5、进程唤醒

(1)被阻塞进程需要的资源可被满足

(2)被阻塞进程等待的事件到达

(3)将该进程的 PCB 插入到就绪队列

(4)进程只能被别的进程或 OS 唤醒

6、进程结束

(1)正常退出(自愿)

(2)错误退出(自愿)

(3)致命错误(强制性):比如访问了其他进程内存空间

(4)被其他进程所杀(强制性):管理进程觉得某一进程占用内存太多,可能破坏其他进程,将它杀死

 

进程的基本状态

1、进程在生命结束前仅处于三个基本状态之一,不同系统设置的进程状态数目不同

(1)运行状态(Running):当一个进程正在处理机上运行时。

(2)就绪状态(Ready):一个进程获得了除处理机(CPU)之外的一切所需资源,一旦得到处理机即可运行。

(3)等待状态(阻塞状态:Blocked):一个进程正在等待某一事件而暂停运行时。如等待某资源,等待输入/输出完成。

2、其他的基本状态

(1)创建状态(New):一个进程正在被创建,还没被转到就绪状态之前的状态

(2)结束状态(Exit):一个进程正在从系统中消失时的状态,这是因为进程结束或由于其他原因所导致

 

进程挂起

1、不同于进程阻塞,把一个处于 Ready / Blocked 进程从内存转存到外存

2、目的:减少进程占用内存,通常选择低优先级进程进行挂起

3、挂起状态

(1)阻塞挂起状态(Blocked-suspend):进程在外存并等待某事件的出现

(2)就绪挂起状态(Ready-suspend):进程在外存,但只要进入内存,即可运行

4、内存 -> 外存:挂起

(1)阻塞 -> 阻塞挂起:没有进程处于就绪状态,或就绪进程要求更多内存资源时,会进行这种转换,以提交新进程或运行就绪进程

(2)就绪 -> 就绪挂起:当有高优先级就绪进程和低优先级就绪进程时,系统会选择挂起低优先级就绪进程

(3)运行 -> 就绪挂起:对抢先式分时系统,当有高优先级等待挂起进程,因时间出现而进入就绪挂起时,系统可能会把运行进程 -> 就绪挂起进程

5、在外存时的状态转换:

(1)阻塞挂起 -> 就绪挂起:当有阻塞挂起进程因相关事件出现时,系统会把阻塞挂起进程 -> 就绪挂起进程

6、外存 -> 内存:解挂 / 激活

(1)就绪挂起 -> 就绪:没有就绪进程,或挂起就绪进程优先级高于就绪进程时,会进行这种转换

(2)阻塞挂起 -> 阻塞:当一个进程释放足够内存时,系统会把一个高优先级等待挂起进程 -> 阻塞进程

 

状态队列

1、由 OS 来维护一组队列,用来表示系统当中所有进程的当前状态,多种队列是 OS 管理进程的重要手段

2、不同的状态分别用不同的队列来表示

3、每个进程的 PCB 都根据它的状态加入到相应的队列当中,当一个进程的状态发生变化时,它的 PCB 从一个状态队列中脱离出来,加入到另外一个队列

 

线程

1、定义:线程是进程的一部分,描述指令流执行状态,它是进程中的指令执行流的最小单元,是 CPU 调度的基本单位

2、特性

(1)线程之间可以并发执行

(2)线程之间共享相同的地址空间

3、线程是进程当中的一条执行流程

(1)进程的资源分配角色:进程由一组相关资源构成,包括地址空间(代码段、数据段)、打开的文件等各种资源

(2)线程的处理机调度角色:线程描述在进程资源环境中的指令流的执行状态,每个线程有自己独立的指令指针

4、 线程 = 进程 - 共享资源 / 进程 = 线程 + 资源管理

5、优点

(1)一个进程中可以同时存在多个线程

(2)各个线程之间可以并发地执行

(3)各个线程之间可以共享地址空间和文件等资源

6、缺点

(1)安全可靠性没有保障:一个线程崩溃,会导致其所属进程的所有线程崩溃

7、进程、线程的比较

(1)进程是资源分配的单元,线程是 CPU 调度的单元

(2)进程拥有一个完整的资源平台,而线程只独享必不可少的资源,如寄存器和栈

(3)线程同样具有就绪、等待、执行三种基本状态,同样具有状态之间的转换关系

(4)线程能减少并发执行的时间和空间开销

线程的创建时间比进程短:进程创建中还要创建内存管理、文件管理;线程创建是直接使用所属的进程创建好的这些资源

线程的终止时间比进程短:不需要考虑上面资源的释放问题

同一进程的线程切换时间比进程短:线程具有同一地址空间(同一进程的线程拥有同一页表),不用切换页表;进程切换的时候要切换页表,这部分开销比较大

由于同一进程的各线程间共享内存和文件资源,可直接进行不通过内核的通信

8、三种实现方式

(1)用户线程

(2)内核线程

(3)轻量级进程

 

用户线程

1、在用户空间实现,不依赖 OS,由一组用户级的线程库函数来完成线程的管理,包括进程的创建、终止、同步、调度等,如 POSIX、Pthreads 等

2、优点

(1)不依赖于 OS 内核,可以用于不支持线程的多进程操作系统

(2)在用户空间实现的线程机制,每个进程都需要它自己私有的线程控制块(TCB)列表,TCB 由线程库函数来维护,用来跟踪记录它的各个线程的状态信息(PC、栈指针、寄存器)

(3)同一进程内的用户线程切换速度快,无需在用户态与核心态之间切换

(4)允许每个进程拥有自己的线程调度算法

3、缺点

(1)线程发起系统调用而阻塞时,整个进程进入等待

(2)不支持基于线程的处理机抢占,除非当前运行线程主动放弃 CPU 使用权,它所在的进程的其他线程无法抢占 CPU

(3)只能按进程分配 CPU 时间,进程中多个线程,每个线程的时间片较少

 

内核线程

1、在内核中实现,由 OS 管理,由内核通过系统调用实现的线程机制,由内核完成线程的创建、终止和管理,如 Windows 等

2、特点

(1)由内核维护 PCB 和 TCB

(2)线程执行系统调用而被阻塞不影响其他线程

(3)因为通过系统调用 / 内核函数,在内核空间实现线程的创建、终止、切换开销相对较大

(4)以线程为单位进行CPU时间分配,多线程的进程可以获得更多CPU时间

 

轻量级进程

1、在内核中实现,内核支持的用户线程

2、一个进程可以有一个或多个轻量级进程,每个轻量级进程由一个单独的内核线程来支持,如 Solaris、Linux

3、用户线程与内核线程的对应关系

(1)可以是多对一、一对一、多对多

(2)一对一是最优的

 

进程控制

 

进程切换(上下文切换)

1、停止当前运行进程,从运行状态改变成其他状态,调度其他进程,转变成运行状态

2、要求

(1)必须在切换之前存储许多部分的进程上下文

(2)必须能够在之后恢复他们,所以进程不能显示它曾经被暂停过

(3)必须快速(上下文转换非常频繁)

3、需要存储的上下文

(1)寄存器(PC、SP……)

(2)CPU状态

(3)内存地址空间

  4、OS 为活跃进程准备了进程控制块(PCB),并将进程控制块放在一个合适的队列里,共有三种队列

(1)就绪队列

(2)等待 IO 队列(每个设备的队列)

(3)僵尸队列

 

进程创建

1、Windows 进程创建 API

(1)CreateProcess(filename, CLOSEFD):创建时关闭所有在子进程里的文件描述符

(2)CreateProcess(filename,CLOSE FDnew_envp):创建时改变子进程的环境

2、Unix 进程创建系统调用

(1)fork() 把一个进程复制成两个进程:parent(old PID), child(new PID)

(2)exec() 用新程序来重写当前进程,PID 没有改变

3、fork、exec 创建示例

int pid = fork();//创建子进程
if (pid == 0) {//子进程在这里继续
    //Do anything (unmap memory、cose net connections……)
    exec("program", argcargvo, argv1,……);
}

(1)fork() 通过复制,创建一个继承的子进程

复制父进程的所有变量和内存

复制父进程的所有CPU寄存器(有一个寄存器除外)

(2)fork() 的返回值

子进程的 fork() 返回 0

父进程的 fork() 返回子进程标识符

(3)fork() 返回值可以方便后续使用,子进程可以使用 getpid() 获取 PID

(4)fork() 执行过程对于子进程而言,是在调用时间对父进程地址空间的一次复制

(5)fork() 得到的子进程和父进程只有上述的返回值不同,对于父进程 fork() 返回 child PID,对于子进程返回值为 0,利用这个特点就可以进行多进程操作

 

进程加载

1、exec():允许程序加载一个完全不同的程序,并从 main 开始执行(和 OS 启动时类似)

2、系统调用 exec() 时,加载程序取代当前运行进程,运行进程加载时,指定启动参数 (argc, argv)

3、exec() 调用成功时,还是相同的进程,但是运行了不同的程序

4、代码段、栈、堆都完全重写

5、fork() 的简单实现

(1)对子进程分配内存

(2)复制父进程的内存和CPU寄存器到子进程里

(3)开销高

6、在 99% 情况下,调用 fork() 之后,都会使用系统调用 exec(),加载新程序取代当前运行进程

(1)在 fork() 操作中内存复制是没有作用的

(2)子进程将可能关闭打开的文件和连接

(3)开销高

7、vfork()

(1)轻量级 fork(),结合 fork()、exec()

(2)一个创建进程的系统调用,不需要创建一个同样的内存映像

(3)只是复制部分内容,子进程应该几乎立即调用exec()

(4)使用 Copy-on-write(COW)技术实现

 

进程等待

1、wait():系统调用用于父进程等待子进程的结束

(1)子进程结束时,通过 exit() 向父进程返回一个值

(2)父进程通过 wait() 接受并处理返回值,回收子进程 PCB

2、wait() 系统调用的功能

(1)有子进程存活时,父进程进入等待状态,等待子进程的返回结果(exit 值作为 wait 的返回值)

(2)当某子进程调用 exit() 时,OS 唤醒父进程,并且将通过 exit() 传递得到的返回值,作为 wait() 调用的一个结果(连同子进程的pid一起)

(3)有僵尸子进程时,wait() 立即返回其中一个值

(4)如果没有子进程存活,wait() 立刻返回

 

进程结束

1、exit() 系统调用,用于进程结束时、父进程 wait() 调用之前,完成进程资源的回收

2、exit() 系统调用的功能

(1)将调用参数作为进程的结果

(2)关闭所有打开的文件等占用资源、释放内存、释放大部分进程相关的内核数据结构

(3)检查是否父进程存活

如果存活,保留结果的值,直到父进程需要它,进入僵尸(zombie / defunct)状态

如果没有,释放所有的数据结构、进程结果,该进程死亡

(4)清理所有等待的僵尸进程

3、进程中止是最终的垃圾收集(资源回收)

posted @   半条咸鱼  阅读(53)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示