windows中的会话概念的总结
转载请标明是引用于 http://blog.csdn.net/chenyujing1234
欢迎大家拍砖!
一、参考: http://blog.csdn.net/zacklin/article/details/7579217
以前我一直不理解Windows Session(会话)倒底是一个什么概念,总是感觉这个概念很虚,现在理解了一点。写下来做一个备忘。简单的说,用户登陆到windows系统之后,不管该用户是本地登陆的,还是远程登陆,系统都会为这个用户分配一个新的会话ID(SID)。也就是说会话与用户的登录是相关连的,没有用户登录就不存在会话。因此,会话的含义是指用户登录之后的一种运行的环境。我们先看看书上是怎么说的!
会话管理器(\Windows\System32\Smss.exe)是系统中第一个创建的用户态模式进程,负责完成执行体和内核的初始化工作的内核模式系统线程在最后阶段创建了实际的Smss进程(这段摘自: 《深入解析Windows操作系统(第4版)》80页)。
在启动Windows的过程中,会话管理器负责许多重要的步骤,比如打开额外的页面文件、执行延迟的文件改名和删除操作、创建系统环境变量。它也将子系统进程(通常只有
Csrss.exe)和winlogon.exe进程启动起来,winlogon进程依次会创建其他的系统进程。
在注册表的HKLM\SYSTEM\CurrentControlSet\Control\Session Manager 下面,你可以放到放多配置信息,它们驱动了Smss的初始化步骤。

Smss中的主线程在执行了这些初始化步骤后,一直在Csrss和Winlogon的进程句柄上等待。如果这两个进程中的任何一个非正常终止了,则Smss让系统崩溃掉(崩溃代码是STATUS_SYSTEM_PROCESS_TERMINATED或0xC000021A),因为Windows要依赖于这两个进程的存在才能运行得下去。
同时,Smss等待加载子系统的请求、调试事件,以及创建新的终端服务器会话(terminal server sessions)的请求。
终端服务会话(Terminal Services session)的创建是由Smss来完成的。当Smss接到一个创建会话的请求时,它
首先调用NtSetSystemInformation,请求建立内核模式的会话数据结构。这又依次调用内部的内存管理器函数MmSessionCreate,该函数建立起会话虚拟地址空间,该地址空间中包含会话中的换页内存池,以及由Win32子系统的内核模式部分(win32k.sys)和其他的会话空间设备驱动程序所分配的、属于每个会话的数据结构。
然后,Smss为该会话创建Winlogon和Csrss的实例。
Windows系统是支持多会话的,因此会话空间(session space)包含了一些针对每个会话的全局信息。所以会话空间是用来管理会话的。那么会话具体包含些什么呢?
会话(session)是由进程和其他的系统对象(比如窗口站、桌面和窗口)构成的,它们代表了一个用户的工作站登录会话。会话具体是由如下几个部分组成的:
1. 每个会话包含一个单独的win32k.sys
2. 专门的换页池区域
3. 私有windows子系统和登陆进程的拷贝
4. 系统空间中被映射的空间,被称为会话空间的区域
(参考: 《深入解析Windows操作系统(第4版)》 414页)
现在我把会话同进程做一个比较,发现他们之间有一些相似之处:
1. 都提供一个执行的环境
2. 都有一个私有空间
进程是为了内部的执行的线程提供一个空间和环境,而会话则是为内部所有的进程提供一个执行的空间和环境。(这是我总结的,感觉总结的很好,便于大家理解会话的概念)
X86会话空间的布局,如下图:(本人手工绘制 参考:《深入解析Windows操作系统(第4版)》 419页)

也就是说默认情况下会话空间的大小是8+4+20+16=48M
在我的机器上做如下的实验(通过windbg.exe双机调试看到的):
lkd> !sessionSessions on machine: 1Valid Sessions: 0Current Session 0
可以看出我的机器上面只有一个会话,因为是我的机器,只有我在登陆。
调用!sprocess 显示该会话数据结构的地址和该会话中的进程
lkd> !sprocessDumping Session 0_MM_SESSION_SPACE b85dc000 这里就是会话空间的地址_MMSESSION b85dc15cPROCESS 8a11a268 SessionId: 0 Cid: 028c Peb: 7ffdf000 ParentCid: 0190 DirBase: 0aa00060 ObjectTable: e1b01120 HandleCount: 346. Image: csrss.exePROCESS 8a2d0318 SessionId: 0 Cid: 02a4 Peb: 7ffdf000 ParentCid: 0190 DirBase: 0aa00080 ObjectTable: e18c70b0 HandleCount: 581. Image: winlogon.exePROCESS 8a349da0 SessionId: 0 Cid: 02d0 Peb: 7ffda000 ParentCid: 02a4 DirBase: 0aa000a0 ObjectTable: e1e8da78 HandleCount: 266. Image: services.exe…….
我现在查看会话的结构
lkd> dt nt!_MM_SESSION_SPACE b85dc000 +0x000 ReferenceCount : 0x15 +0x004 u : __unnamed +0x008 SessionId : 0 +0x00c SessionPageDirectoryIndex : 0x18626 +0x010 GlobalVirtualAddress : 0xb85dc000 _MM_SESSION_SPACE +0x014 ProcessList : _LIST_ENTRY [ 0x8a11a31c - 0x89b98c8c ] +0x01c NonPagedPoolBytes : 0 +0x020 PagedPoolBytes : 0 +0x024 NonPagedPoolAllocations : 0 +0x028 PagedPoolAllocations : 0 +0x02c NonPagablePages : 0x17 +0x030 CommittedPages : 0x5e4 +0x038 LastProcessSwappedOutTime : _LARGE_INTEGER 0x0 +0x040 PageTables : 0x8a0bb3e8 _MMPTE +0x044 PagedPoolMutex : _FAST_MUTEX +0x064 PagedPoolStart : 0xb9800000 +0x068 PagedPoolEnd : 0xb9bfffff +0x06c PagedPoolBasePde : 0xc0602e60 _MMPTE +0x070 PagedPoolInfo : _MM_PAGED_POOL_INFO +0x094 Color : 0xba6 +0x098 ProcessOutSwapCount : 5 +0x09c ImageList : _LIST_ENTRY [ 0x8a355ea0 - 0x8a1de1e8 ] +0x0a4 GlobalPteEntry : 0xc05c2ee0 _MMPTE +0x0a8 CopyOnWriteCount : 0x13 +0x0ac SessionPoolAllocationFailures : [4] 0 +0x0bc AttachCount : 0 +0x0c0 AttachEvent : _KEVENT +0x0d0 LastProcess : (null) +0x0d8 Vm : _MMSUPPORT +0x118 Wsle : 0xbcc0003c _MMWSLE +0x11c WsLock : _ERESOURCE +0x154 WsListEntry : _LIST_ENTRY [ 0x80561b58 - 0x80561b58 ] +0x15c Session : _MMSESSION +0x198 Win32KDriverObject : _DRIVER_OBJECT +0x240 WorkingSetLockOwner : (null) +0x244 PagedPool : _POOL_DESCRIPTOR +0x126c ProcessReferenceToSession : 43 +0x1270 LocaleId : 0x409
来自微软官方的C结构的定义如下:
typedef struct _MM_SESSION_SPACE{ // // This is a pointer in global system address space, used to make various // fields that can be referenced from any process visible from any process // context. This is for things like mutexes, WSL chains, etc. // struct _MM_SESSION_SPACE *GlobalVirtualAddress; LONG ReferenceCount; union { ULONG LongFlags; MM_SESSION_SPACE_FLAGS Flags; } u; ULONG SessionId; // // This is the list of the processes in this group that have // session space entries. // LIST_ENTRY ProcessList; LARGE_INTEGER LastProcessSwappedOutTime; // // All the page tables for session space use this as their parent. // Note that it's not really a page directory - it's really a page // table page itself (the one used to map this very structure). // // This provides a reference to something that won't go away and // is relevant regardless of which process within the session is current. // PFN_NUMBER SessionPageDirectoryIndex; // // This is the count of non paged allocations to support this session // space. This includes the session structure page table and data pages, // WSL page table and data pages, session pool page table pages and session // image page table pages. These are all charged against // MmResidentAvailable. // SIZE_T NonPageablePages; // // This is the count of pages in this session that have been charged against // the systemwide commit. This includes all the NonPageablePages plus the // data pages they typically map. // SIZE_T CommittedPages; // // Start of session paged pool virtual space. // PVOID PagedPoolStart; // // Current end of pool virtual space. Can be extended to the // end of the session space. // PVOID PagedPoolEnd; // // PTE pointers for pool. // PMMPTE PagedPoolBasePde; ULONG Color; LONG ResidentProcessCount; ULONG SessionPoolAllocationFailures[4]; // // This is the list of system images currently valid in // this session space. This information is in addition // to the module global information in PsLoadedModuleList. // LIST_ENTRY ImageList; LCID LocaleId; // // The count of "known attachers and the associated event. // ULONG AttachCount; KEVENT AttachEvent; PEPROCESS LastProcess; // // This is generally decremented in process delete (not clean) so that // the session data page and mapping PTE can finally be freed when this // reaches zero. smss is the only process that decrements it in other // places as smss never exits. // LONG ProcessReferenceToSession; // // This chain is in global system addresses (not session VAs) and can // be walked from any system context, ie: for WSL trimming. // LIST_ENTRY WsListEntry; // // Session lookasides for fast pool allocation/freeing. // GENERAL_LOOKASIDE Lookaside[SESSION_POOL_SMALL_LISTS]; // // Support for mapping system views into session space. Each desktop // allocates a 3MB heap and the global system view space is only 48M // total. This would limit us to only 20-30 users - rotating the // system view space with each session removes this limitation. // MMSESSION Session; // // Session space paged pool support. // KGUARDED_MUTEX PagedPoolMutex; MM_PAGED_POOL_INFO PagedPoolInfo; // // Working set information. // MMSUPPORT Vm; PMMWSLE Wsle; PDRIVER_UNLOAD Win32KDriverUnload; // // Pool descriptor for less than 1 page allocations. // POOL_DESCRIPTOR PagedPool; #if (_MI_PAGING_LEVELS >= 3) // // The page directory that maps session space is saved here so // trimmers can attach. // MMPTE PageDirectory; #else // // The second level page tables that map session space are shared // by all processes in the session. // PMMPTE PageTables; #endif #if defined (_WIN64) // // NT64 has enough virtual address space to support per-session special // pool. // PMMPTE SpecialPoolFirstPte; PMMPTE SpecialPoolLastPte; PMMPTE NextPdeForSpecialPoolExpansion; PMMPTE LastPdeForSpecialPoolExpansion; PFN_NUMBER SpecialPagesInUse;#endif LONG ImageLoadingCount; #if DBG ULONG Debug[MM_SESS_COUNTER_MAX]; MM_SESSION_MEMORY_COUNTERS Debug2[MM_SESS_MEMORY_COUNTER_MAX];#endif } MM_SESSION_SPACE, *PMM_SESSION_SPACE;
查看会话空间的内存使用,调用!vm 4命令
lkd> !vm 4... Terminal Server Memory Usage By Session: Session Paged Pool Maximum is 4096K Session View Space Maximum is 49152K Session ID 0 @ b85dc000: Paged Pool Usage: 0K Commit Usage: 6032K
现在我们清楚了,当用户登陆到系统中之后,用户下所有的进程都属于这个会话空间。在每个进程的PEB当中就有SessionID。
typedef struct _PEB{ BYTE Reserved1[2]; BYTE BeingDebugged; BYTE Reserved2[1]; PVOID Reserved3[2]; PPEB_LDR_DATA Ldr; PRTL_USER_PROCESS_PARAMETERS ProcessParameters; BYTE Reserved4[104]; PVOID Reserved5[52]; PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine; BYTE Reserved6[128]; PVOID Reserved7[1]; ULONG SessionId;} PEB, *PPEB;
该结构最后一个成员就是SessionId。
那么这里就产生一个问题了,同一台机器上面分别属于不同会话空间下的进程之间如何通讯呢?微软的MSDN里面的一些API就说的很清楚了。
我举一个例子吧。如CreateFileMapping MSDN的描述在 http://msdn.microsoft.com/en-us/library/aa366537(VS.85).aspx
lpName 如果使用"Global\" or "Local\" 作用范围是全局的。
今天先写到这儿了!
在局域网中,如果不得已使用XP作为共享文件服务器,经常会出现“连接数达到上限”的错误,这时唯一的办法就是去XP里断开一些空闲的连接,XP默认空闲连接等待时间为15分钟,如上图所示,我们可以将其改为1分钟,一定程度上会减少达到连接上限的频率,这可以通过命令:net config server /autodisconnect:1来完成,修改后的配置如下:

但是如果仅仅只是设置了这个参数,不会起到太大的作用,这需要了解Windows是如何定义空闲的会话的,经过笔者多次实验,发现了以下规律: (假如在机器192.168.1.1上共享了incoming目录,目录中有1.xls,1.txt文件)
空闲会话:
仅访问,不进入incoming目录,保持文件浏览器在状态,这样1分钟后,windows会自动关闭此对话。这个1分钟不太精确,一般是90秒左右。
打开了,保持打开状态,windows会自动关闭此对话。
非空闲会话:
访问了 目录,保持文件浏览器在 状态,Windows永远不会关闭此会话
打开了,保持打开状态,Windows永远不会关闭此会话,使用net files 命令可见锁定的文件标志为3,如下图所示:
综上,当访问的不是计算机共享的根目录,或打开的文件需要锁定处理时,windows都不会去自动关闭会话,后续的用户就不可能登录上来。这是需要强制去关闭会话,可以使用命令net session //computer /delete命令,需要注意的一点是,如果该计算机打开了锁定的文件,如word、xls文件的话,这种方法会导致两个用户共同使用一个文件造成混乱,下图显示了强制关闭有打开锁定文件的计算机会话时出现的提示:
