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 那样传递消息结构,而只能传递一个简单的信号。
    信号会破坏程序的流程。因为我们不知道信号究竟什么时候会发生。
    一个比较合理的处理办法是:
    当进程收到关注的信号时,执抛出一个异常。这样,程序可以根据自己的意愿想停就停,想开就开。
    示例如下:


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


  • 相关阅读:
    重构与反思-<重构代码的7个阶段>有感
    Unity 自定义"=="操作符 [翻译来源blogs.unity3d,2014/05]
    Unity UGUI Button 无法点击问题一例
    [Lua性能] 小试验一例
    C# 循环中 直接索引 VS 缓存索引 性能测试
    Lua table直接索引VS缓存索引性能测试小示例
    大型网站架构系列:负载均衡详解(1)
    大型网站架构系列:电商网站架构案例(3)
    大型网站架构系列:电商网站架构案例(2)
    大型分布式网站架构技术总结
  • 原文地址:https://www.cnblogs.com/diylab/p/1297542.html
Copyright © 2011-2022 走看看