zoukankan      html  css  js  c++  java
  • windows下信号机制的学习

    以前没有注意过这个问题, 近期在代码中看到了用到windows下的signal, MSDN, 上网查了查, 并写了测试的代码, 得出以下结论:

        1. windows下支持的信号时有限的, 在signal.h中定义, 分别是

                 SIGINT      Ctrl+C中断

                 SIGILL       非法指令

                 SIGFPE      浮点异常

                 SIGSEGV   段错误, 非法指针访问

                 SIGTERM   kill发出的软件终止

                 SIGBREAK Ctrl+Break中断

                 SIGABRT   调用abort导致

        2. windows信号的机制~~~

                 1. 表象

                     跟踪了SIGSEGV 和 SIGABRT, 发现这两个信号处理线程和程序的主线程是同一个线程

                     跟踪了SIGINT 和 SIGBREAK, 发现这两个信号处理线程和程序的主线程不是是同一个线程, 而其信号线程的优先级更高

                 2. 查资料

                     看MSDN这段话"SIGINT(我觉得应该再加上SIGBREAK) is not supported for any Win32 application. when Ctrl-C interrupt occurs, win32 operating systemd generate a new thread to specifically handle that interrupt. this can cause a sigle-thread application such as one in UNIX to become multithreaded, resulting in unexpected behavior" 意思是在建议在win2应用程序中使用SIGINT和SIGBREAK信号, 因为当这两个信号发生时, OS会专门产生新的线程来处理信号~~~这将导致一个单线程程序表现出多线程程序的特点, 引发未定义行为.

                  3. 看代码

                      查看了crt, 发现在调用signal(SIGINT/SIGBREAK, handlefunc)的时候, 如果signal函数发现注册是的SIGINT或者是SIGBREAK信号的话, 就会调用SetConsoleCtrlHandler函数, 把一个名为ctrlevent_capture的函数注册进console的control handler function list(每个console程序都有一个这样的队列用于处理Ctrl-C, Ctrl-Break事件, SetConsoleCtrlHandler可以把一个新的handler function压到队尾, 当事件发生时, 会从队尾开始, 产生线程[线程函数就是压入的handle function]处理事件, 直到某个handle function返回值为true, 如果都不返回true, 就会调用ExitProcess)

                      所以, 当调用signal(SIGINT/SIGBREAK, handlefunc)发生以下事件

                              1. 保存handlefunc到合适位置

                              2. SetConsoleCtrlHandler(ctrlevent_capture, true), 也就是说ctrlevent_capture函数被压入到队列尾部

                      当信号发生时发生以下事件

                              1. CreateThread(…, ctrlevent_capture, …)

                              2. 在ctrlevent_capture的内部, 会取出handlefunc, 并调用

                              3. ctrlevent_capture返回的是true~~~所以Ctrl-C处理到此为止

                      综上所述, SIGINT/SIGBREAK的确是OS新产生的线程来处理的

        3. 由于本人略看过linux低版本的代码, 所以在这里再比较一下linux和windows信号的区别

                  1. 这两者完全是两码事, 不可放在同一级别讨论

                  2. linux信号种类丰富, windows就几种

                  3. linux信号是操作系统的一种机制, windows信号是CRT库提供的一种功能

                  4. linux信号的产生和处理不是连续的, 产生SIG的地方只是置位task的sigmask~~~直到系统调用或者中断结束后, 才有可能去处理信号, 也就是信号的发生和处理是异步的

                      windows信号, 除了SIGINT/SIGBREAK, 其他信号都是类似于

                           if (注册了SIGXX)

                                  调用handlerfunc

                      及发生和处理时一起的同步的

        4. 看到这些, 相信对windows信号的使用和底层实现的了解就算比较明白了, 希望对大家有帮助

  • 相关阅读:
    高质量的函数 —— 《clean code》读后感
    保证代码的高质量 —— 《clean code》读后感
    [转 TDD] 如何坚持TDD:使用者出现的问题以及解决方案
    注释 —— 《clean code》读后感
    注释 —— 《clean code》读后感
    如何命名 —— 《clean code》读后感
    高质量的函数 —— 《clean code》读后感
    保证代码的高质量 —— 《clean code》读后感
    格式 —— 《clean code》读后感
    华为内部面试题库(14)
  • 原文地址:https://www.cnblogs.com/ringofthec/p/1707926.html
Copyright © 2011-2022 走看看