7.1 层次式架构
1.系统分层模型
操作系统(包括应用环境、操作环境等)一般具有分层的结构特征,典型的就是UNIX系统的同心环,最里面是硬件,从里向外依次是kernel、共享函数库、应用程序3个层次。Windows CE的分层结构比较复杂(如图7-1所示),这是根据它适合嵌入式应用的特点所设计的。从提供者的角度来看,图中上面4层主要由微软公司维护开发,下面两层主要由嵌入式产品开发商根据产品需要开发。当然,这个划分并不绝对,而是根据产品需求来决定。需要说明的是,这里并没有一个单独的应用层,因为在大多数情况下,从嵌入式产品发布的方式来看,使用者的应用产品是捆绑销售(bundle)的,所以它们本身也是构成应用整合层的一部份。
图7-1 分层结构示意图
从接口的角度来看,一般系统开发环境包括应用和系统两个接口,用以支持系统和应用程序开发,例如在Windows平台中,SDK代表了应用层接口,而DDK代表了系统接口,两个接口之间就是操作系统的实体。如图7-1所示,Windows CE操作系统在中间两层,应用支持库的上部和操作系统层的上部(主要是CoreDLL.dll,应用支持库中的很多接口也是透过DLL导出到系统中的)以及下部具有接口性质,它们构成了Windows CE的应用接口和系统接口。因而,从某种角度来看,OAL起到了系统接口的作用,而上面两层就是应用接口的使用者。
从层与层的互动来看,主要的互动发生在相邻两层之间,但上面三层具有一定的向下跨层存取能力。限制存取在一定程度上有助于功能的区隔,清楚的接口也使我们可以方便地置换掉某一层。
2.组件剖析
从宏观的角度来看,系统的软件组件有CoreDLL、NK、设备管理模块、数据储存模块、GWES模块、通信模块、OAL模块以及两个比较特殊的部分——驱动程序模块和Win32系统服务模块,这两个模块和其他的模块在划分上有一些重叠。
n NK
NK透过nk.exe在系统中运行,它是Windows CE操作系统的真正核心,主要包含以下6类:功能处理器进程、内存管理、异常处理、系统内的通信机制、为其他部分提供核心应用程序例程(routine)、为系统范围内侦错提供的支持。
NK.exe的程序代码非常精简,始终以较高的优先级和处理器特权级别(privilege mode)执行。除了中断处理例程,系统内其他的进程不能中断kernel程序,并且在虚拟储存管理模式下,kernel程序是不被允许换出(swap out)的,它被存放在系统储存空间从0xC2000000起始的位置。NK的程序代码位于[CEROOT]/PRIVATE/WINDOWS CEOS/COREOS/NK目录下。
n CoreDLL
CoreDLL在系统中具有举足轻重的地位,它分隔了应用程序和操作系统的其他模块,是使系统稳定的保护性屏障。它提供了两类功能:第一类是外部应用程序系统功能的代理;第二类则提供了类似字符串处理、随机数生成、时间计算等基本支持函数。前者是主要的功能,它负责系统API的管理和安装应用程序,系统应用程序的核心软件中断过程就发生在这里。这个模块是透过CoreDLL.dll运行的,它是第一段被加载的系统共享程序代码。CoreDLL的程序代码位于[CEROOT]/PRIVATE/WINDOWS CEOS/COREOS/CORE目录下。
n 设备管理模块
这是Windows CE的设备管理核心,透过Device.exe来执行。它提供系统范围内基本的设备列表管理、随插即用管理、电源管理、I/O资源管理,并提供了设备驱动程序运作的基本机制。这一部分的程序代码位于[CEROOT]/PRIVATE/WINDOWS CEOS/COREOS/DEVICE目录下。
n 数据存储模块 Windows CE体系结构
数据存储模块主要是提供系统基本的数据存储能力,其中包括对象存储以及文件系统,这些功能主要是透过filesys.exe来执行。数据存储模块并没有开放全部的原始程序代码,主要开放的原始程序代码部分位于[CEROOT]/PRIVATE/WINDOWS® CEOS/
COREOS/FSD目录以及[CEROOT]/PRIVATE/WINDOWS CEOS/COREOS/STORAGE目
录下。
n GWES模块
Windows CE通过这个模块提供的图形接口提供了几个主要的功能:基本的绘图引擎、窗口管理、接口的事件机制等。这个模块运行时为gwes.exe。这个模块的主要程序代码位于[CEROOT]/PRIVATE/WINDOWS CEOS/COREOS/GWE目录下,与数据存储一样,它的原始程序代码也只开放了一部分。
n 通信模块
在整个Windows CE系统中,网络通信模块是最为独立的部分,它通过一系列的动态链接库来运作,这一部分因为牵涉到较多的Windows平台公用特性,所以原始程序代码开放的程度也最低。也正因为这个原因,本书并没有这一部分的详细分析。对于通信模块的结构,可以找到的程序代码包括TAPI的一个实例、NDIS的一个实例版本(pcx500),它们位于[CEROOT]/PRIVATE/WINDOWS CEOS/COMM目录下。
n OAL模块
这个模块没有确定的形态,主要包括和硬件相关的若干功能,例如处理器的专用支持程序代码、总线控制器的驱动、系统引导程序、系统初始化程序等。一般来说OAL不具有可移植性。
n 驱动程序模块
驱动程序模块实际上并不是一个单独的软件实体,而是一个由驱动程序实体构成的集合,它包括很多组件,执行也比较复杂。它实际上是多个其他模块的底层,例如网络通信模块的下层就是驱动层,NDIS实际上可以看作一个具体的类别驱动程序。此外它是分散在系统中的,有大量的驱动程序分布在OAL中,而系统服务和协议也可以看作是驱动程序,它们由不同的模块管理,例如services.exe和gwes.exe。
n Win32系统服务模块
Win32系统服务是Windows CE对应用程序提供的接口,多数公用的系统管理函数,如产生进程等,都是由NK负责。模块中的黑色虚线框,它表示系统实际运行时,此模块某一部分内容被包含在nk.exe中了。这个模块也是有特殊性的,类似驱动模块,它实际上也包含多个模块的上层对外功能接口。在早期的CE版本中有一组基本的API函数管理集合,系统和用户可以通过这组函数,将自行定义的接口注册到系统服务应用程序代理中,因为系统稳定性的缘故,目前这些函数只能在系统内部使用,例如和设备管理相关的Win32 API,就是通过这组函数注册的。
7.2 内核模块
7.2.1 Windows CE中的中断体系结构
Windows CE的中断体系由硬件中断、内核中断服务例程、OAL中断服务例程和IST程序组成。整个中断服务模型就是围绕着这5部分展开的。
图7-2是所示Windows CE中的中断体系结构的模型。
图7-2 中断体系结构模型
图7-2描述了中断过程中的主要转换过程,纵轴代表系统的抽象层次,横轴代表中断发生及处理的时间顺序。
系统最低层是硬件及其中断控制器。外围设备向处理器的中断信号线上发送中断信号,这时就产生了中断。
第二层是内核ISR。外设产生中断后,处理器立即转入中断服务向量表,一般也就是操作系统的中断服务向量表,然后搜索并执行内核阶段中断服务程序。由于外设的中断可能不仅是一个,有可能是多个中断而且有优先级,因此,内核级的中断服务程序主要做的就是禁止处理器上的所有具有相同和较低优先级的中断在本中断处理时发生中断。之后便进入到OAL的ISR例程。
第三层是OAL的ISR例程.这层由外设的生产商通过驱动实现其设备的特定功能,往往这部分程序会将集成在板级支持包BSP中。此后,OAL ISR既可以直接处理中断,也可以使用NKCallIntChain遍历已安装的ISR列表。主ISR或任何已安装的ISR随后执行任意工作,并且为该设备返回名为SYSINTR的映像中断。这里所说的处理中断,并未完成中断的全部功能,仅仅是完成了以下的简单功能。
A执行最小的中断处理,最小的中断处理指能够检验、答复产生中断的硬件,而把更多的处理工作留给IST。
B当ISR完成时返回中断ID(中断ID大部分是预定义的)。这个中断ID用来给IST标识中断,并且在IST返回后,通过这个ID通知内核此中断处理已经完成.可以释放资源,重新等待该中断的发生。
当然,如时钟这样非常简单的中断处理,可以不需要IST,如果不需要进一步执行IST,那么就返回SYSINTR_NOP。
最上层是驱动程序或应用程序的中断服务线程IST.在OAL ISR对中断进行简单处理后,IST就要具体地处理中断了,这包括从外设取回数据,通过特定协议和设备握手,将处理结果向GUI或者其他文件输出。在IST处理完后,必须返回中断ID,通知内核处理完毕。
对于有些应用场合,ISR可能并不是每次都希望通知IST进行处理.比如,每次发生中断时,ISR仅仅把设备的数据取回,存在缓冲区中,缓冲区未满时,ISR返回SYSINTR_NOP,等到缓冲区满了后,再返回SYSINTR,唤醒IST处理,这样就需要在两者间传递数据。
首先,在Config.bib文件中为ISR保留物理内存空间。Config.bib文件中已经为串口驱动保留了内存空间,大家可以将此作为例子,自己进行修改。在ISR中使用保留的内存空间。由于ISR运行在物理地址模式,因此ISR完成后启动IST前,还需要调用MMMapIoSpace函数,这个函数调用了VirtualAlloc和VirtualCopy函数,把特定的物理地址映像到虚拟地址中去。或者也可以自己显式地调用VirtualAlloc和VirtualCopy函数来实现映像功能。
另外,在可安装ISR中,由于内存可以被自由地动态分配,因此不需要在Config.bib中保留内存地址。
中断相关的API
OEMInterruptEnable函数的代码样例如下:
OEMInterruptEnable
BOOL OEMInterruptEnable(DWORD idInt,…)
{
BOOL bRet = TRUE;
switch(idInt)
{
case SYSINTR_POWER:
POWER_OFF_INT_CLR(1);
POWER_OFF_INT_MASK(1);
Break;
return bRet;
}
}
OEMInterruptEnable函数由内核调用,建立ISR和驱动程序的IST之间的映射关系。这个函数应当完成任何必须的操作来使设备有能力产生中断,同时驱动程序能接收并且处理中断。通常可能包括的操作有设置硬件优先级、使能端口和复位设备(以使设备能够产生中断)。
当设备驱动程序调用InterruptInitialize内核函数后,内核将调用OEMInterruptEnable。在本函数被执行的过程中,系统不应当发生抢占现象。OEMInterruptDisable的代码样例如下:
OEMInterruptDisable
BOOL OEMInterruptDisable(DWORD idInt)
{
…
switch(idInt)
{
case SYSINTR_POWER:
POWER_OFF_INT_MASK(0);
Break;
…
return bRet;
}
}
在OAL中必须实现一个能处理可安装驱动的函数例程。这个函数可以被用来卸载驱动程序。当需要卸载驱动程序并且已调用InterruptDisable时,内核会相应调用OEMInterruptDisable函数。在本函数被执行的过程中,系统不应该发生抢占的现象。本函数的调用参数指定了要关闭的中断号。函数OEMInterruptDone代码样例如下:
OEMInterruptDone
BOOL OEMInterruptDone(DWORD idInt)
{
…
switch(idInt)
{
case SYSINTR_POWER:
POWER_OFF_RISING_EDGE;
POWER_OFF_INT_MASK(1);
Break;
…
return bRet;
}
}
在系统处理中断的过程中,会将中断屏蔽。因此必须在中断处理完毕之后,调用相应的函数(OEMInterruptDone)清除中断屏蔽掩码。
当驱动程序调用InterruptDone时,内核会调用本函数。
7.2.2 Windows CE中的进程
由正文段(text)、用户数据段(user segment)以及系统数据段(system segment)共同组成一个进程执行环境,负责处理器、内存和外围等资源的分配和回收。进程是计算机系统资源的使用主体,是操作系统分配资源的基本单位。动态、独立、并行的Windows CE最多支持32个进程在系统中同时运行。
系统激活的时候,至少自动激活4个进程。第一个是NK.exe,用来提供操作系统中kernel的服务;第二个是FILESYS.EXE,用来提供相关文件系统的服务;第三个是GWES.EXE,用来提供对GUI系统的支持;第四个是DEVICE.EXE,用来加载和管理外围的驱动程序。它们占据虚拟地址的前4个slots,一个slot有32MB空间。
1.Windows CE进程简介
作为一先抢占式的、多任务的操作系统,Windows CE在系统之内最高支持32个正在运行的进程。每个进程由若干个线程组成,其中有一个为主线程。每一线程代表进程的一个独立的部分。进程也能创建未指定的数字的附加的线程。只有可用的系统资源才能限制实际的附加的线程数量。
从Windows CE 3.0开始,系统提供了256个优先级,0为最高优先级,255是最低的优先级。Windows CE 2.12中定义的8种优先级分别映射到了248~255。优先级255~248是为用户态下的应用程序线程所准备的。其余优先级更高的级别(247~0)则是为其他实时要求比较高的线程,如驱动、实时程序、内核线程所准备的。为了防止随机应用把系统的性能降级,OEM可能限定所有247点和零点之间的优先水平只能被应用在OEM指定应用程序中。
由于兼容旧的版本,GetThreadPriority and SetThreadPriority这两个旧的函数依然可以使用,但是建议程序员不要使用这两个函数,因为它们对应的是旧版本的8种优先级。在Windows CE.net中可以使用CeSetThreadPriority和CeGetThreadPriority来替代他们。CeSetThreadPriority用来设置线程的优先级,而CeGetThreadPriority从系统获取线程的优先级别。
Windows CE.net 中的优先级别大致分为如表7-1所示的4组。
表7-1 Windows CE.net中的优先级分组
Levels |
Description |
0到96 |
为实时要求比驱动强的实时程序保留 |
97 through 152 |
为基本的Windows CE驱动程序保留 |
153 through 247 |
为实时要求比驱动弱的实时程序保留 |
248 through 255 |
为非实时应用保留 |
2.Windows CE进程结构组成
进程由正文段(text)、用户数据段(user segment)以及系统数据段(system segment)共同组成,负责处理器、内存和外围等资源的分配和回收。进程是计算机系统资源的使用主体,是操作系统分配资源的基本单位。为了方便管理,在Windows CE中把进程当作对象(HANDLE hProc)。下面将简单介绍代表进程的数据结构的主要部分:
struct Process {
BYTE procnum; /* 00: ID of this process [ie: it's slot number] */
BYTE DbgActive; /* 01: ID of process currently DebugActiveProcess'ing this process */
BYTE bChainDebug; /* 02: Did the creator want to debug child processes? */
BYTE bTrustLevel; /* 03: level of trust of this exe */
#define OFFSET_TRUSTLVL 3 // offset of the bTrustLevel member in Process structure
LPPROXY pProxList; /* 04: list of proxies to threads blocked on this process */
HANDLE hProc; /* 08: handle for this process, needed only for SC_GetProcFromPtr */
DWORD dwVMBase; /* 0C: base of process's memory section, or 0 if not in use */
PTHREAD pTh; /* 10: first thread in this process */
ACCESSKEY aky; /* 14: default address space key for process's threads */
LPVOID BasePtr; /* 18: Base pointer of exe load */
HANDLE hDbgrThrd; /* 1C: handle of thread debugging this process, if any */
LPWSTR lpszProcName; /* 20: name of process */
DWORD tlsLowUsed; /* 24: TLS in use bitmask (first 32 slots) */
DWORD tlsHighUsed; /* 28: TLS in use bitmask (second 32 slots) */
PEXCEPTION_ROUTINE pfnEH; /* 2C: process exception handler */
LPDBGPARAM ZonePtr; /* 30: Debug zone pointer */
PTHREAD pMainTh; /* 34 primary thread in this process*/
PMODULE pmodResource; /* 38: module that contains the resources */
LPName pStdNames[3]; /* 3C: Pointer to names for stdio */
LPCWSTR pcmdline; /* 48: Pointer to command line */
DWORD dwDyingThreads; /* 4C: number of pending dying threads */
openexe_t oe; /* 50: Pointer to executable file handle */
e32_lite e32; /* structure containing exe header */
o32_lite *o32_ptr; /* o32 array pointer for exe */
LPVOID pExtPdata; /* extend pdata */
BYTE bPrio; /* highest priority of all threads of the process */
BYTE fNoDebug; /* this process cannot be debugged */
WORD wPad; /* padding */
PGPOOL_Q pgqueue; /* list of the page owned by the process */
#if HARDWARE_PT_PER_PROC
ulong pPTBL[HARDWARE_PT_PER_PROC]; /* hardware page tables */
#endif
};
n procnum:BYTE类别,目前进程的识别号码(ID),用来辨识不同的进程。
n pProxList:存放proxy的队列,LPPROXY结构的链接。
n hProc:这是此进程的句柄,在调用SC_GetProcFromPtr时使用。
n dwVMBase:DWORD类别,记录进程在内存所占区域中的基地址。
n pTh:一个进程可能拥有多个线程(详见线程介绍部分),pTh表示当前进程中的第一个线程。
n BasePtr:LPVOID类别,指向加载.EXE可执行文件的基底指针。
n lpszProcName:LPWSTR类别,记录进程的名称。
n PfnEH:进程例外处理器,PEXCEPTION_ROUTINE类别。
n pMainTh:此进程所拥有的主线程,当主线程结束后,进程也随之结束。
n pmodResource:PMODULE类别,MODULE结构在NK/INC/kernel.h中所定义。包含资源的模块指针,其中的资源可以被目前的进程用到。
n oe:openexe_t类别。指向可执行档句柄的指针。
以下结构由CreateProcess函数在创建进程和其主线程时填充的。
typedef struct _PROCESS_INFORMATION {
HANDLE hProcess;
HANDLE hThread;
DWORD dwProcessId;
DWORD dwThreadId;
} PROCESS_INFORMATION;
成员功能介绍如下。
n hProcess 返回代表新进程的句柄。这个句柄在所有引用这个进程对象的函数中代表本进程。
n hThread 返回代表主线程的句柄。这个句柄在所有引用这个线程对象的函数中代表本线程。
n dwProcessId 返回全局的进程标识符,用来代表本进程。这个ID从进程创建一直到进程死亡都是有效的。
n dwThreadId 返回全局的线程标识符,用来代表本线程。这个ID从线程创建一直到线程死亡都是有效的。
这个数据结构被填充后,将用来填充Process结构的各个域。
3.有关的函数简介(如表7-2所示)
表7-2 函数介绍
函 数 名 |
功 能 描 述 |
CeGetCallerTrust |
这个函数能返回进程的权限 |
CeGetThreadPriority |
这个函数能返回进程的优先级 |
CeGetThreadQuantum |
这个函数能返回线程占用处理器的时间量 |
CeSetThreadPriority |
这个函数设置了线程的优先级 |
CeSetThreadQuantum |
设置线程可以拥有的处理器占用时间 |
CeZeroPointer |
这个函数将一个被映射指向一个进程的指针转换成空指针 |
续表
函 数 名 |
功 能 描 述 |
CreateProcess |
创建新的进程 |
CreateThread |
在进程的上下文空间内,创建线程 |
ExitProcess |
结束进程以及它所有的线程 |
ExitThread |
结束一个线程 |
FreeLibraryAndExitThread |
将线程调用的DLL的引用计数减一,然后结束这个线程 |
GetCommandLine |
返回当前进程的command-line |
GetCurrentProcess |
返回当前进程的句柄 |
GetCurrentProcessId |
返回当前进程的ID |
GetCurrentThread |
返回当前线程的句柄 |
GetCurrentThreadId |
返回当前线程的ID |
GetExitCodeProcess |
返回特定进程结束时的状态(错误号) |
GetExitCodeThread |
返回特定进程结束时的状态(错误号) |
GetThreadPriority |
返回线程的优先级 |
GetThreadTimes |
获取和特定线程相关的时间片信息 |
IsProcessorFeaturePresent |
获取系统中支持的x86处理器的特性 |
OpenProcess |
打开已经存在的进程,返回进程对象 |
ResumeThread |
减少线程的悬挂计数,这样在任务调度时,就能使线程继续执行 |
SetThreadPriority |
这功能为指定的线程设置了优先级 |
Sleep |
这功能将当前的线程延缓执行一定间隔 |
SuspendThread |
挂起指定的线程 |
TerminateProcess |
终止进程和它所有的线程 |
TerminateThread |
终止指定的线程 |
ThreadProc |
指定了线程启动时要执行的用户态的函数 |
TlsAlloc |
为线程分配thread local storage (TLS) index |
TlsFree |
释放一个(TLS) index,以便重新分配 |
下面我们来具体看下其中几个对进程和线程比较重要的函数。
(1)CreateProcess
这个函数用来创建新的进程,运行新的程序。它创建了新的进程和它的主线程。新的进程将加载可执行文件。下面是函数的原型:
BOOL CreateProcess(
LPCWSTR lpszImageName,
LPCWSTR lpszCmdLine,
LPSECURITY_ATTRIBUTES lpsaProcess,
LPSECURITY_ATTRIBUTES lpsaThread,
BOOL fInheritHandles,
DWORD fdwCreate,
LPVOID lpvEnvironment,
LPWSTR lpszCurDir,
LPSTARTUPINFOW lpsiStartInfo,
LPPROCESS_INFORMATION lppiProcInfo
);
参数解释如下。
n lpszImageName 以null结尾的指针,指向可执行的模块。该字符串可以指定完全路径和文件名,或者相对路径。
n lpszCmdLine 以null结尾的指针,指向可执行的命令行。系统把一种无效的字符添加到命令行,修修串,以表明哪一文件正在被使用。
n lpszCmdLine可以为NULL.这样的话,系统会把lpszImageName中的字符串当作命令行。
如果lpszImageName和lpszCmdLine都非空,则* lpszImageName指定了执行模块的名称,而* lpszCmdLine代表了命令行。
如果文件名没有后缀的话,那么默认后缀为.EXE。
n lpsaProcess 保留,必须设置为NULL.
n LpsaThread 保留,必须设置为NULL.
n fInheritHandles 保留,必须设置为NULL.
n fdwCreate 规定附加的标记对进程的创建中的优先级控制。这些标记可以如7-3中的任意组合。
表7-3 进程创建中的优先级控制
值 |
描 述 |
CREATE_DEFAULT_ERROR_MODE |
暂时保留 |
CREATE_NEW_CONSOLE |
新的进程有自己的控制台,而非从父进程继承 |
CREATE_NEW_PROCESS_GROUP |
暂时保留 |
CREATE_SEPARATE_WOW_VDM |
暂时保留 |
CREATE_SHARED_WOW_VDM |
暂时保留 |
CREATE_SUSPENDED |
进程的主线程在被创建后立即进入挂起状态,直到ResumeThread被调用 |
CREATE_UNICODE_ENVIRONMENT |
暂时保留 |
DEBUG_PROCESS |
如果这个标志被设置,那么调用的进程将被视为被创建进程的调试进程。被创建进程的子进程也同样被调试。被调试进程产生的任何事件都将被传递到调试进程,只有调用CreateProcess函数的线程才可以调用WaitForDe- |
续表
值 |
描 述 |
DEBUG_ONLY_THIS_PROCESS |
功能和DEBUG_PROCESS标志一样,但是被调试进程的子进程不在调试范围内 |
DETACHED_PROCESS |
暂时保留 |
n lpvEnvironment 暂时保留不使用设置成NULL。
n lpszCurDir 暂时保留不使用设置成NULL。
n lpsiStartInfo 暂时保留不使用设置成NULL。
n lppiProcInfo 指向PROCESS_INFORMATION结构,这个数据结构用来接收新进程的标识信息。
函数返回值:非0代表成功,0代表失败。如果要得到详细的错误代码,可以调用GetLast-
Error函数。
(2)CreateThread
这个函数在调用进程的进程上下文中创建线程。
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes,
DWORD dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId
);
参数解释如下。
n lpThreadAttributes 暂时保留,必须设置成NULL.
n dwStackSize 一般情况下被忽略,除非STACK_SIZE_PARAM_IS_A_RESERVATION标志被使用,这时,dwStackSize参数指定了为要创建的线程保留的虚拟内存区域。当被忽略时,线程的堆大小是默认的。
n lpStartAddress 指定了应用程序中在线程被启动时要执行的函数。
n lpParameter 指向传递给线程的32位长的参数指针。
n dwCreationFlags 设置了线程被创建后的状态。这些状态可以是表7-4所示项目的组合:
表7-4 线程创建后的状态表
值 |
描 述 |
CREATE_SUSPENDED |
线程被创建后将立即被挂起,直到ResumeThread函数被调用使被创建的线程获得CPU的占用权。当此标志没有被设置时,线程在被创建后可以立即执行 |
STACK_SIZE_PARAM_IS_A_RESERVATION |
如果此标志被设置,参数dwStackSize则代表线程可以拥有的最大内存数量 |
n lpThreadId 32位长的指针,指向的空间中保存了线程的ID。
如果这个参数被设置成NULL。线程的ID将不被返回。返回值非空返回代表了某个线程的ID,NULL代表失败。
(3)CeSetThreadPriority
这个函数设置了实时线程的优先级。函数原型为:
BOOL CeSetThreadPriority(
HANDLE hThread,
int nPriority
);
参数解释如下。
n hThread 一个线程的句柄。
n nPriority 为线程设置的优先级。可以从0到255,其中0是最高优先级别。返回值为TRUE代表设置成功;FALSE代表失败。
n Remarks 当一个已经被阻塞的线程的优先级增加时,被调度程序将立即判断该线程是否需要状态改变。而当一个已经被阻塞的线程的优先级减少时,丝毫不会影响线程当前的状态。
此函数返回实时线程的优先级。
int CeGetThreadPriority(
HANDLE hThread
);
参数功能解释如下。
n hThread 线程的句柄。如果成功,则返回线程的优先级,否则返回THREAD_
PRIORITY_ERROR_RETURN。
这个函数仅仅返回线程的原始优先级,如果由于优先级逆转等原因,使得线程的实际优先级和原始优先级不同时,此函数返回的值可能会与实际线程的优先级不一致。
4.有关的数据结构
schedule.h中有关于线程时间的数据结构如下。
typedef struct THREADTIME {
struct THREADTIME *pnext;
HANDLE hTh;
FILETIME CreationTime; /*建立时间*/
FILETIME ExitTime; /*结束时间*/
FILETIME KernelTime; /*kernel-mode时间*/