1.基本概念
    中断:
          中断是系统对于异步事件的响应
          中断信号
          中断源
          现场信息
          中断处理程序
          中断向量表
            异步事件的响应:进程执行代码的过程中可以随时被打断,然后去执行异常处理程序
            生活中的中断和计算机系统中的中断
            1)    无中断生活场景
            张三看书,厨房烧水
            2)有中断的生活场景
            张三看书,设置闹钟,厨房烧水。
            闹钟发出中断信号,张三把书合好(第20页),去厨房把开水事情处理好,张三重新打开20页进行阅读。
            3)计算机系统的中断场景
            中断源发出中断信号,CPU判断中断是否屏蔽屏蔽、保护现场,cpu执行中断处理程序,cpu恢复现场,继续原来的任务。
            4)中断的其他概念
            中断向量表保存了中断处理程序的入口地址。
            中断个数固定,操作系统启动时初始化中断向量表。
            中断有优先级(有人敲门,有人打电话,有优先级)
            中断可以屏蔽(张三可以屏蔽电话)。
    中断分类:
              硬件中断(外部中断)
                 外部中断是指由外部设备通过硬件请求的方式产生的中断,也称为硬件中断
              软件中断(内部中断)
                 内部中断是由CPU运行程序错误或执行内部程序调用引起的一种中断,也称为软件中断。
              x86平台INT指令 ARM软中断指令SWI
    信号概念:
                   信号是UNIX系统响应某些状况而产生的事件,进程在接收到信号时会采取相应的行动。
               信号是因为某些错误条件而产生的,比如内存段冲突、浮点处理器错误或者非法指令等
               信号是在软件层次上对中断的一种模拟,所以通常把它称为是软中断
    信号和中断的区别:
                   信号与中断的相似点:
                         (1)采用了相同的异步通信方式;
                         (2)当检测出有信号或中断请求时,都暂停正在执行的程序而转去执行相应的处理程序;
                         (3)都在处理完毕后返回到原来的断点;
                         (4)对信号或中断都可进行屏蔽。
                    信号与中断的区别:
                       (1)中断有优先级,而信号没有优先级,所有的信号都是平等的;
                       (2)信号处理程序是在用户态下运行的,而中断处理程序是在核心态下运行;
                       (3)中断响应是及时的,而信号响应通常都有较大的时间延迟。
2.信号名称及常用信号解释
    kill –l    可以查看linux内核支持的信号
    Man 7 signal 查看信号的默认动作、信号的含义
            信号名称    描述
            SIGABRT        进程停止运行 6
            SIGALRM        警告钟
            SIGFPE        算述运算例外
            SIGHUP        系统挂断
            SIGILL        非法指令
            SIGINT        终端中断 2
            SIGKILL        停止进程(此信号不能被忽略或捕获)
            SIGPIPE        向没有读者的管道写入数据
            SIGSEGV        无效内存段访问
            SIGQUIT        终端退出3
            SIGTERM        终止
            SIGUSR1        用户定义信号1
            SIGUSR2        用户定义信号2
            SIGCHLD        子进程已经停止或退出
            SIGCONT        如果被停止则继续执行
            SIGSTOP        停止执行
            SIGTSTP        终端停止信号
            SIGTOUT        后台进程请求进行写操作
            SIGTTIN        后台进程请求进行读操作
3.信号处理
    进程对信号的三种响应
          1)忽略信号
                不采取任何操作、有两个信号不能被忽略:SIGKILL(9号信号)和SIGSTOP。
                注意:为什么进程不能忽略SIGKILL、SIGSTOP信号。(如果应用程序可以忽略这2个信号,系统管理无法杀死、暂停进程,无法对系统进行管理。)。SIGKILL(9号信号)和SIGSTOP信号是不能被捕获的。
          2)捕获并处理信号
                内核中断正在执行的代码,转去执行先前注册过的处理程序。
          3)执行默认操作
                默认操作通常是终止进程,这取决于被发送的信号。
                注意:信号的默认操作:通过 man 7 signal 进程查看
4.signal信号安装函数
    1)signal函数作用
                (1):站在应用程序的角度,注册一个信号处理函数。
                (2):忽略信号、设置信号默认处理信号的安装和恢复
                        typedef void (*__sighandler_t) (int);
                        #define SIG_ERR ((__sighandler_t) -1)
                        #define SIG_DFL ((__sighandler_t) 0)
                        #define SIG_IGN ((__sighandler_t) 1)
    2)函数原型
        __sighandler_t signal(intsignum, __sighandler_t handler);
        参数:
                1)signal是一个带signum和handler两个参数的函数,准备捕捉或屏蔽的信号由参数signum给出,接收到指定信号时将要调用的函数由handler给出
            2)handler这个函数必须有一个int类型的参数(即接收到的信号代码),它本身的类型是void
            3)handler也可以是下面两个特殊值:
                                                SIG_IGN    屏蔽该信号
                                                SIG_DFL    恢复默认行为
5.信号发送
    1)kill函数
            kill基本用法:    
                        发送信号的函数有kill和raise
                        区别:kill既可以向自身发送信号,也可以向其他进程发送信号;
                        raise函数向进程自身发送信号。
            intkill(pid_tpid, intsiq)
            int raise(intsigno)
            参数组合情况解释:
                            kill(pid_tpid, intsiq)
                            pid>0 将信号sig发给pid进程
                            pid=0 将信号sig发给同组进程
                            pid=-1 将信号sig发送给所有进程,调用者进程有权限发送的每一个进程(除了1号进程之外,还有它自身)
                            pid<-1 将信号sig发送给进程组是pid(绝对值)的每一个进程

注意:如果在fork之前安装信号,则子进程可以继承信号。
            sleep函数几点说明:
                            (1)sleep函数作用,让进程睡眠。
                            (2)能被信号打断,然后处理信号函数以后,就不再睡眠了。直接向下执行代码
                            (3)sleep函数的返回值,是剩余的秒数
    2)raise函数
                
            raise给自己发送信号。raise(sig)等价于kill(getpid(), sig);
            killpg给进程组发送信号。killpg(pgrp, sig)等价于kill(-pgrp, sig);
            sigqueue给进程发送信号,支持排队,可以附带额外数据信息。
    3)alarm函数
            unsigned int alarm(unsigned int seconds);
            alarm函数,设置一个闹钟延迟发送信号告诉linux内核n秒中以后,发送SIGALRM信号

 #include<stdio.h>
#include<stdlib.h>
#include <signal.h>
#include <unistd.h>
#include<errno.h>
void myhandle(int num)
{
printf("recv signal id num : %d \n", num);
alarm();
}
int main()
{
printf("main ....begin\n");
if (signal(SIGALRM, myhandle) == SIG_ERR)
{
perror("func signal err\n");
return ;
}
alarm();
while()
{
pause();
printf("pause return\n");
}
return ;
}

6.信号的阻塞和未达
        信号在内核中的表示:
            执行信号的处理动作称为信号递达(Delivery),信号从产生到递达之间的状态,称为信号未决(Pending)。进程可以选择阻塞(Block)某个信号。被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作。
           注意:阻塞和忽略是不同,只要信号被阻塞就不会递达,而忽略是在递达之后可选的一种处理动作。信号在内核中的表示可以看作是这样的:

      

       说明1)PCB进程控制块中结构体中有信号屏蔽状态字(block),信号未决状态字(pending)还有是否忽略标志;
            说明2)信号屏蔽状态字(block),1代表阻塞、0代表不阻塞;信号未决状态字(pending)的1代表未决(表示有未达信号),0代表信号可以抵达了;
            说明3)向进程发送SIGINT,内核首先判断信号屏蔽状态字是否阻塞,信号未决状态字(pending相应位制成1;若阻塞解除,信号未决状态字(pending)相应位制成0;表示信号可以抵达了。
            说明4)block状态字、pending状态字 64bit;//socket select
            说明5)block状态字用户可以读写,pending状态字用户只能读;这是信号设计机制。

   信号集操作函数(状态字表示)
                intsigemptyset(sigset_t *set);把信号集清空64bit/8=8个字节
                intsigfillset(sigset_t *set);把信号集置成1
                intsigaddset(sigset_t *set, intsigno);根据signo,把信号集中的对应bit置成1
                intsigdelset(sigset_t *set, intsigno);根据signo,把信号集中的对应bit置成0
                intsigismember(constsigset_t *set, intsigno);//判断signo是否在信号集中
        sigprocmask读取或更改进程的信号屏蔽状态字(block)
                int sigprocmask(int how, constsigset_t *set, sigset_t *oset);
                返回值:若成功则为0,若出错则为-1
                如果oset是非空指针,则读取进程的当前信号屏蔽字通过oset参数传出。如果set是非空指针,则更改进程的信号屏蔽字,参数how指示如何更改。如果oset和set都是非空指针,则先将原来的信号屏蔽字备份到oset里,然后根据set和how参数更改信号屏蔽字。假设当前的信号屏蔽字为mask,下表说明了how参数的可选值。

      

      SIG_BLOCK ,讲信号集set添加到进程block状态字中。

    sigpending获取信号未决状态字(pending)信息:int   sigpending(sigset_t *set);

 #include<stdio.h>
#include<stdlib.h>
#include <signal.h>
#include <unistd.h>
#include<errno.h>
void handler(int sig)
{
if (sig == SIGINT)
printf("recv a sig=%d\n", sig);
else if (sig == SIGQUIT)
{
sigset_t uset;
sigemptyset(&uset);
sigaddset(&uset, SIGINT);
//ctr + \ 用来触发 SIGINT 信号
//解除阻塞
sigprocmask(SIG_UNBLOCK, &uset, NULL);
}
} void printsigset(sigset_t *set)
{
int i;
for (i=; i<NSIG; ++i)
{
if (sigismember(set, i))
putchar('');
else
putchar('');
}
printf("\n");
}
// 连续的按ctrl+c键盘,虽然发送了多个SIGINT信号,但是因为信号是不稳定的,只保留了一个。
//不支持排队
int main(int argc, char *argv[])
{
sigset_t pset; //用来打印的信号集
sigset_t bset; //用来设置阻塞的信号集 sigemptyset(&bset);
sigaddset(&bset, SIGINT); if (signal(SIGINT, handler) == SIG_ERR)
ERR_EXIT("signal error"); if (signal(SIGQUIT, handler) == SIG_ERR)
ERR_EXIT("signal error"); //读取或更改进程的信号屏蔽字这里用来阻塞ctrl+c信号
//ctrl+c信号被设置成阻塞,即使用户按下ctl+c键盘,也不会抵达
sigprocmask(SIG_BLOCK, &bset, NULL); for (;;)
{
//获取未决字信息
sigpending(&pset); //打印信号未决sigset_t字
printsigset(&pset);
sleep();
}
return ;
}

7.sigaction函数
        包含头文件<signal.h>
        功能:sigaction函数用于改变进程接收到特定信号后的行为。
        原型:int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);
        参数:
                该函数的第一个参数为信号的值,可以为除SIGKILL及SIGSTOP外的任何一个特定有效的信号(为这两个信号定义自己的处理函数,将导致信号安装错误)
                第二个参数是指向结构sigaction的一个实例的指针,在结构sigaction的实例中,指定了对特定信号的处理,可以为空,进程会以缺省方式对信号处理
                第三个参数oldact指向的对象用来保存原来对相应信号的处理,可指定oldact为NULL。
        返回值:函数成功返回0,失败返回-1
        sigaction结构体:
                第二个参数最为重要,其中包含了对指定信号的处理、信号所传递的信息、信号处理函数执行过程中应屏蔽掉哪些函数等等
                struct sigaction {
                    void (*sa_handler)(int);   //信号处理程序不接受额外数据
                    void (*sa_sigaction)(int, siginfo_t *, void *); //信号处理程序能接受额外数据,和sigqueue配合使用
                    sigset_t sa_mask; //
                    int sa_flags; //影响信号的行为SA_SIGINFO表示能接受数据
                    void (*sa_restorer)(void); //废弃
                    };
                    注意:回调函数句柄sa_handler、sa_sigaction只能任选其一。

   sigaction的函数注册信号,基本用法代码:

 #include<stdio.h>
#include<stdlib.h>
#include <signal.h>
#include <unistd.h>
#include<errno.h>
void handler(int sig)
{
printf("recv a sig=%d\n", sig);
} __sighandler_t my_signal(int sig, __sighandler_t handler)
{
struct sigaction act;
struct sigaction oldact;
act.sa_handler = handler;
sigemptyset(&act.sa_mask);
act.sa_flags = ; if (sigaction(sig, &act, &oldact) < )
return SIG_ERR; return oldact.sa_handler;
} int main(int argc, char *argv[])
{
struct sigaction act;
sigset_t sa_mask; act.sa_handler = handler;
act.sa_flags = ;
sigemptyset(&act.sa_mask); //测试信号安装函数
sigaction(SIGINT, &act, NULL); //模拟signal函数
//my_signal(SIGINT, handler); for (;;)
{
pause();
}
return ;
}

  如上图修改对应地方编译后,都可以实现效果

  测试sigaction结构体第三个参数sigset_tsa_mask的作用,代码如下:

 #include<stdio.h>
#include<stdlib.h>
#include <signal.h>
#include <unistd.h>
#include<errno.h>
/*
struct sigaction {
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void);
} */
//测试sigaction结构体第三个参数sigset_t sa_mask的作用
//作用sigaddset(&act.sa_mask, SIGQUIT); 加入到sa_mask中的信号,被阻塞(信号处理函数执行的过程中被阻塞)。
//注意:SIGQUIT信号最终还会抵达
void handler(int sig);
int main(int argc, char *argv[])
{
struct sigaction act;
act.sa_handler = handler; sigemptyset(&act.sa_mask);
sigaddset(&act.sa_mask, SIGQUIT);
act.sa_flags = ; if (sigaction(SIGINT, &act, NULL) < )
{
perror("sigaction error");
} for (;;)
{
pause();
}
return ;
} void handler(int sig)
{
printf("recv a sig=%d 信号处理函数执行的时候,阻塞sa_mask中的信号\n", sig);
sleep();
}

结论:sigaddset(&act.sa_mask, SIGQUIT) 加入到sa_mask中的信号,被阻塞(信号处理函数执行的过程中被阻塞),SIGQUIT信号最终还会抵达;

8.sigqueue函数
        功能:新的发送信号系统调用,主要是针对实时信号提出的支持信号带有参数,与函数sigaction()配合使用。
     注意:和kill函数相比int kill(pid_tpid, intsiq)多了参数
     原型:int sigqueue(pid_t pid, int sig, const union sigval value);
        参数:
           sigqueue的第1个参数是指定接收信号的进程id,第2个参数确定即将发送的信号,第3个参数是一个联合数据结构union sigval,指定了信号传递的参数,即通常所说的4字节值。
                        union sigval {
                                int   sival_int;
                                void *sival_ptr;
                                };
        返回值:成功返回0,失败返回-1
        sigqueue()比kill()传递了更多的附加信息,但sigqueue()只能向一个进程发送信号,而不能发送信号给一个进程组。
9.其他介绍
    三种睡眠函数:
            unsigned int sleep(unsigned int seconds);秒
            若被中断打断,返回剩余时间
            int usleep(useconds_tusec);微妙
            若被中断打断,返回剩余时间
            int nanosleep(const struct timespec *req, struct timespec *rem);纳秒时间
            要睡眠的时间req;剩余睡眠时间,如果要中断,通过rem返回过来。
    三种时间结构:
            time_t秒
            struct timeval {
                long    tv_sec;         /* seconds */
                long    tv_usec;        /* microseconds */微妙
            };
            struct timespec {纳秒
                time_ttv_sec;        /* seconds */
                long   tv_nsec;       /* nanoseconds */
            };
    setitime函数:间隙性产生
            包含头文件<sys/time.h>
            功能setitimer()比alarm功能强大,支持3种类型的定时器
            原型:int setitimer(int which, const struct itimerval *new_value,struct itimerval *old_value);
            参数:
                第一个参数which指定定时器类型
                第二个参数是结构itimerval的一个实例,结构itimerval形式
                第三个参数可不做处理。
            返回值:成功返回0失败返回-1
            ITIMER_REAL:经过指定的时间后,内核将发送SIGALRM信号给本进程
            ITIMER_VIRTUAL :程序在用户空间执行指定的时间后,内核将发送SIGVTALRM信号给本进程
            ITIMER_PROF :进程在内核空间中执行时,时间计数会减少,通常与ITIMER_VIRTUAL共用,代表进程在用户空间与内核空间中运行指定时间后,内核将发送SIGPROF信号给本进程.

linux信号的介绍的更多相关文章

  1. Linux 信号介绍

    是内容受限时的一种异步通信机制 首先是用来通信的 是异步的 本质上是 int 型的数字编号,早期Unix系统只定义了32种信号,Ret hat7.2支持64种信号,编号0-63(SIGRTMIN=31 ...

  2. Linux性能工具介绍

    l  Linux性能工具介绍 p  CPU高 p  磁盘I/O p  网络 p  内存 p  应用程序跟踪 l  操作系统与应用程序的关系比喻为“唇亡齿寒”一点不为过 l  应用程序的性能问题/功能问 ...

  3. Linux core 文件介绍

    Linux core 文件介绍 http://www.cnblogs.com/dongzhiquan/archive/2012/01/20/2328355.html 1. core文件的简单介绍在一个 ...

  4. Linux信号(signal) 机制分析

    Linux信号(signal) 机制分析 [摘要]本文分析了Linux内核对于信号的实现机制和应用层的相关处理.首先介绍了软中断信号的本质及信号的两种不同分类方法尤其是不可靠信号的原理.接着分析了内核 ...

  5. Linux 启动参数介绍

    Linux 启动参数介绍 取自2.6.18 kernel Documentation/i386/boot.txt 文件中介绍 vga= 这里的不是一个整数(在C语言表示法中,应是十进制,八进制或者十六 ...

  6. 非常好的一篇对linux信号(signal)的解析 (转载)【转】

    转自:https://blog.csdn.net/return_cc/article/details/78845346 Linux信号(signal) 机制分析 转载至:https://www.cnb ...

  7. Linux信号机制

    Linux信号(signal) 机制分析 [摘要]本文分析了Linux内核对于信号的实现机制和应用层的相关处理.首先介绍了软中断信号的本质及信号的两种不同分类方法尤其是不可靠信号的原理.接着分析了内核 ...

  8. linux信号基本概念及如何产生信号

    linux信号基本概念及如何产生信号 摘自:https://blog.csdn.net/summy_j/article/details/73199069 2017年06月14日 09:34:21 阅读 ...

  9. Linux信号(signal) 机制分析(转)

    [摘要]本文分析了Linux内核对于信号的实现机制和应用层的相关处理.首先介绍了软中断信号的本质及信号的两种不同分类方法尤其是不可靠信号的原理.接着分析了内核对于信号的处理流程包括信号的触发/注册/执 ...

随机推荐

  1. [Chrome] 如何下载老版本的 Chrome

    Google 官方只提供了最新版的 Chrome, 在旧版本的系统(如:Ubuntu 12.04 LTS)安装不上 这里提供了 Chrome 的历史版本下载 备注:Ubuntu 12.04 LTS 可 ...

  2. Net 常用资源

    opensource: http://www.dotnetfoundation.org/projects https://github.com/dotnet/corefx Enterprise Lib ...

  3. bootloader,kernel,initrc

    http://www.ibm.com/developerworks/cn/linux/l-k26initrd/index.html http://www.68idc.cn/help/server/li ...

  4. 剑指Offer——不用加减乘除做加法

    题目描述: 写一个函数,求两个整数之和,要求在函数体内不得使用+.-.*./四则运算符号. 分析: "^"是不带进位的加法. "&"可以得到所有进位位组 ...

  5. 【非root用户】安装【python,pip,package】

    安装python: 下载源码 解压 进入 ./configure --prefix=/path/python3.6 注意一定要设置prefix,否则默认安装到/usr/local make make ...

  6. CloudFoundry V2 单机版离线安装(伪离线安装)

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/wangdk789/article/details/30255763     之前安装CloudFou ...

  7. DevExpress控件学习总结

    1.Navigation & Layout 1.1 Bar Manager 如果想在窗体或用户控件(user control)上添加工具条(bars)或弹出菜单(popup menus),我们 ...

  8. 从数学分析的角度来看Softmax

    作者:无影随想 时间:2016年1月. 出处:https://zhaokv.com/machine_learning/2016/01/softmax-calculous-perspective.htm ...

  9. MySQL高可用架构之MHA(转)

    简介: MHA(Master High Availability)目前在MySQL高可用方面是一个相对成熟的解决方案,它由日本DeNA公司youshimaton(现就职于Facebook公司)开发,是 ...

  10. 网络爬虫Java实现抓取网页内容

    package 抓取网页; import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream; ...