Windows Via C/C++:线程实现细节
我们已经了解如何定义线程入口点函数、调用系统API创建执行指定函数的线程。本节将揭示这一切在系统内部是如何完成的。
图6-1描述了线程创建并完成初始化后的状态。调用CreateThread会使系统产生一个线程内核对象,其引用计数(Usage count)被初始化为2(创建线程的进程和线程本身都引用了该内核对象),其它属性也完成了初始化:暂停标置(Suspend count)被设置为1,线程退出码(Exit code)被设置为STILL_ACTIVE,内核对象状态被置为nonsignaled(Signaled)。
内核对象创建完成后,系统在当前进程中为新线程的线程栈分配内存,并在线程栈的高位写入两个值。第1个指是CreateThread函数的pvParam参数,然后是pfnStartAddr参数。
每个线程有自己的CPU寄存器组,被称为线程上下文(Context),线程的上下文反映了线程最后一次执行时其CPU寄存器的状态。WinNT.h中定义了CONTEXT结构对应线程的CPU寄存器组,线程的CONTEXT实例保存在其内核对象中。
线程上下文中最重要的两个寄存器是指令指针寄存器(Instruction pointer)和栈指针寄存器(Stack pointer)。由于线程是运行在进程地址空间内的,因此其栈中的地址就是进程地址空间中的地址。线程内核对象初始化时,其CONTEXT结构中的栈指针寄存器内容被设置为pfnStartAddr在线程栈中的地址,指令指针寄存器内容被设置为名为RtlUserThreadStart的函数的地址,该函数在NTDLL.dll中定义,基本框架如下所示:
VOID RtlUserThreadStart(PTHREAD_START_ROUTINE pfnStartAddr, PVOID pvParam) {
__try {
ExitThread((pfnStartAddr)(pvParam));
}
__except(UnhandledExceptionFilter(GetExceptionInformation())) {
ExitProcess(GetExceptionCode());
}
// NOTE: We never get here.
}
线程初始化完成后,系统会检查CreateThread是否传递了CREATE_SUSPENDED参数,如果没有的话,系统会把线程内核对象的暂停计数设置为0并马上调度线程,然后将线程上下文中的值加载到CPU的寄存器组中,由于线程指令指针寄存器指向RtlUserThreadStart,因此线程将以RtlUserThreadStart开始执行,RtlUserThreadStart又调用了CreateThread为线程设置的入口点函数pfnStartAddr,并在pfnStartAddr返回时调用ExitThread退出线程。要注意假如在pfnStartAddr执行时发生了未处理的异常,RtlUserThreadStart中的结构化异常处理框架将执行ExitProcess,导致整个进程的退出。
相关文档:
VB
If MSComm1.PortOpen = True Then MSComm1.PortOpen = False
MSComm1.CommPort = i1
MSComm1.PortOpen = True
MSComm1.InputMode = comInputModeBinary
MSComm1.InBufferCount = 0
& ......
Delphi 与 C/C++ 数据类型对照表
Delphi数据类型C/C++
ShorInt
8位有符号整数
char
Byte
8位无符号整数
BYTE,unsigned short
SmallInt
16位有符号整数
short
Word
16位无符号整数
unsigned short
Integer,LongInt
32位有符号整数
int,long
Cardinal,LongWord/DWORD
32位无符号整数
unsigned long
Int6 ......
1. static 变量
静态变量的类型 说明符是static。 静态变量当然是属于静态存储方式,但是属于静态存储方式的量不一定就是静态变量。 例如外部变量虽属于静态 存储方式,但不一定是静态变量,必须由 static加以定义后才能成为静态外部变量,或称静态全局变量。
2. 静态局部变量
静态局部变量属于静态存储方式,它具有以下 ......
一家之言,欢迎拍砖哈。
1、可以考虑先学习C.
大多数时候,我们学习语言的目的,不是为了成为一个语言专家,而是希望成为一个解决问题的专家。做一个有用的程序员,做一个赚钱的程序员。我们的价值,将体现在客户价值上,而不是语言写得好不好看。
C++是C的一个面向对象的解释,C++为C扩充了大规模工程应 ......
#pragma 指令可能是最复杂的了,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作。
#pragma 指令对每个编译器给出了一个方法,在保持与C 和C ++语言完全兼容的情况下,给出主机或操作系统专有的特征。
依据定义,编译指示是机器或操作系统专有的,且对于每个编译器都是不同的。
一、#pragma message
#pragma ......