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

终止进程vs ctrl+c

  •  6
  • arolson101  · 技术社区  · 16 年前

    我有一个控制台模式程序,它使用sqlite3来维护数据库文件。执行需要一段时间,但在任何时候取消都应该是安全的,假设数据库写入发生。(这都在窗户下面)

    从运行程序的角度来看,点击 Ctrl键 C 在控制台上还有其他程序调用TerminateProcess吗?

    我注意到,如果调用TerminateProcess,我可能会导致数据库损坏-我假设这是因为程序没有机会完成写操作。我猜是这样的 Ctrl键 C 更好的是,因为程序接收到一个信号并自行终止,而不是被操作系统杀死。

    请注意,程序实际上不处理信号(除非sqlite处理);我正在讨论win32可执行文件的内置默认机制来处理 Ctrl键 C 信号。

    为了澄清/简化这个问题-鉴于本文刚刚执行:

    fwrite(buf, 1024*1024, 1, stream);
    

    在此写入期间,终止进程的行为是否与 Ctrl键 C ?

    4 回复  |  直到 10 年前
        1
  •  5
  •   udondan    10 年前

    所有这些都是令人信服的论点,但唯一确定的方法是尝试一下。所以我编写了一个简单的程序,它分配了一个1GB的缓冲区,给它分配了一些数据,然后使用一个fwrite()把它写到一个文件中。我尝试了几种方法来让写操作“损坏”数据(我希望得到一个被截断的文件,具体来说):

    • 调用TerminateProcess(通过Perl的kill函数和win32::process::kill)
    • Ctrl键 C
    • 使用任务管理器的“结束进程”
    • 使用Process Explorer的“终止进程”

    没有什么可以阻止写入-在每种情况下,文件的大小和数据都是正确的。尽管“杀戮”会立即发生,但这一过程会一直持续到写完为止。

    结论性的是,终止进程和 Ctrl键 C 从I/O的角度来看——一旦写入开始,它似乎就可以保证完成(除非断电)。

        2
  •  1
  •   udondan    10 年前

    你的申请必须有机会处理 Ctrl键 C Ctrl键 断裂 ,因为按键或信号(取决于配置),这意味着应用程序有机会进行一个干净的退出,这将是一个更软的方法来终止一个进程,如果没有其他东西,允许它有更多的执行时间。

    TerminateProcess更像是一个累赘,应用程序无法处理它,它来自内核,如果应用程序能够处理它,这将导致挂起TerminateProcess处理程序并拒绝退出的“不可杀死”进程出现各种问题。

    正如我所理解的,一旦在进程上调用TerminateProcess,它就不能再执行代码了,就是它,没有清理,没有关闭,它刚刚结束,你不能处理它,如果你能,而不是从安全的角度,它就是没有意义的。

    关于处理Windows控制台信号的优秀代码项目文章:

    http://www.codeproject.com/KB/winsdk/console_event_handling.aspx

    实现上面的一些信号处理,您可以确保数据库写入有机会在程序退出之前完成,而不是让它有机会完成。

    你可以阻止TerminateProcess,但它的“不太礼貌”编程,更像是根工具包编程,我在root kit.com上看到过一篇关于这个的好文章,所以在那里搜索“进程不可战胜”,一旦你有了不可战胜的进程,它可以在收到这样的“请求”后在自己的时间关闭,并在海航之前执行任何清理。D,但这肯定是一个黑客。

    但在我看来 Ctrl键 C 您当前看到的行为是由于它没有立即结束正在运行的进程。

        3
  •  0
  •   hughdbrown    16 年前

    sqlite声称是原子的,即使在电源故障时也是如此,请参见 http://www.sqlite.org/atomiccommit.html .

    唯一的例外是,某些磁盘系统会报告在数据实际写入磁盘盘前成功写入,即数据在磁盘缓存中,或操作系统位于sqlite中。参见 http://www.sqlite.org/lockingv3.html , 第6.0节如何损坏数据库文件。

    终止的进程 must stop all running threads and complete pending I/O operations before they exit . 只要进程没有崩溃,就应该保证数据的完整性。

        4
  •  0
  •   udondan    10 年前

    我相信为了你的目的,使用它更安全 Ctrl键 C . 这将导致发送到程序的信号终止。如果程序不处理信号,它将在现场终止。

    TerminateProcess强制终止进程和任何子线程。

    MSDN :

    TerminateProcess函数终止 指定的过程及其所有 线程。…评论

    使用TerminateProcess函数 无条件地使进程 出口。全局数据的状态 由动态链接库维护 (DLL)可能会受到影响,如果 使用TerminateProcess而不是 退出过程。

    终止进程启动终止 马上回来。这个停止 执行中的所有线程 流程和请求取消 所有挂起的I/O。终止 在所有挂起之前,进程无法退出 I/O已完成或取消。

    进程不能阻止自己 正在终止。

    有一些方法可以阻止TerminateProcess进程,但我怀疑SQLITE3是否会这样做。