操作系统学习笔记002

1、进程与线程

1、进程

进程是对一个正在运行的程序的抽象。(一个正在运行的程序就是一个进程,进程是动态的。)

1.1、进程模型

在进程模型中,计算机上所有可运行的软件,通常也包括操作系统,被组织成若干顺序进程(sequential process),简称进程(process)。一个进程就是一个正在执行程序的实例,包括程序计数器、寄存器和变量的当前值。

1.2、进程的创建

有4种主要事件导致进程的创建:
1)系统初始化。
2)执行了正在运行的进程所调用的进程创建系统调用。一个正在运行的进程经常发出系统调用,以便创建一个或多个新进程协助其工作。
(例如,如果有大量的数据要通过网络调取并进行顺序处理,那么创建一个进程取数据,并把数据放入共享缓冲区中,而让第二个进程取走数据项并处理之,应该比较容易。在多处理机中,让每个进程在不同的CPU上运行会使整个作业运行得更快。)
3)用户请求创建一个新进程。
4)一个批处理作业的初始化。
(用户在这种系统中(可能是远程地)提交批处理作业。在操作系统认为有资源可运行另一个作业时,它创建一个新的进程,并运行其输入队列中的下一个作业。)

从技术上看,在所有这些情形中,新进程都是由于一个已存在的进程执行了一个用于创建进程的系统调用而创建的。这个进程可以是一个运行的用户进程、一个由键盘或鼠标启动的系统进程或者一个批处理管理进程。这个进程所做的工作是,执行一个用来创建新进程的系统调用。这个系统调用通知操作系统创建一个新进程,并且直接或间接地指定在该进程中运行的程序。
也就是说:新进程是这样产生的:已经存在的进程执行了一个用于创建进程的系统调用

例如:在UNIX系统中,只有一个系统调用可以用来创建新进程:fork。这个系统调用会创建一个与调用进程
相同的副本。在调用了fork后,这两个进程(父进程和子进程)拥有相同的存储映像、同样的环境字符串和
同样的打开文件。这就是全部情形。通常,子进程接着执行execve或一个类似的系统调用,以修改其存储映
像并运行一个新的程序。

一个Win32函数调用CreateProcess既处理进程的创建,也负责把正确的程序装入新的进程。

1.2、进程的终止

进程终止的条件:
1)正常退出(自愿的)。
2)出错退出(自愿的)。
3)严重错误(非自愿)。
4)被其他进程杀死(非自愿)。

1.3、进程的层次结构

某些系统中,当进程创建了另一个进程后,父进程和子进程就以某种形式继续保持关联。子进程自身可
以创建更多的进程,组成一个进程的层次结构。请注意,这与植物和动物的有性繁殖不同,进程只有一个父
进程(但是可以有零个、一个、两个或多个子进程)。

在UNIX中,进程和它的所有子女以及后裔共同组成一个进程组。

例如:
考虑UNIX在启动时如何初始化自己。一个称为init的特殊进程出现在启动映像中。当它开始运行时,读入一个说明终端数量的文件。接着,为每个终端创建一个新进程。这些进程等待用户登录。如果有一个用户登录成功,该登录进程就执行一个shell准备接收命令。所接收的这些命令会启动更多的进程,以此类推。这样,在整个系统中,所有的进程都属于以init为根的一棵树。

相反,Windows中没有进程层次的概念,所有的进程都是地位相同的。惟一类似于进程层次的暗示是在
创建进程的时侯,父进程得到一个特别的令牌(称为句柄),该句柄可以用来控制子进程。但是,它有权把
这个令牌传送给某个其他进程,这样就不存在进程层次了。

1.3、进程的状态(重要)

每个进程是一个独立的实体,有其自己的程序计数器和内部状态,但进程之间经常需要相互作用。
一个进程的输出结果可能作为另一个进程的输入。

这三种状态是:
1)运行态(该时刻进程实际占用CPU)。
2)就绪态(可运行,但因为其他进程正在运行而暂时停止)。
3)阻塞态(除非某种外部事件发生,否则进程不能运行)。

前两种状态在逻辑上是类似的。处于这两种状态的进程都可以运行,只是对于第二种状态暂时没有CPU
分配给它。第三种状态与前两种状态不同,处于该状态的进程不能运行,即使CPU空闲也不行。

在这里插入图片描述

1.3、进程的实现

为了实现进程模型,操作系统维护着一张表格(一个结构数组),即进程表(process table)。每个进程占用一个进程表项。(有些作者称这些表项为进程控制块。)该表项包含了进程状态的重要信息,包括程序计数器、堆栈指针、内存分配状况、所打开文件的状态、账号和调度信息,以及其他在进程由运行态转换到就绪态或阻塞态时必须保存的信息,从而保证该进程随后能再次启动,就像从未被中断过一样。

2、线程

在传统操作系统中,每个进程有一个地址空间和一个控制线程。线程是进程当中的⼀条执⾏流程,是更小的能独立运行的基本单位。

2.1、线程的使用

使用多线程的原因:
1、使得程序设计模型变得更简单。
(在许多应用中同时发生着多种活动。其中某些活动随着时间的推移会被阻塞。通过将这些应用程序分解成可以准并行运行的多个顺序线程,程序设计模型会变得更简单。)
2、线程更轻量、比进程更容易创建和撤销
由于线程比进程更轻量级,所以它们比进程更容易(即更快)创建,也更容易撤销。在许多系统中,创建一个线程较创建一个进程要快10~100倍。在有大量线程需要动态和快速修改时,具有这一特性是很有用的。
3、提高程序的执行速度
若多个线程都是CPU密集型的,那么并不能获得性能上的增强,但是如果存在着大量的计算和大量的I/O处理,拥有多个线程允许这些活动彼此重叠进行,从而会加快应用程序执行的速度。

进程中的不同线程不像不同进程之间那样存在很大的独立性。所有的线程都有完全一样的地址空间,这
意味着它们也共享同样的全局变量。由于各个线程都可以访问进程地址空间中的每一个内存地址,所以一个
线程可以读、写或甚至清除另一个线程的堆栈。

和传统进程一样(即只有一个线程的进程),线程可以处于若干种状态的任何一个:运行、阻塞、就绪
或终止。正在运行的线程拥有CPU并且是活跃的。被阻塞的线程正在等待某个释放它的事件。

每个线程需要有自己的堆栈。

在这里插入图片描述
第一列表项是进程的属性,而不是线程的属性。如果每个线程有其自己的地址空间、打开文件、即将发生的报警等,那么它们就应
该是不同的进程了。线程概念试图实现的是,共享一组资源的多个线程的执行能力,以便这些线程可以为完成某一任务而共同工作。

每个线程的堆栈有一帧,供各个被调用但是还没有从中返回的过程使用。在该帧中存放了相应过程的局部变量以及过程调用完成之后使用的返回地址。

2.1、线程实现的三种方式

1、在用户空间中实现线程
最明显的优点是,用户级线程包可以在不支持线程的操作系统上实现。并且它允许每个进程有自己定制的调度算法。

在用户空间管理线程时,每个进程需要有其专用的线程表(thread table),用来跟踪该进程中的线程。这些表和内核中的进程表类似,不过它仅仅记录各个线程的属性,如每个线程的程序计数器、堆栈指针、寄存器和状态等。

2、在内核中实现的线程
在内核中有用来记录系统中所有线程的线程表。当某个线程希望创建一个新线程或撤销一个已有线程时,它进行一个系统调用,这个系统调用通过对线程表的更新完成线程创建或撤销工作。(内核中实现的线程其创建、撤销都由内核来完成,内核负责维和线程表)

内核的线程表保存了每个线程的寄存器、状态和其他信息。

3、混合实现
内核只识别内核级线程,并对其进行调度。其中一些内核级线程会被多个用户级线程多路复用。如同在没有多线程能力操作系统中某个进程中的用户级线程一样,可以创建、撤销和调度这些用户级线程。在这种模型中,每个内核级线程有一个可以轮流使用的用户级线程集合。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值