理解 COM 套间
2006-07-22 22:58:03 来源:WEB开发网我们知道,CPU中拥有众多的寄存器,EAX,EBX等,而CPU的指令一般都是通过寄存器来实现的。其中有一个寄存器叫做EIP(Instruction Pointer,指令寄存器),程序的有序执行,是靠它来完成的。看下面的例子: ……
假如我们的程序运行到mov eax,4,那么EIP就会指向该句代码所在的内存的地址。当这行代码执行完毕之后,那么EIP会自动加一,那么它就会指向mov ebx,4。而程序的执行就是靠EIP的不断增加来完成的(跳转的话,EIP就变成了跳转到的地址)。在Windows系统下,进程并不拥有EIP,EAX,那么只有进程,一个程序就无法运行。而拥有这些寄存器的是线程,所以说进程是静态的。
mov eax,4
mov ebx,5
……
我们知道一个CPU下只有一个EIP,一个EAX,也就是说同一时刻只能有一个线程可以运行,那么所说的多线程又是什么呢?事实上同一时刻也只有一个线程在运行,每个线程运行一段时间后,它会把它拥有的EIP,EAX等寄存器让出来,其它线程占有这些寄存器后,继续运行。因为这段时间很短,所以我们感觉不出来。这样我们就可以在一边听音乐的时候,一边玩俄罗斯方块了。为了实现不同的线程之间的转换,CPU要求操作系统维护一份固定格式的数据(该数据存在于内存中),这份数据叫做Task-State Segment(TSS),在这份数据结构里,维护着线程的EAX,EIP,DS等寄存器的内容。而CPU还有一个寄存器叫做Task Register(TR),该寄存器指向当前正在执行的线程的TSS。而线程切换事实上就是TR指向不同的TSS,这样CPU就会自动保存当前的EAX,EBX的信息到相应的TSS中,并将新的线程的信息加载到寄存器。
事实上线程不过上一些数据结构,这些结构保存了程序执行时候需要的一些信息。我们可以在windows提供的头文件中找到一些影子,安装VC后在它的include目录下有一个Winnt.h文件。在该文件中,我们可以找到这样一个struct(_CONTEXT)。这就是线程切换时需要的数据结构(我不确定Windows内部是否用的就是这个结构,但应该和这份数据相差无几)。 //
好了,线程就先讲这么多了。如果对进程和线程的内容感兴趣,可以到Intel的网站下载PDF格式的电子书《IA-32 Intel Architecture Software Developer’s Manual》,纸版的书也可以在这儿预定(他们会免费邮寄给你)。通过这套书,你可以对CPU的结构有一个清晰的认识。另外可以找几本讲解Windows系统的书看看,不过这类的好书不多,最著名的是《Advance Windows》,不过也是偏向于实用,对系统结构的讲解不多。也是,要完全去了解这部分的细节,太困难了,毕竟微软没有给我们提供这部分的源码。幸好,其实我们理解它大致的原理就足够用了。
// Context Frame
//
// This frame has a several purposes: 1) it is used as an argument to
// NtContinue, 2) is is used to constuct a call frame for APC delivery,
// and 3) it is used in the user level thread creation routines.
//
// The layout of the record conforms to a standard call frame.
//
typedef struct _CONTEXT {
//
// The flags values within this flag control the contents of
// a CONTEXT record.
//
// If the context record is used as an input parameter, then
// for each portion of the context record controlled by a flag
// whose value is set, it is assumed that that portion of the
// context record contains valid context. If the context record
// is being used to modify a threads context, then only that
// portion of the threads context will be modified.
//
// If the context record is used as an IN OUT parameter to capture
// the context of a thread, then only those portions of the thread''s
// context corresponding to set flags will be returned.
//
// The context record is never used as an OUT only parameter.
//
DWORD ContextFlags;
//
// This section is specified/returned if CONTEXT_DEBUG_REGISTERS is
// set in ContextFlags. Note that CONTEXT_DEBUG_REGISTERS is NOT
// included in CONTEXT_FULL.
//
DWORD Dr0;
DWORD Dr1;
DWORD Dr2;
DWORD Dr3;
DWORD Dr6;
DWORD Dr7;
//
// This section is specified/returned if the
// ContextFlags word contians the flag CONTEXT_FLOATING_POINT.
//
FLOATING_SAVE_AREA FloatSave;
//
// This section is specified/returned if the
// ContextFlags word contians the flag CONTEXT_SEGMENTS.
//
DWORD SegGs;
DWORD SegFs;
DWORD SegEs;
DWORD SegDs;
//
// This section is specified/returned if the
// ContextFlags word contians the flag CONTEXT_INTEGER.
//
DWORD Edi;
DWORD Esi;
DWORD Ebx;
DWORD Edx;
DWORD Ecx;
DWORD Eax;
//
// This section is specified/returned if the
// ContextFlags word contians the flag CONTEXT_CONTROL.
//
DWORD Ebp;
DWORD Eip;
DWORD SegCs; // MUST BE SANITIZED
DWORD EFlags; // MUST BE SANITIZED
DWORD Esp;
DWORD SegSs;
//
// This section is specified/returned if the ContextFlags word
// contains the flag CONTEXT_EXTENDED_REGISTERS.
// The format and contexts are processor specific
//
BYTE ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION];
} CONTEXT;
更多精彩
赞助商链接