windows 子系统认识(1)
环境:XP
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystems]
"Windows"=%SystemRoot%\system32\csrss.exe ObjectDirectory=\Windows SharedSection=1024,3072,512 Windows=On SubSystemType=Windows ServerDll=basesrv,1
ServerDll=winsrv:UserServerDllInitialization,3 ServerDll=winsrv:ConServerDllInitialization,2 ProfileControl=Off MaxRequestThreads=16
ServerDll等号后面是动态库的文件名,如basesrv.dll。逗号后面的是这个库注册的序号。如basesrv.dll的就是1
冒号后面的名字是子系统加载这个动态库时候调用的函数名,如果没有提供,就默认是“ServerDllInitialization”
上面说到注册,子系统csrss.exe用一个数组来保存这些注册的动态库。
这个数组名叫 CsrLoadedServerDll,这个变量是在csrsrv.dll中,一共只有4个元素。每个元素是一个_CSR_SERVER_DLL结构。包括上面注册表提供的3个,再加上csrss.exe初始化时,提供的一个序号0的元素,一共4个。
其实csrss只是一个外壳,很多处理函数都是在csrsrv.dll中。
csrss.exe在初始化时候,调用csrsrv.dll的导出函数
int __stdcall CsrServerInitialization(unsigned int argc, char **argv)
{
//这个函数里面会创建那个核心LPC端口"\\Windows\\ApiPort",并且会创建一个线程CsrApiRequestThread专门来处理来自这个端口的各种LPC请求
int __stdcall CsrApiPortInitialize();
//这个函数里面会创建LPC端口"\\Windows\\SbApiPort",并且会创建一个线程CsrSbApiRequestThread专门来处理来自这个端口的各种LPC请求
int __stdcall CsrSbApiPortInitialize();
int __stdcall CsrParseServerCommandLine(unsigned int argc, char **argv)
}
CsrParseServerCommandLine就会解析上面注册表提供的参数。逐个加载进来。并为每个dll申请一个_CSR_SERVER_DLL结构。
接着调用dll提供的初始化函数,如上面注册表的就是那些冒号后面的函数。参数就是_CSR_SERVER_DLL结构。
这样每个dll都可以有一次初始化提供自己私有数据初始化_CSR_SERVER_DLL结构的机会。
最重要的一个私有数据字段是_CSR_SERVER_DLL->ApiDispatchTable。这个字段指明一个函数分发表。
以后"\\Windows\\ApiPort" 这个LPC有请求的时候,一般客户端发起请求是,是调用下面的函数:CsrClientCallServer()
Status = CsrClientCallServer(
&m,
CaptureBuffer,
CSR_MAKE_API_NUMBER( CSRSRV_SERVERDLL_INDEX,CsrpClientConnect),
sizeof( *a )
);
CsrApiRequestThread会根据其中的APINUMBER来索引对应的_CSR_SERVER_DLL结构。和
_CSR_SERVER_DLL->ApiDispatchTable[xxx]处理函数,所以这个apinumber比较特殊,它能够索引对应的dll和对应的分发处理函数。
。。
PS:MaxRequestThreads字段是CsrApiRequestThread线程的个数。默认是16个
CsrApiRequestThread线程在处理请求的时候,会检测下当前的CsrApiRequestThread线程数有没超过这个数,如果没的话,会启动一个新的CsrApiRequestThread线程同时来处理请求