会话(Session) 工作区(Workstation) 桌面(Desktop)之简介 

Friday, October 29, 2010 12:40:00 PM

问题:

什么是会话,工作区,桌面?他们之间有什么关系?

解决方法:

本文将探讨关于他们的基本概念。

会话由所有的进程和系统对象构成,代表一个单独的用户登录会话。这些对象包括:窗口,桌面和windows工作站(windows station)。桌面是一个特定于会话的分页池区域,加载在内核的内存空间。会话私有的GUI对象都是从这个区域分配的。Windows工作站是包含桌面和进程的安全边界。总之,会话可能包含多于一个的Windows工作站,而每个Windows工作站可以有多个桌面。

只允许一个Windows工作站与控制台用户交互,这个工作站就是winstat0。在这个工作站里面会加载三个桌面:Winlogon(登陆桌面),Default(用户桌面),Disconnect。这三个都有独立的逻辑显示,这也是为什么当你锁定工作站时,主桌面就不见了。当锁定工作站时,显示从Default转到了Winlogon并且两者之间没有用户交互。Windows vista系统中,这点更加明显,当弹出UAC提示时,它会做一个缺省桌面的屏幕截图,在前台显示UAC窗口,在后面以灰掉的状态显示该截图。UAC窗口是安全桌面(vista中新加入的,类似于登录桌面)的一部分,在你提供输入之前,它不允许你跟Default桌面交互。

其他的Windows工作站并不与用户交互。例如,服务加载到"Service-0x0-3e7$"这个非交互Windows工作站中,而那些需要和终端用户交互的服务是将被加载到Winsta0中。
某一用户的所有页都使用相同的内存页,但是每个用户在虚拟内存中有他们自己的会话空间。会话空间被划分为4个不同的区域:
会话结构(session structure)-内存管理控制结构,包括会话工作集列表。
会话镜像空间-存放Win32k.sys已修改数据的私有拷贝,Win32k.sys代码,未修改数据以及各种驱动的单一拷贝。
会话视图空间-会话映射视图,包括桌面堆
会话分页池-用于这个会话的分页池内存
正如上面提到的,桌面是一个对象,逻辑显示接口加载到它下面,包括:窗口,菜单和钩子。Session 0是基本的会话,服务运行在它下面,通常也是控制台会话,在windows vista/7中,这个session已经专门用来运行服务了,console session通常是session 1而非session 0。用Querysession可以看到它们的详细信息(如下图所示),这两个session的名字分别是services,console。

  Query session to get session 0 and session 1  

下图显示了sessions,windows工作站,桌面之间的关系,比较了vista/Windows 7和之前的版本(windows xp/windows server 2003)。
session 0 and session 1 in windows vista or windows 7

windows vista中的session 0和session 1

Session 0 in windows xp/Windows server 2003

Session 0 in windows xp/windows server 2003

现在让我们用这个例子做更进一步的研究。在下图中(适用于windows vista/7之前的系统,windows xp和windows server 2003),我们查看一个名为Bob的用户登录会话-session 0。正如你所见,winsta0包含了来自用户控制台会话的进程和任何标志为"Interactive"的服务。这里主要包括Winlogon.exe,Explorer.exe和其他任何 需要与用户交互的服务。工作站Service-0x0-3e7$包含任何运行在Local System账户下且不需要与用户交互的服务,这里只显示services.exe。通过那个连接条,你可以看到来自不同虚拟会话的进程可以加载到单个Windows工作站中。SQL进程在它自己的工作站和证书下工作,所以它不包含在任何其他的工作站中。
windows stations

这里,重申上图中各个部分的关系:
1.这个图表示的是Session 0
2.运行在Bob账户下的所有进程都被加载到Winsta0
3.运行在Local System下的交互式进程也被加载到Winsta0
4.运行在Local System下的非交互式进程被加载到Service-0x0-3e7%
5.运行在他们自己身份下的进程加载到他们自己的Windows工作站中,例如SQL
每个桌面对象都有一个桌面堆。这个堆里存放着各种用户界面对象,例如窗口,菜单和钩子。当应用程序需要画一个用户界面对象时,它会调用user32.dll中的代码来分配这个对象。我想你会猜测,每个界面元素都需要桌面堆的资源。如果桌面堆大量减少了,你就会看到类似显示崩溃或者其他诡异的现象。这是为什么机器的空闲内存还有很多,却提示你内存不足的部分原因。
当这种事情发生时,除了获得可见的崩溃信息外,你可能还会获得初始化错误信息。你可能见到的一个典型错误是0xc0000142(表示STATUS_DLL_INIT_FAILED)。基于表象,你可以辨别出这个问题是单个桌面的问题还是整个会话的。
对于桌面堆,Win32k.sys有固定的48M内核地址空间。对于终端服务(Terminal Services),这个空间要和会话存储共享,所以只剩下20M的空间给桌面堆。所以,正如你所见,在终端服务器上比在标准的机器上更容易发生桌面堆资源耗尽。对于Windows vista之前的操作系统的确如此。在Windows vista/7和windows server 2008/2008 r2中,桌面堆是动态分配的,从而就没有48M内存的限制。
通过注册表,可以有限地修改内存处理方式:在键HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystemsx下面,查找windows值,这是一个长字符串,它的值类似:%SystemRoot%system32csrss.exe ObjectDirectory=Windows SharedSection=1024,3072,512 Windows...我们所感兴趣的部分是"SharedSection=1024,3072,512"。这里的三个值决定了桌面堆中每个组件会分配多少内存(以KB为单位)。在这里警告一下:请不要一时兴起而修改这些值,如果把第二个或者第三个值改得太高的话,你可能就无法启动系统了,因为内核无法分配内存以启动Session 0。通常值在8MB以下是安全的,但是也有可能会出现问题,通常不需要设置的太高,除非有已安装的程序表现异常。我们建议以512KB为单位来升高这个值,只要能解决你遇到的问题即可。
第一个值是共享堆大小,对所有的桌面都一样。它用于存储全局句柄表和共享的系统设置,缺省值是1024KB,正常情况下,你不需要修改这个值。第二个值表示交互式工作站中每个桌面所分配桌面堆的大小,它用于存储用户对象如钩子,菜单,字符串和窗口,缺省值是3072KB。登录的用户越多,创建的桌面也就越多。结果,总的交互式桌面堆增大以反映出创建的桌面数量。然而,每个桌面都会有一个3072KB的交互式桌面堆。第三个值表示非交互式工作站中每个桌面所分配桌面堆的大小,缺省值是512KB,如果这个值没有设置,它将使用和交互式桌面一样的设置。
在某一用户帐号下创建的每个服务进程都将在SCM(Service ControlManager)创建的Windows工作站中分配一个新的桌面。因而,每个这样的服务都将消耗SharedSection中第三个值大小的桌面堆。交互式和非交互式工作站所使用的桌面堆必须满足48M系统缓存。这样,减少第二或第三个值可以增加能创建的桌面个数,但是会减少在每个桌面中可以创建的钩子,菜单,字符串和窗口数量。相反的,如果增大第二个值,会减少可以创建的桌面数量,却增加每个桌面中可创建的钩子,菜单,字符串和窗口数量。同样,增加第三个值会减少系统中可以运行的用户账户服务数量。

希望这里基本解释了Sessions,Windows station和desktop的概念,以及他们之间的关系。更深入的内容请参看如下资源:
KB126962 "Out of Memory" error message appears when you have a large number of programs running
KB142676 Overcoming User32.dll Initialization Failure Errors
NT Debugging Blog: Desktop Heap Overview

参考:http://blogs.technet.com/b/askperf/archive/2007/07/24/sessions-desktops-and-windows-stations.aspx

转载于:http://windobe.com/%E4%BC%9A%E8%AF%9Dsession-%E5%B7%A5%E4%BD%9C%E5%8C%BAworkstation-%E6%A1%8C%E9%9D%A2desktop%E4%B9%8B%E7%AE%80%E4%BB%8B.aspx