windows 子系统认识(1)

时间:2021-06-16 20:26:49

环境: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线程同时来处理请求