美文网首页
signal信号

signal信号

作者: Tomtoms | 来源:发表于2019-11-07 23:07 被阅读0次

[C] signal信号

我们应该遇到过这样的几个场景

  1. 程序在运行过程中需要终止ctrl+c,但是程序正在读写数据,为了防止程序在buffer中没有写入磁盘,需要在终止之前flush一次文件buffer
  2. 设置一个定时任务,n秒之后进行某些操作
  3. …(后续补充)
    实际上这些都是信号处理,程序运行中按下键盘ctrl+c实际上是给程序发了一个SIGINT信号,默认情况下程序会直接退出,但是我们可以定制这些信号处理。

信号处理的头文件是signal.h,里面有一个特定的数据结构sigaction

struct  sigaction {
    union __sigaction_u __sigaction_u;  /* signal handler 信号处理函数*/
    sigset_t sa_mask;               /* signal mask to apply 信号处理过程中需要屏蔽掉的其他信号*/
    int     sa_flags;               /* see signal options below 选项*/
};

另外还有一个sigaction函数,参数为

intsigaction(int, const struct sigaction * __restrict,
    struct sigaction * __restrict);

下面看下具体用法

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>

void INIProcess(int nsig)
{
    printf("signal:%d\n", nsig);
    int i=0;
    while(i<20){
        // do sth
        printf("%d/n",i);
        sleep(1);
        i++;
    }
}

int main()
{
    struct sigaction act;
    act.sa_handler = INIProcess;
    act.sa_flags = SA_NODEFER|SA_RESETHAND;
    sigaction(SIGINT,&act,NULL);
    while(1)sleep(100);
    return 0;
}

Sigaction方法的意思是捕捉SIGNIT(ctrl+c)信号,并且交给act指定的参数去进行信号处理,act指定了sa_handler为INIProcess去处理信号,同时有两个sa_flags参数,分别是如下解释
SA_NODEFER: 信号处理函数过程中不阻塞对于信号处理函数自身信号功能
SA_RESETHAND:用户注册的信号处理函数执行一次后被重置为系统默认的信号处理
所以上面这个例子,在按下ctrl+c以后,就已经把SIGINI的控制权交给了系统,再次按下以后就会退出

(base) ➜  C++ ./signal
^Csignal:2
^C

如果将flag改成SA_NODEFER的话,每次SIGINI处理都会进入注册函数,再也无法退出(除非在main函数内退出)

^C0/n1/n2/n3/n4/n5/n6/nsignal:2
^C0/nsignal:2
^C0/n1/n2/n3/nsignal:2
^C0/n1/n2/n3/nsignal:2
^C0/nsignal:2
^C0/nsignal:2
^C0/nsignal:2
^C0/nsignal:2
^C0/nsignal:2
^C0/nsignal:2
^C0/nsignal:2
^C0/nsignal:2
^C0/n1/n2/nsignal:2
^C0/nsignal:2
^C0/nsignal:2
^C0/nsignal:2
^C0/n1/n2/n3/n4/n5/n6/nsignal:2
^C0/nsignal:2
^C0/nsignal:2
^C0/n1/n2/n3/n4/n5/n6/n7/n8/n9/n10/n11/n12/n13/n14/n15/n16/n17/n18/n19/n1/n2/n3/n4/n5/n6/n7/n8/n9/n10/n11/n12/n13/n14/n15/n16/n17/n18/n19/n1/n2/n3/n4/n5/n6/n7/n8/n9/n10/n11/n12/n13/n14/n15/n16/n17/n18/n19/n7/n8/n9/n10/n11/n12/n13/n14/n15/n16/n17/nsignal:2

如果将flag设置成0,那么每次都会处理SIGINI信号都会被阻塞,下面是一段解释

情况下,我们去掉了SA_NODEFER标志位。程序在执行信号处理函数过程中,ctrl+c信号将会被阻止,但是在执行信号处理函数期发送的ctrl+c信号将会被阻塞,知道信号处理函数执行完成,才有机会处理信号函数执行期间产生的ctrl+c,但是在信号函数执行产生的多次ctrl+c,最后只会产生ctrl+c。2)情况下,由于设置了SA_NODEFER,ctrl+c信号将不会被阻塞。所以能够并行执行下次的信号处理函数。

同时处理SIGINI和SIGALRM

有时候不光要处理ctrl+c,还要处理一些定时操作。但是一旦收到某些信号,比如SIGQUIT就要开始做一些收尾的工作,但是与此同时有其他一些定时信号可能会干扰到这个信号的处理,就需要在注册的时候屏蔽掉定时信号(或者其他信号)

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>

void INIProcess(int nsig)
{
    printf("signal:%d\n", nsig);
    int i=0;
    while(i<10){
        sleep(1);
        i++;
    }
    exit(0);
}

int main()
{
    struct sigaction act;
    act.sa_handler  = INIProcess;
    
    act.sa_flags = SA_NODEFER; // 只进行一次ini,否则全部重来
    sigaddset(&act.sa_mask,SIGALRM); // 处理ini信号的时候屏蔽掉alarm信号
    sigaction(SIGINT,&act,NULL);
    alarm(5);
    while(1)sleep(5);
    return 0;
}

所以上面这个例子,如果没有SIGINI信号,程序5s就会停止,因为收到了SIGALRM,但是如果收到了SIGINI,程序的结束时间就是10s了,因为SIGALRM已经被屏蔽掉了。

另外有一个signal函数,比sigaction简单易用

相关文章

  • 北航921信号与系统专业英语词汇

    信号与系统 Determinate signal确定性信号 Random signal随机信号 Continuou...

  • kill命令

    语法: kill -SIGNAL pid SIGNAL是信号,kill -l可以查看支持的信号 常用信号: 1) ...

  • RAC的升阶操作

    // 信号高阶操作 // 通过信号转换 // 升阶 value转signal // 降阶 signal转value...

  • Signal和SignalProducer的简单使用

    一:Signal:信号(主要包含:信号观察者,信号发射器)<<<基本使用方法:>>>创建一个Signal,添加观察...

  • 信号(Signal)

    信号的基本概念 信号被认为是一种软件中断(区别于硬件中断),信号机制提供了一种在单进程/线程下处理异步事件的方法。...

  • Signal 信号

    信号通过发送通知来帮助您解耦应用程序当操作发生在核心框架的其他地方或其他Flask扩展时,简言之,信号允许某些发送...

  • 信号signal

    1,接受信号 void handler(int num){printf("recv num%d\n",num);}...

  • signal信号

    [C] signal信号 我们应该遇到过这样的几个场景 程序在运行过程中需要终止ctrl+c,但是程序正在读写数据...

  • [python]signal

    signal包的核心是使用signal.signal()函数来预设(register)信号处理函数,singnal...

  • Heart Signal-心动的信号

    Heart Signal-心动的信号 最近吸食综艺,欲罢不能。Heart signal和心动的信号,无法言说这是不...

网友评论

      本文标题:signal信号

      本文链接:https://www.haomeiwen.com/subject/jbmbbctx.html