linux c++(信号介绍)

信号的处理包括信号的发送、捕捉和处理,它们有各自相对应的常见函数

  • 发生信号的函数
    kill()、raise()、alarm()、setitimer()、sigqueue()

  • 捕捉信号的函数
    alarm()、pause()

  • 处理信号的函数
    signal()、sigaction()

函数介绍 kill()、raise()

  • raise()函数允许进程向自身发送信号
  • kill()函数不仅可以终止进程(实际上是通过发出SIGKILL信号终止),也可以向进程发送其他信号


函数介绍 alarm()、pause()

  • alarm()也称为闹钟函数,它可以在进程中设置一个定时器,当定时器指定的时间到时,它就向进程发送SIGALARM信号。要注意的是,一个进程只能有一个闹钟时间
  • pause()函数用于将调用进程挂起直至捕捉到信号为止。这个函数很常用,通常可以用于判断信号是否已到。


函数介绍 signal()、sigaction()

  • 使用signal()函数处理时,只需指出要处理的信号和处理函数即可。它主要用于前32种非实时信号的处理,不支持信号传递信息


处理信号的流程

尽量避免使用此函数进行捕捉,因为signal函数有时可能在其他函数中有其他的含义
typedef void(*sighandler_t)(int);
sighandler_t signal(int signum,sighandler_t handler);
	signum 要捕捉的信号
	handler 要执行的捕捉函数指针,函数应该声明void func(int);

注册捕捉函数

 struct sigaction {
               void     (*sa_handler)(int);//函数指针
               void     (*sa_sigaction)(int, siginfo_t *, void *);
               sigset_t   sa_mask;//执行捕捉函数期间,临时屏蔽的信号集
               int        sa_flags;//一般填0,若不写0,SA_SIGINFO会使用第二个函数指针
               void     (*sa_restorer)(void);//无效
           };


int sigaction(int signum,const struct sigaction *act,struct sigaction *oldact);
	signum 捕捉的信号
	act 传入的动作
	oldact 原动作,恢复现场

示例

void sigCatchFun(int num)
{
    printf("beng call %d\n",num);
    sleep(5);
    printf("end call %d\n",num);

}
int main()
{
    //注册捕捉函数 #include <signal.h>
    struct sigaction act;    
    act.sa_flags=0;
    act.sa_handler = sigCatchFun;
    sigemptyset(&act.sa_mask);
    sigaddset(&act.sa_mask,SIGQUIT); //临时屏蔽ctrl + \信号
    sigaction(SIGINT,&act,NULL);

    while(1)
    {   
        printf("who can kill me?\n");
        sleep(1);                                                                                
    }   
    return 0;
}

信号屏蔽

sigset_t set; // typedef unsigned long sigset_t;
int sigemptyset(sigset_t *set); 将某个信号集清0 成功:0;失败:-1
int sigfillset(sigset_t *set); 将某个信号集置1 成功:0;失败:-1
int sigaddset(sigset_t *set, int signum); 将某个信号加入信号集 成功:0;失败:-1
int sigdelset(sigset_t *set, int signum); 将某个信号清出信号集 成功:0;失败:-1
int sigismember(const sigset_t *set, int signum);判断某个信号是否在信号集中 返回值:在集合:1;不在:0;出错:-1

sigprocmask
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset); 成功:0;失败:-1,设置errno

参数:
set:传入参数,是一个位图,set中哪位置1,就表示当前进程屏蔽哪个信号。
oldset:传出参数,保存旧的信号屏蔽集。
how参数取值: 假设当前的信号屏蔽字为mask
1.SIG_BLOCK: 当how设置为此值,set表示需要屏蔽的信号。相当于 mask = mask|set
2.SIG_UNBLOCK: 当how设置为此,set表示需要解除屏蔽的信号。相当于 mask = mask & ~set
3.SIG_SETMASK: 当how设置为此,set表示用于替代原始屏蔽及的新屏蔽集。相当于 mask = set若,调用sigprocmask解除了对当前若干个信号的阻塞,则在sigprocmask返回前,至少将其中一个信号递达。

sigpending
读取当前进程的未决信号集
int sigpending(sigset_t *set); set传出参数。 返回值:成功:0;失败:-1,设置errno

信号忽略

// 方案一
    if(signal(SIGHUP,SIG_IGN) == SIG_ERR)
    {                                                                                                               
        perror("signal ignore SIGHUB");
        exit(1);
    } 
// 方案二
  sigset_t myset,oldset;
   sigemptyset(&myset);
   sigaddset(&myset,SIGINT);
   sigprocmask(SIG_BLOCK,&myset,&oldset)

posted on 2021-05-06 09:24  lodger47  阅读(386)  评论(0)    收藏  举报

导航