Windows核心编程 进程与线程

进程

Windows作为多任务操作系统,允许多个程序同时在系统中运行。这些程序被称为进程,进程运行在一片独立的空间中,受到操作系统保护,操作系统的很多资源都是围绕着进程来进行分配,可以理解为操作系统维度下资源分配的最小粒度.

一个进程由两部分构成

  1. 一个内核对象
    内核对象保存进程的各种统计信息,操作系统依靠这些统计信息对进程进行管理
  2. 一个空间地址
    包含了exe,dll的代码和数据,以及线程栈与堆。

在Windows操作系统中,进程拥有如下资源(节选):

  1. 一片虚拟地址,也就是进程空间
  2. PID
    即ProcessId
  3. Image
    即将程序加载到内存并使其能够运行所需的所有信息,也就死exe在内存中的表示
  4. 线程
    1-N个线程数量
  5. EPROCESS(Executive Process Block)
    位于内核态,记录着内核态的关键信息
  6. 句柄表
    位于内核态,记录进程所创建/打开的内核对象。
  7. DirBase
    进程的起始基地址
  8. PEB(Process Environment Block)
    位于用户态,记录着用户态的关键信息
  9. Access token
    表示进程的用户,安全组以及优先级

眼见为实

Windows核心编程 进程与线程

  1. SessionId
    指进程所在的windows会话Id,当多个用户登录时,有不同的会话Id
  2. Cid/ParentCid
    即PID,以及创建该进程的那个进程Id

眼见为实:句柄表

即ObjectTable
Windows核心编程 进程与线程

眼见为实:Token

Windows核心编程 进程与线程

EPROCESS,内核态数据结构

每一个进程都会持有一个EPROCESS的结构,如果一个档案一样记录着进程的所有信息。上面所展示的信息,本质上就是对EPROCESS信息的提取

眼见为实

Windows核心编程 进程与线程

PEB,用户态数据结构

包含了进程的用户态信息,与EPROCESS位于内核态不同,PEB是先在内核态中创建,再映射到用户态之中

眼见为实

Windows核心编程 进程与线程

进程空间

操作系统为了保护进程的安全,为不同的进程分配了独立的进程空间虚拟地址。目的旨在一个进程的代码与数据不会受到其它进程的修改,它们之间互相隔离。

32位系统进程空间

Windows核心编程 进程与线程

64位系统进程空间

Windows核心编程 进程与线程

内核态与用户态

Windows定义了两种访问模式,用户模式(user mode)与内核模式(kernel mode).
应用程序运行在user mode下,操作系统运行的kernel model下,他们之间互相隔离,无法直接访问,即便应用程序知道了在内核态中的某个数据的正确指针,也会被终止访问。

虽然不可以直接访问,但Windows提供了一道桥梁,用于程序可以通过调用Win32 API来间接的访问内核态。

眼见为实

Windows核心编程 进程与线程

线程

如果把操作系统比作一个国家,那么进程就是这个国家的家庭,而线程则是家庭的成员。

懒惰的进程

进程是非常懒惰的,从不执行任何东西,它只是线程与统计信息的一个容器,具体的工作需要由线程来执行。
从上面的比喻也可以看出,家庭是一个抽象的概念,家庭的成员才是物理意义上的执行单位。

臃肿的进程

从上面的介绍可以看出,进程使用的资源会更多,其原因在于地址空间。
为一个进程创建一个虚拟地址空间需要大量资源。

  1. 大量的日志记录
    这需要用到大量内存
  2. 加载文件
    加载exe,dll到内存中,也是消耗大户

相比之下,线程所使用的资源就要少得多了。一个线程实际上只有一个内核对象和一个栈。也不涉及日志记录。
与进程类似,线程也由两个部分组成

  1. 线程的内核对象
    内核对象保存线程的各种统计信息,操作系统依靠这些统计信息对线程进行管理
  2. 一个线程栈
    用于维护线程执行时所需要的函数参数与局部变量

ETHREAD,内核态数据结构

与EPROCESS结构来描述进程内核态的信息一样,线程也有一个类似的结构。名字叫做ETHREAD
Windows核心编程 进程与线程

ETHREAD的结构也很庞大,包含着线程各种属性。其中第一行的TCB(Thread Control Block)信息尤为重要,里面的字段主要是供内核调度线程时使用。
Windows核心编程 进程与线程

ETHREAD 结构字段太多了,一般使用!thread来简化输出。

PEB,用户态数据结构

与描述进程用户态信息的PEB一样,NT内核定义了线程环境块(Thread Environment Block)来描述线程的用户态信息。
主要有用户态的栈空间,异常信息,线程本地存储等
Windows核心编程 进程与线程

创建进程的流程

Windows核心编程 进程与线程

  1. 打开执行文件,确定其名称,类型等前置资料,类似于C#中的EEClass
  2. 为新进程创建EPROCESS,进程空间,PEB
  3. 创建初始线程,状态为susepend
    这被称为主线程,然后这个线程会去创建更多的线程
  4. 通知CSRSS,类似新生儿上户口
  5. 初始线程开始执行
  6. 线程执行初始化动作,主要是加载依赖的dll
发表评论

评论已关闭。

相关文章