Windows 的停机机制在 <Microsoft Windows Internals, 4th> 一书中也只是很简单的描述了几句
“如果已经有人登录到系统中,并且某个进程通过调用 Windows 的 ExitWindowsEx函数发出了停机指令,
那么就会有一个消息被发送到Csrss, 指示它执行停机处理”
windows 的关机流程
Windows关机步骤涉及到Windows多个组件和多个过程,简单的说,Windows的关机步骤不是大多数人认为的那么简单。基本的过程是这样的:
1. 用户发起关机指令以后,发起关机指令的程序将调用系统函数库user32.dll中的ExitWindwsEx函数,此函数将会向Windows子系统CSRSS.EXE,CSRSS.EXE收到通知以后会和Winlogon.EXE做一个数据交换,winlogon.exe检查请求者的权限,做好准备,并给ExitWindowsEx发回准备就绪信号,接着由Winlogon.EXE通知CSRSS.EXE开始关闭系统的流程 。
2. CSRSS.EXE收到Winlogon.EXE的通知以后,会依次查询拥有顶层窗口的用户进程,循环给所有正在运行的应用程序发送WM_QUERYENDSESSION和WM_ENDSESSION消息,让这些用户进程退出。如果某一个用户进程在一个默认的超时时间5000毫秒(可以通过修改注册表键值HKEY_CURRENT_USER\Cont rol Panel\Desktop\ HungAppTimeout设定超时时间)内没有退出的话,Windows会显示一个结束任务对话框用于询问用户是否结束这个任务。默认情况下将显示这个对话框并一直保持而不会自动关闭。对于控制台程序来说,基本情况类似,只不过Windows使用HK EY_CURRENT_USER\Control Panel\Desktop\ WaitToKillAppTimeout值来设置超时时间。
3. 接着是轮到终止系统进程了,csrss.exe给所有的系统进程发消息令他们退出。系统进程包括SMSS.EXE、Winlogon.EXE、Lsass.EXE等。Windows在终止系统进程的时候并不像终止用户进程那样如果无法在规定时间内终止则提示用户,而是跳过这个进程,去执行下一个系统进程的终止操作。使用的超时时间和第2步使用的时间相同。准备工作完毕,winlogon.exe给smss.exe发出"InitiateSystemShutdown"请求,smss.exe命令释放所有系统资源
上述3个步骤是整个Windows关机过程中最耗费时间的一段,大多数关机缓慢的原因都是因为这3个步骤引起的。完成前3个步骤以后,进入了关机操作的第4个阶段,也是最后一个阶段。
4. Winlogon.EXE调用一个原生API函数NtShutdownSystem()来命令系统执行后面的扫尾工作。在这个阶段里面,Windows执行子系统会完成最后的关机操作,例如:设备驱动在这个阶段里面完成一些驱动设定的特殊操作; 也是在这个阶段,配置管理系统将被修改过的注册表数据会写道磁盘里面。等除了电源管理以后的全部子系统完成退出以后,电源管理完成最后的操作:如重启、关机等。
小试牛刀
kd> !process 0 0
**** NT ACTIVE PROCESS DUMP ****
PROCESS 81bbc830 SessionId: none Cid: 0004 Peb: 00000000 ParentCid: 0000
DirBase: 00039000 ObjectTable: e1001c58 HandleCount: 251.
Image: System
PROCESS 81a39178 SessionId: none Cid: 020c Peb: 7ffda000 ParentCid: 0004
DirBase: 077ad000 ObjectTable: e13b7b78 HandleCount: 21.
Image: smss.exe
PROCESS 818e72c0 SessionId: 0 Cid: 024c Peb: 7ffd9000 ParentCid: 020c
DirBase: 082ae000 ObjectTable: e14c2198 HandleCount: 303.
Image: csrss.exe
PROCESS 81a8caf8 SessionId: 0 Cid: 0264 Peb: 7ffdb000 ParentCid: 020c
DirBase: 08673000 ObjectTable: e14bb4c8 HandleCount: 498.
Image: winlogon.exe
PROCESS 81a12140 SessionId: 0 Cid: 0294 Peb: 7ffd7000 ParentCid: 0264
DirBase: 089d8000 ObjectTable: e17a0738 HandleCount: 257.
Image: services.exe
.
PROCESS 819cac08 SessionId: 0 Cid: 05b0 Peb: 7ffd8000 ParentCid: 0550
DirBase: 0b91c000 ObjectTable: e1bfeac0 HandleCount: 291.
Image: explorer.exe
kd> .PROCESS 819cac08
Implicit process is now 819cac08
WARNING: .cache forcedecodeuser is not enabled
kd> .reload
Connected to Windows XP 2600 x86 compatible target at (Wed Nov 4 14:16:26.001 2009 (GMT+8)), ptr64 FALSE
Loading Kernel Symbols
.
Loading User Symbols
Loading unloaded module list
.
kd> bp USER32!ExitWindowsEx
kd> g
StartMenu -> ShutDown
Breakpoint 0 hit
USER32!ExitWindowsEx:
001b:77d89e6d 8bff mov edi,edi
kd> kb
ChildEBP RetAddr Args to Child
01f1ff7c 7ca746cc 00000009 00000000 00000000 USER32!ExitWindowsEx
01f1ff9c 7ca74b80 00000000 00000000 011ef6d8 SHELL32!CommonRestart+0x59
01f1ffb4 7c80b50b 00124800 011ef6d8 7c90fb71 SHELL32!ShutdownThreadProc+0x72
01f1ffec 00000000 7ca74b0e 00124800 00000000 kernel32!BaseThreadStart+0x37
kd> !thread
THREAD 819495d8 Cid 05b0.0374 Teb: 7ffd5000 Win32Thread: e18bfeb0 RUNNING on processor 0
Not impersonating
DeviceMap e1525378
Owning Process 0 Image: <Unknown>
Attached Process 819cac08 Image: explorer.exe
Wait Start TickCount 304321 Ticks: 0
Context Switch Count 12 LargeStack
UserTime 00:00:00.000
KernelTime 00:00:00.000
Win32 Start Address SHELL32!ShutdownThreadProc (0x7ca74b0e)
Start Address kernel32!BaseThreadStartThunk (0x7c810856)
Stack Init f6c7f000 Current f6c7e768 Base f6c7f000 Limit f6c7b000 Call 0
Priority 11 BasePriority 8 PriorityDecrement 2 DecrementCount 16
ChildEBP RetAddr Args to Child
01f1ff7c 7ca746cc 00000009 00000000 00000000 USER32!ExitWindowsEx (FPO: [2,6,0])
01f1ff9c 7ca74b80 00000000 00000000 011ef6d8 SHELL32!CommonRestart+0x59 (FPO: [2,1,4])
01f1ffb4 7c80b50b 00124800 011ef6d8 7c90fb71 SHELL32!ShutdownThreadProc+0x72 (FPO: [1,0,0])
01f1ffec 00000000 7ca74b0e 00124800 00000000 kernel32!BaseThreadStart+0x37 (FPO: [Non-Fpo])
kd> !process
PROCESS 819cac08 SessionId: 0 Cid: 05b0 Peb: 7ffd8000 ParentCid: 0550
DirBase: 0b91c000 ObjectTable: e1bfeac0 HandleCount: 311.
Image: explorer.exe
VadRoot 81aaa268 Vads 205 Clone 0 Private 2098. Modified 1243. Locked 0.
DeviceMap e1525378
Token e179a030
ElapsedTime 01:22:09.593
UserTime 00:00:02.406
KernelTime 00:00:17.812
QuotaPoolUsage[PagedPool] 61892
QuotaPoolUsage[NonPagedPool] 9640
Working Set Sizes (now,min,max) (4153, 50, 345) (16612KB, 200KB, 1380KB)
PeakWorkingSetSize 4640
VirtualSize 65 Mb
PeakVirtualSize 74 Mb
PageFaultCount 6596
MemoryPriority BACKGROUND
BasePriority 8
CommitCharge 2634
THREAD 819ca990 Cid 05b0.05b4 Teb: 7ffdf000 Win32Thread: e179a590 WAIT: (WrUserRequest) UserMode Non-Alertable
818e1420 SynchronizationEvent
THREAD 818fc7f8 Cid 05b0.05f4 Teb: 7ffdc000 Win32Thread: e16e34f8 WAIT: (WrUserRequest) UserMode Non-Alertable
818fc560 SynchronizationEvent
THREAD 81a17a78 Cid 05b0.05fc Teb: 7ffdb000 Win32Thread: 00000000 WAIT: (DelayExecution) UserMode Alertable
81a17b68 NotificationTimer
THREAD 81a17780 Cid 05b0.0600 Teb: 7ffda000 Win32Thread: e1d91868 WAIT: (WrQueue) UserMode Non-Alertable
81a179f8 Unknown
81a17870 NotificationTimer
THREAD 81a17410 Cid 05b0.0604 Teb: 7ffd9000 Win32Thread: 00000000 WAIT: (UserRequest) UserMode Alertable
81a17688 NotificationTimer
81a1a958 SynchronizationEvent
8193c208 NotificationEvent
THREAD 81993370 Cid 05b0.06a8 Teb: 7ffd7000 Win32Thread: e18779f0 WAIT: (UserRequest) UserMode Alertable
819e27fc NotificationEvent
81783084 NotificationEvent
81a7b454 NotificationEvent
81a7a8cc NotificationEvent
81abc9f4 NotificationEvent
81abc89c NotificationEvent
8178dbdc NotificationEvent
818e1550 SynchronizationEvent
THREAD 8176fda8 Cid 05b0.01b0 Teb: 7ffd6000 Win32Thread: e1836368 WAIT: (WrUserRequest) UserMode Non-Alertable
819bbc68 SynchronizationEvent
THREAD 81a9d020 Cid 05b0.05a4 Teb: 7ffde000 Win32Thread: e1884eb0 WAIT: (WrLpcReceive) UserMode Non-Alertable
8196da50 Semaphore Limit 0x7fffffff
81a9d110 NotificationTimer
THREAD 81940d80 Cid 05b0.0528 Teb: 7ffdd000 Win32Thread: 00000000 WAIT: (WrLpcReceive) UserMode Non-Alertable
8196da50 Semaphore Limit 0x7fffffff
81940e70 NotificationTimer
THREAD 81992d80 Cid 05b0.0678 Teb: 7ffd4000 Win32Thread: 00000000 WAIT: (DelayExecution) UserMode Non-Alertable
81992e70 NotificationTimer
THREAD 819495d8 Cid 05b0.0374 Teb: 7ffd5000 Win32Thread: e18bfeb0 RUNNING on processor 0
重启后再来一次,Start menu -> ShutDown此时屏幕为灰色,Ctrl + Break
kd> bp advapi32!AdjustTokenPrivileges
kd> g
Breakpoint 0 hit
ADVAPI32!AdjustTokenPrivileges:
001b:77dfc534 8bff mov edi,edi
kd> kb
ChildEBP RetAddr Args to Child
01fbfe98 74ad168c 000004d4 00000000 01fbfecc ADVAPI32!AdjustTokenPrivileges
01fbfee8 74ad1d2d 000004d4 00000002 01fbff08 POWRPROF!SetPrivilegeAttribute+0x8e
01fbff0c 74ad1cf1 00000004 00000000 00000000 POWRPROF!CallNtPowerInformation+0x2d
01fbff28 74ad399d 01fbff34 74ad0000 74ad3984 POWRPROF!GetPwrCapabilities+0x26
01fbff84 7ca74690 00000000 000e72d8 000e72d8 POWRPROF!IsPwrShutdownAllowed+0x19
01fbff9c 7ca74b80 00000001 00000000 011ef6d8 SHELL32!CommonRestart+0x1d
01fbffb4 7c80b50b 000e72d8 011ef6d8 7c90fb71 SHELL32!ShutdownThreadProc+0x72
01fbffec 00000000 7ca74b0e 000e72d8 00000000 kernel32!BaseThreadStart+0x37