Sigaction

#include <signal.h>
int sigaction(int signum, const struct sigaction *act,
                     struct sigaction *oldact);

功能:

sigaction函数用于改变进程接收到特定信号后的行为。

参数

第一个参数为信号的值,可以为除SIGKILL及SIGSTOP外的任何一个特定有效的信号(为这两个信号定义自己的处理函数,将导致信号安装错误)

第二个参数是指向结构sigaction的指针,在结构 sigaction的实例中,指定了对特定信号的处理,可以为空,进程会以缺省方式对信号处理

第三个参数oldact指向的对象用来保存原来对相应信号的处理,可指定oldact为NULL。

返回值:函数成功返回0,失败返回-1

sigaction结构体

第二个参数最为重要,其中包含了对指定信号的处理、信号所传递的信息、信号处理函数执行过程中应屏蔽掉哪些函数等等

struct sigaction {
//信号处理程序 不接受额外数据(比较过时)
	void (*sa_handler)(int);

//信号处理程序能接受额外数据,和sigqueue配合使用(支持信号排队,信号传送其他信息),推荐使用
	void (*sa_sigaction)(int, siginfo_t *, void *); 		

sigset_t sa_mask; 	//屏蔽
	int sa_flags; 		//表示信号的行为:SA_SIGINFO表示能接受数据
	void (*sa_restorer)(void); //废弃不用了
};
//简单示例1: 用sigaction简单替换signal函数
void signalAction(int signo, siginfo_t *signalInfo, void *p)
{
    cout << "signal = " << signo << ", desc: " << strsignal(signo) << endl;
}

int main()
{
    struct sigaction act;
    //注意:回调函数句柄sa_handler、sa_sigaction只能选其一!!!
    //act.sa_handler = sigHandler;
    act.sa_sigaction = signalAction;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    if (sigaction(SIGINT,&act,NULL) == -1)
        err_exit("sigaction error");

    pause();
}
//简单实例2: 用sigaction模拟signal函数
sighandler_t mySignal(int signum, sighandler_t handler)
{
    struct sigaction act;
    struct sigaction oldAct;
    act.sa_handler = handler;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;

    if (sigaction(signum, &act, &oldAct) == -1)
        return SIG_ERR;
    return oldAct.sa_handler;
}

sa_mask选项

sa_mask specifies a mask of signals which should be blocked/** 指定一个信号集的掩码, 在这个掩码中的信号将要阻塞**/      (i.e., added  to  the  signal mask of the thread in which the signal handler is invoked)

during execution of the signal handler.  In addition, the signal which triggered the handler will be blocked,

unless the SA_NODEFER flag is used.

/** 在执行handler 的时候, 如果此时进程收到了sa_mask所包含的信号, 则这些信号将不会被响应, 直到handler函数执行完毕

与sigprocmask不同是: sigprocmask 是指定该进程的信号屏蔽字-> 屏蔽该信号, 不会接收该信号, 而sa_mask则是接收了该信号, 但是不会相应该信号**/

//示例: 将sa_mask选项设置以后的效果
/** 在进程相应SIGINT信号时, 如果此时有SIGQUIT信号抵达, SIGQUIT信号也不会被响应, 直到SIGINT信号相应完成之后, 才会去相应SIGQUIT信号(如运行截图所示)**/
int main()
{
    struct sigaction act;
    act.sa_handler = sigHandler;
    sigemptyset(&act.sa_mask);
    // 添加下面一行后: 在响应SIGINT信号时, 是不会被中断的
    sigaddset(&act.sa_mask, SIGQUIT);
    act.sa_flags = 0;
    if (sigaction(SIGINT, &act, NULL) == -1)
        err_exit("sigaction error");

    while (true)
        pause();
}
void sigHandler(int signo)
{
    cout << "catch a signal, signo = " << signo << ", desc: " << strsignal(signo) << endl;
    sleep(10);
}

//运行截图

sa_flags: 详细信息

siginfo_t结构:

siginfo_t{
    int      si_signo;    /* Signal number */
    int      si_errno;    /* An errno value */
    int      si_code;     /* Signal code */
    int      si_trapno;   /* Trap number that caused
                                        hardware-generated signal
                                        (unused on most architectures) */
    pid_t    si_pid;      /* Sending process ID */
    uid_t    si_uid;      /* Real user ID of sending process */
    int      si_status;   /* Exit value or signal */
    clock_t  si_utime;    /* User time consumed */
    clock_t  si_stime;    /* System time consumed */
    sigval_t si_value;    /* Signal value */
    int      si_int;      /* POSIX.1b signal */
    void    *si_ptr;      /* POSIX.1b signal */
    int      si_overrun;  /* Timer overrun count; POSIX.1b timers */
    int      si_timerid;  /* Timer ID; POSIX.1b timers */
    void    *si_addr;     /* Memory location which caused fault */
    long     si_band;     /* Band event (was int in
                                        glibc 2.3.2 and earlier) */
    int      si_fd;       /* File descriptor */
    short    si_addr_lsb; /* Least significant bit of address
                                        (since Linux 2.6.32) */
}

sigqueue

#include <signal.h>
int sigqueue(pid_t pid, int sig, const union sigval value);

功能

sigqueue是新的发送信号系统调用,主要是针对实时信号提出的支持信号带有参数,与函数sigaction()配合使用。

和kill函数相比多了一个参数:const union sigval value(int kill(pid_t pid, int sig)),因此sigqueue()可以比kill()传递更多的信息,但sigqueue()只能向一个进程发送信号,而不能发送信号给一个进程组。

参数

参数1是指定接收信号的进程id,参数2确定即将发送的信号;

参数3是一个联合数据结构union sigval,指定了信号传递的参数,即通常所说的4字节值。

sigval联合体

typedef union sigval{
    int sival_int;
    void *sival_ptr;
} sigval_t;
//综合实验sigaction+sigqueue
void onSa_SignalAction(int signalNum, siginfo_t *signalInfo, void *p)
{
    cout << "signalNum = " << signalNum << endl;
    //int recValue = signalInfo -> si_value.sival_int;  同下
    int recValue = signalInfo -> si_int;
    cout << "recvValue = " << recValue << endl;
}

int main()
{
    struct sigaction act;

    sigemptyset(&act.sa_mask);
    act.sa_flags = SA_SIGINFO;
    act.sa_sigaction = onSa_SignalAction;
    if (sigaction(SIGINT,&act,NULL) == -1)
        err_exit("sigaction error");

    pid_t pid = fork();
    if (pid == -1)
        err_exit("fork error");
    else if (pid == 0)  //In Child
    {
        /*
        typedef union sigval{
            int sival_int;
            void *sival_ptr;
        } sigval_t;
        */

        //union sigval signalValue; 同下
        sigval_t signalValue;
        signalValue.sival_int = 256;
        sleep(2);

        //给父进程发送SIGINT信号
        sigqueue(getppid(),SIGINT,signalValue);
    }

    pause();

    return 0;
}

Linux信号实践(4) --可靠信号的更多相关文章

  1. linux可靠信号和非可靠信号测试样例

    不可靠信号(在执行自定义函数其间会丢失同类信号) 可靠信号(在执行自定义函数其间不会丢失同类信号) 不可靠信号用一次以后,就恢复其默认处理吗? 至少在ubuntu 12.04上,已经是一次绑定,永远使 ...

  2. Linux信号实践(2) --信号分类

    信号分类 不可靠信号 Linux信号机制基本上是从UNIX系统中继承过来的.早期UNIX系统中的信号机制比较简单和原始,后来在实践中暴露出一些问题,它的主要问题是: 1.进程每次处理信号后,就将对信号 ...

  3. Linux 信号详解六(可靠信号与不可靠信号)

    #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h&g ...

  4. APUE学习笔记——10.可靠信号与不可靠信号

    首先说明:现在大部分Unix系系统如Linux都已经实现可靠信号. 1~31信号与SIGRTMIN-SIGRTMAX之间并不是可靠信号与不可靠信号的区别,在大多数系统下他们都是可靠信号. 只不过: 1 ...

  5. Linux系统编程——进程间通信:信号中断处理

    什么是信号? 信号是 Linux 进程间通信的最古老的方式.信号是url=474nN303T2Oe2ehYZjkrggeXCaJPDSrmM5Unoh4TTuty4wSgS0nl4-vl43AGMFb ...

  6. Linux驱动实践:中断处理函数如何【发送信号】给应用层?

    作 者:道哥,10+年嵌入式开发老兵,专注于:C/C++.嵌入式.Linux. 关注下方公众号,回复[书籍],获取 Linux.嵌入式领域经典书籍:回复[PDF],获取所有原创文章( PDF 格式). ...

  7. Linux信号实践(3) --信号内核表示

    信号在内核中的表示 执行信号的处理动作称为信号递达(Delivery),信号从产生到递达之间的状态,称为信号未决(Pending).进程可以选择阻塞(Block)某个信号.被阻塞的信号产生时将保持在未 ...

  8. Linux信号实践(1) --Linux信号编程概述

    中断 中断是系统对于异步事件的响应, 进程执行代码的过程中可以随时被打断,然后去执行异常处理程序; 计算机系统的中断场景:中断源发出中断信号 -> CPU判断中断是否屏蔽屏蔽以及保护现场 -&g ...

  9. UNIX环境高级编程——可靠信号与不可靠信号

    在早期的UNIX中信号是不可靠的,不可靠在这里指的是:信号可能丢失,一个信号发生了,但进程却可能一直不知道这一点. 现在Linux 在SIGRTMIN实时信号之前的都叫不可靠信号,这里的不可靠主要是不 ...

随机推荐

  1. python字典无限遍历

    #无限遍历dict,通过key获取value,嵌套字典存在多个相同的key,可获取多个key class getValues(object): def __init__(self): pass #无限 ...

  2. Vue实践经验

    多考虑应变 如果模版中绑定了 obj.xx 时,需要注意 obj 是否是异步数据,默认值是否为 null.安全起见,可在组件最外层加 v-if 判断. <template> <div ...

  3. ERP中的地区管理

    地区管理 地区管理主要实现地区数据的添加.编辑.查看.启用.禁用等功能,另外还包含地区选择控件封装. 业务功能点: 地区数据查看:地区列表树状展现,列表增加省.市.区.县.乡图标. 地区选择控件:选择 ...

  4. c++指针函数的使用——回调函数

    /* 函数指针 函数也是有地址的 所谓函数指针,就是指向函数的指针,函数指针也是一个变量,可以指向不同的函数.同时通过函数指针可以调用其指向函数,从而使函数的调用更加灵活. 函数指针的用途 */ #i ...

  5. Win10 下Cmake编译配置 Opencv3.1 + Cuda7.5 + VS2013

    折腾了三天终于配置成功了,在此写下编译配置的全部步骤和遇到的很多坑. 整体介绍: OpenCV 中 CUDA 实现的函数还不是太多,使用前要在OpenCV的官网上确认以下你想要的功能是否已经实现,否则 ...

  6. JAVA 中转义符的理解

    生物信息中有时候会遇到JAVA写的程序,今天阅读源码的时候发现对于正则中的转义符不好理解,后来查资料后终于弄明白了,这里详细说明一下: 字符串的表示有三种方法:1.直接单字符,例如"A&qu ...

  7. 牛客网编程练习之PAT乙级(Basic Level):1033 害死人不偿命的(3n+1)猜想

    3n+1水题.... AC代码: import java.util.Scanner; /** * @author CC11001100 */ public class Main { public st ...

  8. 这是一个测试,测试markdown语法

    [TOC] 1. chpt1 这是一段话,前面没有空格 前面有4个空格,且在编辑状态下上面没有空行 前面有4个空格,且在编辑状态下上面有一个空行. 前面按了一下tab 1.1 1.1 2 段落1 前面 ...

  9. Android图表库MPAndroidChart(七)—饼状图可以再简单一点

    Android图表库MPAndroidChart(七)-饼状图可以再简单一点 接上文,今天实现的是用的很多的,作用在统计上的饼状图,我们看下今天的效果 这个效果,我们实现,和之前一样的套路,我先来说下 ...

  10. Scheme call/cc 研究

    目前尚不清楚实质,但已经能够从形式上理解它的某些好处,有个很简单的连乘函数可以说明: 为了展示究竟发生了什么,我包装了下乘法函数,将其变为mul. 我们将比较product和xproduct的区别. ...