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. iOS多线程编程--NSOperation(转)

    这篇文章写得非常不错,基础用法都涉及到了,我把文章提到的例子都写到了demo里面, 原文地址: iOS多线程--彻底学会多线程之『NSOperation』 demo下载:https://github. ...

  2. Python中迭代输出(index,value)的几种方法

    需求如下:迭代输出序列的索引(index)和索引值(value). 1.创建测试列表: >>> lst = [1,2,3,4,5] 2.实现方法如下: #方法1:range()+le ...

  3. 【已解决】IIS搭建 asp.net core 项目后 其他电脑访问不到资源文件

    IIS搭建asp.net core 项目后,访问不到里面的资源文件(图片等),解决方法如下: 1.检查asp.net core发布文件中的资源文件是不是都放到了wwwroot名称的目录中. 2.检查a ...

  4. PHP MySQL Update

    UPDATE 语句用于中修改数据库表中的数据. 更新数据库中的数据 UPDATE 语句用于更新数据库表中已存在的记录. 语法 UPDATE table_name SET column1=value, ...

  5. blog写作心得体会

    虽然写blog也挺久了,写出来的东西自己回顾的时候也会怀疑读者是否能看的明白,还是有种流水账的感觉,以后希望多从读者的角度出发.下面记录一些以后写博客的注意点. 具体关于某种技术点的小知识还有碰到的各 ...

  6. 操作系统内核Hack:(四)内核雏形

    操作系统内核Hack:(四)内核雏形 在本系列的前一篇文章<操作系统内核Hack:(三)BootLoader制作>中,我们制作出了一个两阶段引导BootLoader,并进入了一个内核的空壳 ...

  7. python命令行参数解析模块argparse和docopt

    http://blog.csdn.net/pipisorry/article/details/53046471 还有其他两个模块实现这一功能,getopt(等同于C语言中的getopt())和弃用的o ...

  8. iOS学习笔记--Quartz2D

    Quartz 2D是一个二维绘图引擎,同时支持iOS和Mac系统. Quartz 2D能完成的工作: 1. 绘制图形 : 线条\三角形\矩形\圆\弧等 2. 绘制文字 3. 绘制\生成图片(图像) 4 ...

  9. Unity UGUI图文混排(六) -- 超链接

    图文混排更新到超链接这儿,好像也差不多了,不过就在最后一点,博主也表现得相当不专业,直接整合了山中双木林同学提供的超链接的解决方案,博主甚至没来得及细看就直接复制了,但感觉还是挺好用的. 博主已经将超 ...

  10. sql group句子

    rollup SELECT employee_id,department_id,job_id,SUM(salary) FROM employees WHERE department_id <60 ...