每个线程都有它自己的一组C P U寄存器,称为线程的上下文

一旦内核对象创建完成,系统就分配用于线程的堆栈的内存。该内存是从进程的地址空间
分配而来的,因为线程并不拥有它自己的地址空间。然后系统将两个值写入新线程的堆栈的上
端(线程堆栈总是从内存的高地址向低地址建立)。写入堆栈的第一个值是传递给C r e a t e T h r e a d
的p v P a r a m参数的值。紧靠它的下面是传递给C r e a t e T h r e a d的p f n S t a r t A d d r参数的值。
每个线程都有它自己的一组C P U寄存器,称为线程的上下文。该上下文反映了线程上次运
行时该线程的C P U寄存器的状态。
线程的这组C P U寄存器保存在一个C O N T E X T结构(在
Wi n N T. h头文件中作了定义)中。C O N T E X T结构本身则包含在线程的内核对象中。
指令指针和堆栈指针寄存器是线程上下文中两个最重要的寄存器。记住,线程总是在进程
的上下文中运行的。因此,这些地址都用于标识拥有线程的进程地址空间中的内存。当线程的
内核对象被初始化时, C O N T E X T结构的堆栈指针寄存器被设置为线程堆栈上用来放置p f n S t a r t -
A d d r的地址。指令指针寄存器置为称为B a s e T h r e a d S t a r t的未文档化(和未输出)的函数的地址
中。该函数包含在K e r n e l 3 2 . d l l模块中(这也是实现C r e a t e T h r e a d函数的地方)。图6 - 1显示了它
的全部情况。

下面是B a s e T h r e a d S t a r t函数执行的基本操作:

当线程完全初始化后,系统就要查看C R E AT E _ S U S P E N D E D标志是否已经传递给
C r e a t e T h r e a d。如果该标志没有传递,系统便将线程的暂停计数递减为0,该线程可以调度到一
个进程中。然后系统用上次保存在线程上下文中的值加载到实际的C P U寄存器中。这时线程就
可以执行代码,并对它的进程的地址空间中的数据进行操作。
由于新线程的指令指针被置为B a s e T h r e a d S t a r t,因此该函数实际上是线程开始执行的地方。
B a s e T h r e a d S t a r t的原型会使你认为该函数接收了两个参数,但是这表示该函数是由另一个函数
来调用的,而实际情况并非如此。新线程只是在此处产生并且开始执行。B a s e T h r e a d S t a r t认为
它是由另一个函数调用的,因为它可以访问两个函数。但是,之所以可以访问这些参数,是因
为操作系统将值显式写入了线程的堆栈(这就是参数通常传递给函数的方法)。注意,有些
C P U结构使用C P U寄存器而不是堆栈来传递参数。对于这些结构来说,系统将在允许线程执行
B a s e T h r e a d S t a r t函数之前对相应的寄存器正确地进行初始化。
当新线程执行B a s e T h r e a d S t a r t函数时,将会出现下列情况:
• 在线程函数中建立一个结构化异常处理(S E H)帧,这样,在线程执行时产生的任何异常情
况都会得到系统的某种默认处理(关于结构化异常处理的详细说明参见第2 3、2 4和2 5章)。
• 系统调用线程函数,并将你传递给C r e a t e T h r e a d函数的p v P a r a m参数传递给它。
• 当线程函数返回时, B a s e T h r e a d S t a r t调用E x i t T h r e a d,并将线程函数的返回值传递给它。
该线程内核对象的使用计数被递减,线程停止执行。
• 如果线程产生一个没有处理的异常条件,由B a s e T h r e a d S t a r t函数建立的S E H帧将负责处理
该异常条件。通常情况下,这意味着向用户显示一个消息框,并且在用户撤消该消息框时,
BzsethreadStart调用ExitThread,以终止整个进程的运行,而不只是终止线程的运行。
注意,在B a s e T h r e a d S t a r t函数中,线程要么调用E x i t T h r e a d,要么调用E x i t P r o c e s s。这意味
着线程不能退出该函数,它总是在函数中被撤消。这就是B a s e T h r e a d S t a r t的原型规定返回
V O I D,而它从来不返回的原因。
另外,由于使用B a s e T h r e a d S t a r t,线程函数可以在它完成处理后返回。当B a s e T h r e a d S t a r t
调用线程函数时,它会把返回地址推进堆栈,这样,线程函数就能知道在何处返回。但是,
B a s e T h r e a d S t a r t不允许返回。如果它不强制撤消线程,而只是试图返回,那么几乎可以肯定会
引发访问违规,因为线程堆栈上不存在返回地址,并且B a s e T h r e a d S t a r t将试图返回到某个随机
内存位置。
当进程的主线程被初始化时,它的指令指针被设置为另一个未文档化的函数,称为
B a s e P r o c e s s S t a r t。该函数几乎与B a s e T h r e a d S t a r t相同,形式类似下面的样子:
130计计第二部分编程的具体方法
下载

进程上下文是指在一个进程执行期间,CPU的所有寄存器的值、进程的状态以及堆栈的内容的总和。它包括用户级上下文和系统级上下文。用户级上下文包括用户的程序块、数据块、运行时的堆和用户栈等组成的用户空间信息。而系统级上下文包括进程标识信息、进程现场信息、进程控制信息(包含进程表、页表、打开文件表等)和系统内核栈等组成的内核空间信息。 线程上下文与进程上下文类似,但是线程之间共享同一进程的地址空间,所以在切换线程上下文时,不需要切换地址空间,只需要切换线程寄存器状态即可。一次线程上下文切换发生在一个进程内的不同线程之间。 上下文是发生在CPU响应硬件断时,保存当前正在执行的上下文,然后切换到断处理程序的上下文上下文保存了断前的进程上下文信息,以及断处理程序执行所需要的寄存器和堆栈等。 上下文的切换是由硬件自动完成的,它会保存当前正在执行的进程或线程上下文,切换到断服务程序的上下文,等断处理完成后再切换回原来的上下文。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Linux:上下文,进程上下文上下文概念,上下文切换](https://blog.csdn.net/W546556/article/details/126300300)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [系统调用,上下文切换(cpu上下文,进程上下文线程上下文上下文,进程切换,线程切换)](https://blog.csdn.net/aa541850383/article/details/125363264)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值