windows内核开发学习笔记三十八:内核概念之进程和线程管理

        前面在windows内核开发学习笔记三十五:系统线程和系统进程博文中介绍了系统进程和系统线程,涉及了一些线程和进程的概念,在本文更进一步的介绍进程和线程管理的相关知识。

        进程(process)定义了一个执行环境,包括他自己的私有的地址空间、一个句柄表,以及一个安全环境;线程(thread)则是一个控制流,有自己的调用栈(call stack),记录了它的执行历史,每个进程都包含一个或多个线程,当进程被初始创建时系统为该进程创建第一个线程;当最后一个线程结束时,进程也随之结束。windows是一个多进程操作系统环境,但它对处理器资源的分配是按照线程来进行调度的。进程中的线程既可能在用户模式下执行,也可能在内核模式下执行。如果一个进程在用户模式下执行,那么它只能访问进程的地址空间;如果运行在内核模式下,那么可以访问整个地址空间。

        在windows系统中,进程有父子关系,进程的许多属性在不明确指定的情况虚啊,均继承自父进程,与UNIX系统不同的是,windows中的进程的父子关系是一个相对松散的概念,仅仅代表了创建者和被创建者的关系。进程本身是独立的,它仅仅记录了父进程的ID而已。

        在windows内核结构中,进程和线程的核心机制是在微内核中实现的,而管理机制是在执行体中实现的,这符合机制与策略分工的原则,如:线程调度是由微内核来完成的,线程的和进程的创建、各种管理属性的设置则由执行体来完成的。因此,我们在检查内核函数和阅读windows源代码时,会看到有些关于进程和线程的数据结构和函数属于微内核的范畴,而另外一些则属于执行体的范畴。比较典型的例子是:KPROCESS和KTHREAD是微内核中的进程核线程的数据结构,而EPROCESS和ETHREAD是执行体中进程和线程的数据结构;KeAttachProcess/KeStackAttachProcess是微内核中将线程依附到指定进程的函数,而PspCreateThread/PspCreateProcess是执行体中创建线程和进程的函数。

        进程的创建是在内核函数PspCreateProcess中完成的,它先创建一个执行体进程对象(EPROCESS)然后初始化该对象的状态,包括建立地址空间。类似地,线程的创建是在内核函数PspCreateThread中完成的,它先创建一个执行体线程对象(ETHREAD),然后初始化其中的域,并维护好新线程与宿主进程之间的关系。而windows子系统进程的创建过程还要复杂一些,有一部分工作是在子系统DLL中完成的。如:首先要打开指定的可执行文件,创建一个内存区对象,然后才调用到内核中的PspCreateProcess函数。等到进程对象和线程对象建立起来以后,windows子系统进程(csrss.exe)还会介入创建过程,以维护子系统内部的进程、线程状态。而且,进程的最后阶段的初始化工作是由初始线程在该进程环境中执行的,所以当初始线程获得第一次执行权时,总是从某个预定的函数开始执行,然后在这个函数中从内核模式切换到用户模式下,执行基本的进程初始化任务,包括加载必要的动态链接库,并执行每个库的初始化函数。完成初始化工作以后,最终控制权进入用户指定的线程启动函数或者可执行映像文件的入口函数。至此,进程和线程进入正常的运行状态,参与系统的统一调度和资源管理。

        windows实现了基于优先级的抢占式(preemptive)线程调度算法,每个线程都有一个基本优先级(base priority)和一个动态优先级(priority)。优先级的值处于0~31之间,共分三个类别:

  • 系统优先级:0表示系统优先级,为最低优先级,仅用于零页面线程;
  • 动态优先级:1~15为动态优先级,在某些情形下线程的动态优先级可以在此范围内进行微调,例如当一个前台线程从等待状态中被唤醒时,他的优先级将有一点点提升,从而可以尽快获得处理器的执行权(至少比相同基本优先级的其他线程优先);
  • 实时优先级:16~31为实时优先级,用于一些实时处理任务。

每个线程从初始化开始一直到最后终止,其状态会随着系统状态以及自身的代码逻辑而发生变化。windows调度算法中的线程状态转移图比传统的抢占式调度算法略微细致一些。本质上每个线程都处于两种状态之一:

  • 满足继续执行的条件,正在排队或者已经在执行;
  • 不满足继续执行条件,处于等待状态,或者它的调用栈甚至所处的进程已被换出内存。

        在满足执行条件的情况下,线程按优先级排队执行;对于多处理器系统排队过程要复杂一些,调度器不仅要处理多个队列,而且要考虑每个处理器的就绪线程队列的平衡程度。由于各个线程可能存在处理器的亲和性(affinity),所以,此排队和分发过程要略微复杂一些。而对于不满足执行条件下的情形,长时间处于等待状态的线程,其调用栈(甚至整个进程)可能被换出内存,在这种情况下,一旦其执行条件已满足,则首先要被换回内存,然后才能参与排队分发。

        还有两个进程和线程的相关的概念也值得提一下:作业和纤程。

  • 作业(job)是一个执行体支持的内核对象,它使得一个或多个进程被当作一个整体来加以管理和控制。管理程序通过windows API可以控制一个作业消耗系统资源(CPU或内存)的各种限制,如用户模式的CPU时间限制,进程的处理器亲和性、工作集的最大和最小值、虚拟内存的使用限制等。
  • 纤程(fiber)是一种用户线程,它对于内核是不可见的,由kernel32.dll实现。应用程序可以在一个线程环境中创建多个纤程,然后手动控制它们执行。纤程不会被自动执行,应用程序必须显式的选择某个纤程来执行,而且,一旦纤程运行起来,要么一直运行到它退出,要么运行到它显式地切换到另一个纤程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jyl_sh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值