来源:http://www.cnblogs.com/russinovich/archive/2011/04/26/2029655.html
以前我一直不理解Windows Session(会话)倒底是一个什么概念,总是感觉这个概念很虚,现在理解了一点。写下来做一个备忘。简单的说,用户登陆到windows系统之后,不管该用户是本地登陆的,还是远程登陆,系统都会为这个用户分配一个新的会话ID(SID)。也就是说会话与用户的登录是相关连的,没有用户登录就不存在会话。因此,会话的含义是指用户登录之后的一种运行的环境。我们先看看书上是怎么说的!
会话管理器(\Windows\System32\Smss.exe)是系统中第一个创建的用户态模式进程,负责完成执行体和内核的初始化工作的内核模式系统线程在最后阶段创建了实际的Smss进程(这段摘自: 《深入解析Windows操作系统(第4版)》80页)。
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
--------------------------------------------------------------------------------
在我的机器上做如下的实验:
lkd> !session
Sessions on machine: 1
Valid Sessions: 0
Current Session 0
可以看出我的机器上面只有一个会话,因为是我的机器,只有我在登陆。
--------------------------------------------------------------------------------
调用!sprocess 显示该会话数据结构的地址和该会话中的进程
lkd> !sprocess
Dumping Session 0
_MM_SESSION_SPACE b85dc000 这里就是会话空间的地址
_MMSESSION b85dc15c
PROCESS 8a11a268 SessionId: 0 Cid: 028c Peb: 7ffdf000 ParentCid: 0190
DirBase: 0aa00060 ObjectTable: e1b01120 HandleCount: 346.
Image: csrss.exe
PROCESS 8a2d0318 SessionId: 0 Cid: 02a4 Peb: 7ffdf000 ParentCid: 0190
DirBase: 0aa00080 ObjectTable: e18c70b0 HandleCount: 581.
Image: winlogon.exe
PROCESS 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结构的定义如下:
view sourceprint?001 typedef struct _MM_SESSION_SPACE
002 {
003 //
004 // This is a pointer in global system address space, used to make various
005 // fields that can be referenced from any process visible from any process
006 // context. This is for things like mutexes, WSL chains, etc.
007 //
008 struct _MM_SESSION_SPACE *GlobalVirtualAddress;
009
010 LONG ReferenceCount;
011
012 union
013 {
014 ULONG LongFlags;
015 MM_SESSION_SPACE_FLAGS Flags;
016 } u;
017
018 ULONG SessionId;
019
020 //
021 // This is the list of the processes in this group that have
022 // session space entries.
023 //
024
025 LIST_ENTRY ProcessList;
026
027 LARGE_INTEGER LastProcessSwappedOutTime;
028
029 //
030 // All the page tables for session space use this as their parent.
031 // Note that it's not really a page directory - it's really a page
032 // table page itself (the one used to map this very structure).
033 //
034 // This provides a reference to something that won't go away and
035 // is relevant regardless of which process within the session is current.
036 //
037
038 PFN_NUMBER SessionPageDirectoryIndex;
039
040 //
041 // This is the count of non paged allocations to support this session
042 // space. This includes the session structure page table and data pages,
043 // WSL page table and data pages, session pool page table pages and session
044 // image page table pages. These are all charged against
045 // MmResidentAvailable.
046 //
047
048 SIZE_T NonPageablePages;
049
050 //
051 // This is the count of pages in this session that have been charged against
052 // the systemwide commit. This includes all the NonPageablePages plus the
053 // data pages they typically map.
054 //
055
056 SIZE_T CommittedPages;
057
058 //
059 // Start of session paged pool virtual space.
060 //
061
062 PVOID PagedPoolStart;
063
064 //
065 // Current end of pool virtual space. Can be extended to the
066 // end of the session space.
067 //
068
069 PVOID PagedPoolEnd;
070
071 //
072 // PTE pointers for pool.
073 //
074
075 PMMPTE PagedPoolBasePde;
076
077 ULONG Color;
078
079 LONG ResidentProcessCount;
080
081 ULONG SessionPoolAllocationFailures[4];
082
083 //
084 // This is the list of system images currently valid in
085 // this session space. This information is in addition
086 // to the module global information in PsLoadedModuleList.
087 //
088
089 LIST_ENTRY ImageList;
090
091 LCID LocaleId;
092
093 //
094 // The count of "known attachers and the associated event.
095 //
096
097 ULONG AttachCount;
098
099 KEVENT AttachEvent;
100
101 PEPROCESS LastProcess;
102
103 //
104 // This is generally decremented in process delete (not clean) so that
105 // the session data page and mapping PTE can finally be freed when this
106 // reaches zero. smss is the only process that decrements it in other
107 // places as smss never exits.
108 //
109
110 LONG ProcessReferenceToSession;
111
112 //
113 // This chain is in global system addresses (not session VAs) and can
114 // be walked from any system context, ie: for WSL trimming.
115 //
116
117 LIST_ENTRY WsListEntry;
118
119 //
120 // Session lookasides for fast pool allocation/freeing.
121 //
122
123 GENERAL_LOOKASIDE Lookaside[SESSION_POOL_SMALL_LISTS];
124
125 //
126 // Support for mapping system views into session space. Each desktop
127 // allocates a 3MB heap and the global system view space is only 48M
128 // total. This would limit us to only 20-30 users - rotating the
129 // system view space with each session removes this limitation.
130 //
131
132 MMSESSION Session;
133
134 //
135 // Session space paged pool support.
136 //
137
138 KGUARDED_MUTEX PagedPoolMutex;
139
140 MM_PAGED_POOL_INFO PagedPoolInfo;
141
142 //
143 // Working set information.
144 //
145
146 MMSUPPORT Vm;
147 PMMWSLE Wsle;
148
149 PDRIVER_UNLOAD Win32KDriverUnload;
150
151 //
152 // Pool descriptor for less than 1 page allocations.
153 //
154
155 POOL_DESCRIPTOR PagedPool;
156
157 #if (_MI_PAGING_LEVELS >= 3)
158
159 //
160 // The page directory that maps session space is saved here so
161 // trimmers can attach.
162 //
163
164 MMPTE PageDirectory;
165
166 #else
167
168 //
169 // The second level page tables that map session space are shared
170 // by all processes in the session.
171 //
172
173 PMMPTE PageTables;
174
175 #endif
176
177 #if defined (_WIN64)
178
179 //
180 // NT64 has enough virtual address space to support per-session special
181 // pool.
182 //
183
184 PMMPTE SpecialPoolFirstPte;
185 PMMPTE SpecialPoolLastPte;
186 PMMPTE NextPdeForSpecialPoolExpansion;
187 PMMPTE LastPdeForSpecialPoolExpansion;
188 PFN_NUMBER SpecialPagesInUse;
189 #endif
190
191 LONG ImageLoadingCount;
192
193 #if DBG
194 ULONG Debug[MM_SESS_COUNTER_MAX];
195
196 MM_SESSION_MEMORY_COUNTERS Debug2[MM_SESS_MEMORY_COUNTER_MAX];
197 #endif
198
199 } 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。
view sourceprint?01 typedef struct _PEB
02 {
03 BYTE Reserved1[2];
04 BYTE BeingDebugged;
05 BYTE Reserved2[1];
06 PVOID Reserved3[2];
07 PPEB_LDR_DATA Ldr;
08 PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
09 BYTE Reserved4[104];
10 PVOID Reserved5[52];
11 PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine;
12 BYTE Reserved6[128];
13 PVOID Reserved7[1];
14 ULONG SessionId;
15 } PEB, *PPEB;
该结构最后一个成员就是SessionId。
--------------------------------------------------------------------------------
那么这里就产生一个问题了,同一台机器上面分别属于不同会话空间下的进程之间如何通讯呢?微软的MSDN里面的一些API就说的很清楚了。
我举一个例子吧。如CreateFileMapping MSDN的描述在 http://msdn.microsoft.com/en-us/library/aa366537(VS.85).aspx
lpName 如果使用"Global\" or "Local\" 作用范围是全局的。
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课