代码之家  ›  专栏  ›  技术社区  ›  bltxd

在Win32上停止进程的最干净方法?

  •  1
  • bltxd  · 技术社区  · 17 年前

    在用c++实现应用服务器及其客户端库时,我在寻找一种干净可靠的方法来停止windows上服务器关闭时的客户端进程时遇到了困难。

    假设服务器及其客户端在同一用户下运行,则要求是:

    • 解决方案应在以下情况下有效:
      • 客户机可以使用控制台或图形用户界面。
      • 用户可能没有权限。
      • 客户端可能没有响应(无限循环、死锁)。
      • 客户机可以是也可以不是服务器的子级(直接或间接)。
    • 除非客户机缺陷被阻止,否则客户将被允许有机会干净地退出(释放他们的资源,同步一些数据到磁盘…)和一些合理的时间来这样做。
    • 在关闭过程中,所有客户端返回代码(如果可能的话)都可以提供给服务器。
    • 服务器应等到所有客户端都不在。

    在这个编辑中,下面的大多数答案都主张在服务器和它的客户机之间使用共享内存(或另一个IPC机制)来传送关机命令和客户端状态。这些解决方案可以工作,但要求客户端成功初始化库。

    我没有说的是,服务器还用于启动客户机,在某些情况下,还用于启动根本不使用客户机库的其他程序/脚本。如果可能的话,一个不依赖于服务器和客户机之间优雅通信的解决方案会更好。

    前段时间,我偶然发现一个c代码片段(在msdn中,我相信)执行了以下操作:

    1. 在进程关闭过程中通过CyTreExtType启动线程。
    2. 如果线程直接调用ExtPo过程。

    不幸的是,现在我正在寻找它,我找不到它,搜索结果似乎暗示这个技巧在vista上不再有效。对此有什么专家意见吗?

    5 回复  |  直到 17 年前
        1
  •  2
  •   titanae    17 年前

    如果使用thread,一个简单的解决方案是使用一个命名的系统事件,线程在事件上休眠,等待发出信号,控制应用程序可以在希望客户端应用程序退出时发出信号。

    对于UI应用程序(线程)可以将消息发布到主窗口,WMY关闭或退出,我忘记了,在控制台应用程序中,它可以发出CTRL C,或者如果主控制台代码循环,它可以检查线程所设置的一些退出条件。

    无论哪种方式,都不要让客户机应用程序退出,而是使用操作系统来表示它们应该退出。如果使用WaiFutSunLeObjt睡眠,睡眠线程将几乎不占用CPU占用空间。

        2
  •  1
  •   Asaf Bartov    17 年前

    在客户端和服务器之间需要某种IPC。如果所有客户机都是子客户机,我认为管道是最简单的;因为它们不是子客户机,我想可以使用服务器操作的共享内存段来注册客户机,发出shutdown命令,并收集成功关闭的客户机在那里发布的返回码。

    在这个共享内存区域中,客户端将他们的进程ID放在一起,这样服务器就可以使用终止进程()来强制杀死任何无响应的客户端(模数服务器特权)。

        3
  •  1
  •   Arkadiy    17 年前

    如果你愿意走ipc路线,那么就让客户端和服务器之间的正常通信双向进行,让服务器要求客户端关闭。或者失败了,让客户进行投票。或者作为最后的手段,当客户向服务器发出请求时,应该指示客户退出。您可以让库用户注册退出回调,但我知道的最好方法是在客户机被关闭时在客户机库中简单地调用“退出”。如果客户机陷入关闭代码中,服务器需要能够通过忽略该客户机的数据结构和连接来解决这个问题。

        4
  •  1
  •   Jason S    17 年前

    使用postmessage或命名事件。

    回复:postmessage——除了gui以外的应用程序,以及gui线程以外的线程,都可以有消息循环,对于这样的事情非常有用。(事实上,com在引擎盖下使用了消息循环)我以前在atl上做过,但现在有点生疏了。

    如果您想对来自“坏”进程的恶意攻击保持鲁棒性,请将客户机/服务器共享的私有密钥作为消息中的一个参数。

    命名事件方法可能更简单;使用CliaEvter,该名称是由客户机/服务器共享的一个名称,并有适当的应用程序在其主循环中检查事件的状态(例如WaHTFrutSunLoad,超时为0),以确定是否关闭。

        5
  •  0
  •   MSalters    17 年前

    这是一个非常普遍的问题,也有一些不一致之处。

    虽然这不是100%的规则,但大多数控制台应用程序运行到完成,而gui应用程序运行到用户终止它们为止(服务运行到通过scm停止为止)。因此,请求关闭gui更容易。你把它们等同于ALT-F4。但是对于控制台程序,你必须向它们发送相当于CTRL C的代码,并希望它们能够处理它。在这两种情况下,你只需等待。如果这个过程停留在你周围,你就把它击落(祈祷过程),祈祷伤害是有限的。但你的硬盘可以填满临时文件。

    GUI应用程序一般没有退出代码——它们将去向何方?通过定义强制终止的控制台进程不会退出,因此它没有退出代码。因此,在服务器关闭场景中,不要期望退出代码。

    如果附加了调试器,则通常无法从其他应用程序关闭进程。这将使调试器无法调试退出代码!

    推荐文章