windows session机制深入解析

原文:http://www.cppblog.com/dawnbreak/archive/2009/07/16/90291.html 

Sessions, Desktops and Windows Stations

session是由代表单个用户登录会话的所有进程和系统对象组成的。其中的对象包括所有的窗口,桌面和windows stations。桌面是特定session页的内存池并且被加载到内核存储区。这个区域正是session私有的GUI对象的存储区域。windows station基本上可以被描述为包含桌面和进程的安全边界。因此,一个session可以包含多个windows station,而每个windows station又可拥有多个桌面

只有被称为 winsta0 的windows station才被允许与用户交互。在winsta0下共被载入三个桌面:winlogon(登陆界面),缺省桌面(用户桌面),和Disconnect(? )。它们三个都有各自的显存,这就是为什么当你锁定工作站时你的主桌面会消失。当你锁定工作站时,屏幕由用户桌面切换到登录界面,并且两者之间并没有交互。在windows vista这一点更是体现的淋漓尽致。例如当你看到UAC弹出时,系统会将用户桌面的快照降低灰度,而在前端显示UAC窗口,UAC窗口是安全桌面(vista系统的新特性类似登录桌面)并且在你给予权限之前禁止你与用户桌面的交互。

其他windows station存在但并不与用户交互。例如:加载到‘service-0x0-3e7$’无用户交互windows station中的服务。另外也有些需要与用户交互的服务被加载到winsta0。

内存页是被所有用户所共享的,但是每个用户会将其各自的session空间映射到虚拟内存。session空间被划分到四个不同的区域:

  • session 结构存储区-内存控制器结构,其中包含session工作集
  • session映像存储区-保留一块私有的win32k.sys修改过的数据,一个sin32k,sys代码副本和原始数据副本,还有各种驱动
  • session视图存储区-包括桌面堆在内的session映射视图
  • session分页存储区-用于这个session被分页了的内存池

 正如前文所提到的,一个桌面正是被加载了显示信息的内核对象。其中包括窗口,菜单,还有钩子。session0是一个基础session,服务在其中运行,并且一般情况下也是控制台session。在windows Vista中session0仅仅用来运行服务,而控制台session一般在session1。下图显示了各自的关系,并且对比了vista和早期操作的区别。(来自our earlier post on Session 0 Application Compatibility Issues)


Session 0 in Windows XP / Windows Server 2003



Session 0 / Session 1 in Windows Vista 


我们在深入一点。在下图中展示了session0的基本组成,其中有个名为Bob的用户登入。正如你所看到的,Winsta0包含用户控制台中的所有进程还有任何被标记为可交互
(Interactive)的任何服务。本例中,Winsta0包括winlogon.exe,explorer.exe和其他需要与用户交互的服务。名为service-0x0-3e7$的Windows station 拥有在Local system帐号下且不与用户交互的所有服务。本例中service.exe正是这样的服务。,正如你所看到的连接线,将来自各个不同虚拟session的进程载入到单个windows station。SQL进程被载入到其自身的windows station并且使用自己的证书认证,所以它不属于其他两个windows station。

因此,我们可以将上图总结如下:

  1. 整个图展示的是session0.
  2. 在Bob帐号下的所有进程都载入到Winsta0。
  3. 在local system帐号下可交互进程载入到winsta0。
  4. 在local system帐号下不可交互进程载入到Service-0x0-3e7% windows station 。
  5. 在私有证书下启动的进程载入到其自己的windows station(像SQL)。

一个单独的桌面堆分配给一个单独的桌面对象。这个堆包含各种人机交互对象,包括窗口,目录和钩子。当应用程序需要引用一个人机交互对象时,它将会去调用user32.dll去分配该对象,并且分配的每一个交互对象都会占用一部分桌面堆。如果桌面堆趋于耗尽,你将会看到不正常显示或其他不正常现象。并且,如果session视图存储区耗尽,session将不能在创建更多的桌面堆。当然两者中的任何一个出现都是不好的。这就是或许为什么当你还有很多内存剩余的时候仍然会接到“内存耗尽错误”的原因。


当这种情况发生时,你可能会收到“初始化错误”伴随着视窗不正常显示。一个典型的错误是 0xc0000142,意思是 STATUS_DLL_INIT_FAILED。你可以从症状中得知引发问题的原因是由于单个桌面堆还是整个会话引起的。如果桌面堆耗尽,你仅仅会看到与该窗口堆相关的进程出现问题。如果是session视图存储区耗尽,你会看到整个session出现问题。


win32k.sys有一个固定的48M的存储空间分配给桌面堆。在终端服务中,这个空间是被每个session所共享,结果是仅仅留出20MB给桌面堆。所以,在终端服务器上比在个人电脑上更容易出现桌面堆耗尽的情况。但在vista和windows server2008中由于桌面堆是动态分配的,所以48M的限制不复存在。


注册表项 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystems 用来设定这个存储区的大小,它的值形如“%SystemRoot%system32csrss.exe ObjectDirectory=Windows SharedSection=1024,3072,512 Windows… ”

需要关注的是"SharedSection=1024,3072,512".  这三个值决定了将有多少KB的空间分配给桌面堆的各个部分。<span value=""
第一个值指示所有桌面共享堆的大小,用来存储全局句柄表和共享系统设置。默认值是1024KB,一般情况下不需要修改这个值。第二个值指示分配个每个在可交互windows station中桌面堆的大小,用来存储诸如钩子,菜单,字符串和窗口之类的对象,默认值是3072KB。登录的用户越多,创建的桌面就越多。结果是,所有桌面堆大小的总和增加以反映创建的桌面数增加。然而,每个桌面仅仅拥有3072KB的可交互桌面堆大小。第三个值指示分配个每个在不可交互windows station中桌面堆的大小,默认值是512KB,如果没有设定,将于第二个值相同。


在用户帐号下的每个服务进程都会由SCM(Service Control Manager )在不可交互window station下分配一个桌面。因此,每个这样的服务都会消耗一部分向SharedSection中第三个值设定的桌面堆的大小。在可交互和不可交互wndow station下的桌面堆的总大小必须在48M以内。所以,减小在sheareSection中第二或第三个值的大小会增加可以被创建的总桌面数的大小,相应的也会减少在各自桌面内科创建的钩子,菜单,字符串和窗口的数量。反之亦然。同样,增加SharedSection第三个值的大小会减少用户帐号下可运行的服务数量

参考文章:



  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值