zoukankan      html  css  js  c++  java
  • c++上下文使用信号小结

    说明:本文的上下文环境是 unix/linux操作系统,g++编译环境, gdb调试环境。


    signal是 阻塞模式的良好搭挡。一些需要低速调用的程序,例如 socket、oracle连接,若工作在非阻塞模式下,轮询会有大量的CPU开销,而阻塞模式则使得程序不能及时处理那些需要实时响应的操作。signal可以将程序从阻塞状态唤醒,以处理紧急事件,然后再做别的事情。

    unix_program_advance 一书中第十章,详细地介绍了 unix 系统提供的信号捕获函数。

    在开发中应注意:

    1、确定要使用阻塞还是非阻塞。oci和 socket中,默认都是阻塞的。

    在socket 中,可以使用  fcntl()来设置O_NONBLOCK, O_NDELAY.

    if (fcntl(fd, F_SETFL, orig_flags | O_NONBLOCK) < 0
    {
        
    }

    在oci中,可以使用 OCIAttrSet()函数的 OCI_ATTR_NONBLOCKING_MODE 属性值来设置oci的操作为非阻塞模式。详细的用法见 Oracle Call Interface Programmer's Guide  B10779-01. chapter 2 中 Nonblocking Mode in OCI 一节。

    当socket为阻塞模式时,可以使用 setsockopt来设置 recv的超时时间。

    1、任何一个可能无限阻塞的调用,调用之间加一个alarm()

    在oracle中,如果在呼叫 oracle时网络掉线。则函数会永远阻塞。所以,有必要在可能阻塞的函数前,加一个alarm()以在超时后将其唤醒。

    下面示例了信号的使用。当函数调用超过3秒后,跳出函数并重新连接数据库以执行此操作。直到操作三次仍不能成功,则放弃操作。

    do
    {
        alarm(
    3);
        
    if(  table.query() == false && errno == EINTR ) 
        {
            conndb();
        }
        
    else
        {
         
    break;
        }
    }
    while (retryTimes < 3)

    alarm(0);

    2、用 sigaction() 而不是 signal() 来设置信号钩子。signal()跨平台性能不好。在 linux下跑得很健壮的程序,到了 hp-unix或 ibm-aix上表现得非常糟糕,而 solaris上 signal 又有不同的表现。较于 signal, sigaction 定义了被中断的低速调用是否重新唤起 ( 默认不唤起);sigactionl() 还有屏蔽功能,这使得信号处理函数可以专注地处理当前的信号。

    3、当前信号处理函数结束前要唤起先前定义的信号处理函数。

    sigaction( signo, NULL, oldHandle );

    4、可以设置捕获所有的信号,以避免程序收到信号时意外退出。信号编号下界限为1,最高界限是SIGMAX,可以使用for()循环设置钩子。

    5、子进程会继承父进程的信号钩子,但不能继承父进程中已经设置的信号(例如,闹钟信号)。

    6、如果想在收到信号后跳出当前的上下文环境,用  throw()。

    相关资料 :

    1、 <the design of the unix operationg system>第 7.2 信号  从操作系统实现的角度,详细地介绍了信号的分类、信号如何被唤醒、信号在什么情况下会丢失或引发意外。(注 : 书中讨论的内容是 原始版本的 signal(),实际上, sigaction 已经解决了信号丢失、信号异常的问题。)

    2、<Advanced Programming in the UNIX Environment>  第 10章详细介绍了不可靠信号signal、可靠信号sigaction在 posix.1、SVR4、4.3+BSD中,信号的实现。并给出了对信号进行处理的相关源码。

    使用信号的完整示例:

    信号一个极有用的使用是:将进程从阻塞状态唤醒。
    信号有一定的局限性。信号不能像 message 那样传递消息结构,而只能传递一个简单的信号。
    信号会破坏程序的流程。因为我们不知道信号究竟什么时候会发生。
    一个比较合理的处理办法是:
    当进程收到关注的信号时,执抛出一个异常。这样,程序可以根据自己的意愿想停就停,想开就开。
    示例如下:


    范晨鹏
    ------------------
    软件是一种态度
    成功是一种习惯


  • 相关阅读:
    简单的模板解析函数
    HTML通过事件传递参数到js 二 event
    HTML通过事件传递参数到js一
    通过this获取当前点击选项相关数据
    LeetCode 20. 有效的括号(Valid Parentheses)
    LeetCode 459. 重复的子字符串(Repeated Substring Pattern)
    LeetCode 14. 最长公共前缀(Longest Common Prefix)
    LeetCode 168. Excel表列名称(Excel Sheet Column Title)
    LeetCode 171. Excel表列序号(Excel Sheet Column Number) 22
    LeetCode 665. 非递减数列(Non-decreasing Array)
  • 原文地址:https://www.cnblogs.com/diylab/p/1297542.html
Copyright © 2011-2022 走看看