The Windows NT 6 shutdown process【Windows NT 6 关机过程】

  原文: http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/windows-nt-6-shutdown-process.html

你来到这里看这个页面原因大概是你经常被问到下面类似的问题:

Windows NT 版本6 ("Windows Vista") 关机过程是什么 样子的?

下面是常见的答案.

Windows NT 6 关机过程很大程度上是围绕着一个Win32 API ExitWindowsEx(). 仅在这个函数的最后阶段才请求内核执行真正的关机任务.

ExitWindowsEx()的角色

不同于很多其它Win32 API 调用,从Windows NT 4开始, ExitWindowsEx() 一直是作为RPC实现,向自己会话里的CSRSS进程进行远程过程调用 ("Client-Server Runtime Subsystem") 。 就是这一点使得关机过程的控制流程复杂了一些,因为CSRSS执行的许多动作是以另外的进程名义进行的 (并模拟[impersonating]调用者的凭证[credentials]) 而不是直接由那个进程自己执行。

ExitWindowsEx() 有两个行为。其一是它向当前会话WINLOGON进程的一个窗口发送窗口消息[window message],其二是它向一个会话的所有顶层窗口广播结束会话[end-session]消息。 上述两个行为都是由CSRSS实现的,但这是因为NT Win32的client-server设计使然,并非必需这样。

用户和程序如何初始化关机

初始化关机的三个方法:程序调用InitiateSystemShutdownEx(), 程序调用ExitWindowsEx()带上关机请求参数,会话1用户触发的Secure Attention Sequence. 前面两个方式最终都是模拟第三个方式。

当程序调用ExitWindowsEx()去请求关机,注销,重启等操作,ExitWindowsEx() (CSRSS以调用进程的名义) 简单地发送一个窗口消息给当前会话WINLOGON进程的一个窗口来模拟用户在WINLOGON用户界面选择的同样功能的按钮 。因此调用ExitWindowsEx() 初始化关机方式,是靠发送给当前会话WINLOGON进程一个窗口消息来请求关机的,从这一刻起WINLOGON的后续行为就和用户自己在图形界面上的点击一样了。

This is why, incidentally, ExitWindowsEx() only has an effect if the process invoking it is being run in session 1. (微软讲的 "by交互用户", which can be misleading. This is what it actually means.)ExitWindowsEx() 发送窗口消息到WINLOGON 进程for the session in which the invoking process is running. 但是仅仅在会话1的WINLOGON进程响应关机消息,因为 it is the only session talking to a "本地" 用户;实际上,其它会话甚至不必有WINLOGON进程。 (会话0有WININIT,没有WINLOGON.) 因此,只有会话1的进程调用ExitWindowsEx()才有实际效果。

InitiateSystemShutdownEx() 的行为类似,,但比上面稍微复杂点。原因在于这种方式触发的关机可以被延迟。当程序调用InitiateSystemShutdownEx() 它连接命名管道\InitShutdown并且使用该命名管道执行一个RPC来计划关机。命名管道的服务端是WINLOGON,它处理延迟关机的细节并在计划的时间点触发关机。WINLOGON 也允许取消已经计划的延迟关机请求。AbortSystemShutdown()执行一个RPC via the same named pipe to request that a previously scheduled shutdown be cancelled.

WINLOGON通过命名管道处理"初始化关机"请求的函数是BaseInitiateShutdownEx(). 它会检查客户端的权限、请求的有效性、确保之前未有计划关机且关机未已执行。检查WINLOGON 是否不在"logged-on and locked" 状态、写入审计日志,(if everything succeeds to this point — flags in the request allowing some of the aforementioned checks to be overridden) 启动一个线程在计划的时间执行关机。

这个线程执行命名的不太恰当的函数LogoffThreadProc(). This function waits until the specified time, 在过渡期显示一个"倒计时" 对话框,时间到调用ExitWindowsEx(). This is a normal call to ExitWindowsEx(), which sends a message to WINLOGON to simulate shutdown being requested via its user interface.

WINLOGON有用不同的内部标记和变量控制延迟关机机制。ShutdownInProgress 标记记录已经安排了关机计划 (i.e. the thread has already been invoked). ShutdownTime变量记录了线程真正关机前需要等待的时间ShutdownHasBegun 记录the fact that a shutdown has begun (i.e. the thread has called ExitWindowsEx()). AbortShutdown标记被设置,如果从命名管道收到 "abort shutdown" 请求 或者在"倒计时"对话框选择了abort。

WINLOGON对关机请求的响应

When WINLOGON receives an interactive (or simulated) shutdown request, it first logs the current user off. (IfExitWindowsEx() had been called requesting a logout, the procedure would end here.) Logging the user off involves sending end-session messages to all of the message queues in the session, sending logoff events to all of the consoles in the session, switching from the user desktop to the login desktop, and effecting an internal change of state to the "no-one logged on" state.

To send end-session messages and logoff events, WINLOGON itself callsExitWindowsEx(), impersonating the currently logged on user and using secret undocumented parameters to the call that request thesecond behaviour of ExitWindowsEx(), namely that that end-session messages be broadcast to all of the top-level windows in the current session.ExitWindowsEx() (i.e. CSRSS acting upon WINLOGON's behalf) enumerates all of the top-level windows in the the session, first sending theWM_QUERYENDSESSION window message and then sending the WM_ENDSESSION window message to them. If they are console windows, this in turn causes CSRSS (which is the owner of all console windows) to send theCTRL_LOGOFF_EVENT event to the associated console.

Microsoft's documentation talks about sending messages to threads, implying that all threads in the session that have message queues are enumerated. In fact,ExitWindowsEx() takes the easy option and enumerates top-level windows instead, which is a lot simpler to do. Thus if a single-threaded application has two top-level windows, it will receive the end-session window messages twice, once per window. Similarly, even if a thread has a message loop, it won't receive end-session messages unless the program has created a top-level window. These are both contrary to what Microsoft's documentation implies.

It is CSRSS that implements the timeouts, waiting for a response, and that displays the "end task" dialogue boxes for unresponsive processes.

The shutdown process can potentially become stuck forever at this point, if the user does not close the dialogue boxes. CSRSS knows that it is in the middle of processing anExitWindowsEx() broadcast, and so responds with a failure result code if any process in the session (including WINLOGON) callsExitWindowsEx() again. The current broadcast sequence must be cancelled before CSRSS allows another one to be triggered. (Note that ifExitWindowsEx() were not implemented as a client-server Win32 API call, this behaviour would be a lot harder to duplicate, since there would be no central arbitrator to prevent two separate processes from executingExitWindowsEx() simultaneously.)

When all of the end session messages and events have been sent, CSRSS completes the remote procedure call and WINLOGON's call toExitWindowsEx() returns. WINLOGON then effects an internal change of state from the "logged-on" state to the "no-one logged on" state. This involves updating the user's profile, deleting network connections, playing the "log off" and "system exit" sounds, killing all COM processes (which has a grace period of 15 minutes), saving and unloading the user's profile, and deleting RAS connections. Finally WINLOGON informs the LogonIU of the state change. (On prior versions of Windows NT, WINLOGON would notify the GINA of an internal change of state by calling the GINA's WlxLogoff() function.)

After logging the current user off, WINLOGON then attempts to stop all of the processes running in session 0.

To stop all of the processes running in session 0, WINLOGON calls ExitWindowsEx() again, again using secret undocumented parameters to the call to request an end-session broadcast, but this time under the aegis of the "local system" user account.ExitWindowsEx() (i.e. CSRSS acting upon WINLOGON's behalf) performs the same enumeration for session 0 as it did for session 1, sending the same window messages. One difference, however, is that instead of sending a logoff event to any consoles, it sends a CTRL_SHUTDOWN_EVENT instead.

It is here that the Service Controller (SCM) is first informed that the system is shutting down. It, in turn, attempts to stop all running service processes. (Its console event handler, itsScShutdownNotificationRoutine() function, receives the CTRL_SHUTDOWN_EVENT event and in turn calls the SCM'sScShutdownAllServices() function.) Because it does so, CSRSS implements a special case for it. Since it knows which process is the SCM (because the SCM registers itself with CSRSS at startup) it knows to implement a different, usually longer, timeout when sending end-session messages to the SCM.

When all of the shutdown messages and events have been sent, CSRSS completes the remote procedure call and WINLOGON's call toExitWindowsEx() returns. WINLOGON then effects an internal change of state from the "no-one logged-on" 状态to the "shutdown" 状态。WINLOGON通知LogonIU状态的变化。 (On prior versions of Windows NT, WINLOGON would notify the GINA of an internal change of state 通过调用GINA的函数WlxShutdown()。)

最后,WINLOGON告诉Session Manager Subsystem (SMSS) 关机。它通过发送一个关机请求到SMSS的LPC port实现。

SMSS对LPC端口关机请求的响应

关机过程最后一步是SMSS。它通知所有它所启动的会话里的子系统进程(例如CSRSS, PSXSS, OS2SS等),通知它们系统即将关闭,给它们时机去终止他们的客户进程并且终止自己。之后它会调到内核的NtShutdownSystem()系统调用。

NtShutdownSystem()系统调用中的关机处理

在内核里,关闭所有驱动程序,内存中的注册表hives被写入磁盘,磁盘缓存回写,页面文件被清除。最后调用NtSetSystemPowerState()函数关闭所有的即插即用设备,使系统休眠,重启或关机等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值