zoukankan      html  css  js  c++  java
  • Linux 对信号的总结

    Linux信号_总结

    对信号本质的理解:

    类似于中断,区别在于中断是由硬件产生的,而信号是由软件实现的。

    信号的来源:

    触发硬件(触发键盘,或是硬件故障);软件信号函数kill 、alarm、setitimer、sigqueue 等函数。

    信号的分类:

    可靠信号与不可靠信号,实时信号与非实时信号;

    不可靠信号:

    SIGRTMIN前的信号称为不可靠信号,在早期这段信号可能做出错误的反应,或是丢失。因此对此段信号成为不可靠信号。

    可靠信号:

    在SIGRTMIN与SIGRTMAX之间的信号称做可靠信号,可靠信号是为了防止信号丢失的。这些信号可以排队处理。

    实时信号与非实时信号:

    非实时信号都不支持排队,都是不可靠信号;实时信号都是支持排队的,都是可靠信号;

    对信号的响应:

    响应的三种方式

    (1)忽略信号

    有两个特殊的信号SIGKILL 和SIGSTOP信号不能被忽略。

    (2)捕捉信号

    给对应的信号绑定响应的处理函数,带到信号产生时,执行对应的函数。

    (3)执行缺省信号

    进程对实时信号的缺省反应时进程的终止。

    信号的发送:

    发送信号的函数有,kill(), alarm(),raise(),setitimer();

    (1)kill(int pid, int signal);

    PID参数信号的就收进程
    pid>0 进程的ID为pid的进程
    pid=0 同一个进程组
    pid<0 && pid!=-1 进程组ID为pid绝对值的所有进程
    pid=-1 发送至所有ID大于1的进程

    参数介绍:

    pid为进程号,singnal为信号值。

    kill常用于pid>0的信号处理,调用成功返回0,否则返回-1。

    (2)alarm(unsigned int seconds)

    专门为SIGALRM信号而设函数,seconds表示时间,此函数意味着在seconds秒后向SIGALRM信号发送消息。

    进程调用alarm后,以前的alarm()调用都将无效。若调用alarm()前,进程中已经设置了闹钟,则返回上一个闹钟生于的时间,否则返回0;

    eg:

    #include<signal.h>
    #include<stdio.h>
    int main(void)
    {
    printf("first time return:%d ",alarm(4));
    sleep(1);
    printf("after sleep(1),remain:%d ",alarm(2));
    printf("renew alarm,remain:%d ",alarm(1));
    }

    //运行结果为
    first time return:0
    after sleep(1),remain:3
    renew alarm,remain:2

    (3)raise(int signal);

    此函数时向本进程发送signal信号的,signal为即将发送的信号值。调用成功返回0;否则返回 -1。

    (4)setitimer()函数

    int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue));

    结构体介绍:

    struct itimerval 
    {
     struct timeval it_interval;//间隔时间
     struct timeval it_value; //初始时间
     };  

    struct timeval
    {
       long tv_sec; //秒
       long tv_usec; //微妙
    };            

    参数描述:

    which:表示定时器类型,setitimer有三种定时器类型。

    ITIMER_REAL : 以系统真实的时间来计算,它送出SIGALRM信号。  

    ITIMER_VIRTUAL : 设定程序执行时间;经过指定的时间后,内核将发送SIGVTALRM信号给本进程;

    ITIMER_PROF : 设定进程执行以及内核因本进程而消耗的时间和,经过指定的时间后,内核将发送ITIMER_VIRTUAL信号给本进程;

    it_interval指定间隔时间,it_value指定初始定时时间。如果只指定it_value,就是实现一次定时;如果同时指定 it_interval,则超时后,系统会重新初始化it_value为it_interval,实现重复定时;

    eg:

    #include <signal.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <sys/time.h>

    void sigroutine(int signo) {
           switch (signo) {
                   case SIGALRM:
                           printf("Catch a signal -- SIGALRM ");
                           break;
                   case SIGVTALRM:
                           printf("Catch a signal -- SIGVTALRM ");
                           break;
          }
    }

    int main(int argc, char ** argv) {
           struct itimerval value,ovalue,value2;

           printf("process id is %d ",getpid());
           signal(SIGALRM, sigroutine); //为SIGALRM信号绑定sigroutine函数
           signal(SIGVTALRM, sigroutine); //为SIGVTALRM信号绑定sigroutine函数

           value.it_value.tv_sec = 1;//设定起始时间
           value.it_value.tv_usec = 0;
           value.it_interval.tv_sec = 1;//设定终止时间
           value.it_interval.tv_usec = 0;
           setitimer(ITIMER_REAL, &value, &ovalue);

           value2.it_value.tv_sec = 0;
           value2.it_value.tv_usec = 500000;
           value2.it_interval.tv_sec = 0;
           value2.it_interval.tv_usec = 500000;
           setitimer(ITIMER_VIRTUAL, &value2, &ovalue);

           for (;;) ;
    }

    //运行结果为
    process id is 3136
    Catch a signal -- SIGVTALRM
    Catch a signal -- SIGALRM
    Catch a signal -- SIGVTALRM
    Catch a signal -- SIGVTALRM
    Catch a signal -- SIGALRM
    Catch a signal -- SIGVTALRM
    Catch a signal -- SIGVTALRM
    Catch a signal -- SIGALRM
    Catch a signal -- SIGVTALRM
    Catch a signal -- SIGVTALRM
    Catch a signal -- SIGALRM
    Catch a signal -- SIGVTALRM
    Catch a signal -- SIGVTALRM
    Catch a signal -- SIGALRM
    Catch a signal -- SIGVTALRM
    Catch a signal -- SIGVTALRM
    Catch a signal -- SIGALRM
    Catch a signal -- SIGVTALRM
    Catch a signal -- SIGVTALRM

    安装信号:

    由signal()、sigaction()处理:

    (1)signal(int signum, sighandler_t handler);

    此函数的作用是,为handler函数,或处理过程绑定一个信号,每当出现信号后,进行handler处理。

    signum:所指信号;

    handler:处理过程,可以时函数的指针。这个也可设置为"SIG_IGN",表示忽略此信号,"SIG_DFL"表示以系统默认方式处理此信号。(注意:SIGKILL SIGSTOP不可被安装)

    此函数的例子可参考上一个例子。

    (2)sigaction();

    int sigaction(int signum,const struct sigaction *act,struct sigaction *oldact));

    signum:指定的信号(除SIGKILL,SIGSTOP外)

    sigaction:指向结构指针,指定对特定信号的处理

    oldact:指向的对象用来保存原来对相应信号的处理

    sigaction()函数中第二个参数最为关键。

    sigaction结构体如下:

    struct sigaction 
    {
          void     (*sa_handler)(int);
          void     (*sa_sigaction)(int, siginfo_t *, void *);
          sigset_t   sa_mask;
          int        sa_flags;  //会影响信号接受特殊标志
          void     (*sa_restorer)(void);
      };

    (1)结构体中的sa_restorer已经不使用可以忽略。

    (2)sa_handler指定的处理函数只有一个参数类似于使用signal()函数

    (3)sa_sigaction也是指定信号的处理函数,不过可以带三个参数:

    第一个参数为信号值;

    第二个参数是指向siginfo_t结构的指针;

    第三个参数没有使用;

    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) */
    };

    (4)sa_mask指定在信号处理程序执行过程中,哪些信号应当被阻塞。缺省情况下当前信号本身被阻塞,防止信号的嵌套发送,除非指定SA_NODEFER或者SA_NOMASK标志位。

    注:请注意sa_mask指定的信号阻塞的前提条件,是在由sigaction()安装信号的处理函数执行过程中由sa_mask指定的信号才被阻塞。

    (5)sa_flags标志位:

    当sa_flags设置为SA_SIGINFO时,示信号附带的参数可以传递到信号处理函数中。即使sa_sigaction指定信号处理函数,如果不设置SA_SIGINFO,信号处理函数同样不能得到信号传递过来的数据,在信号处理函数中对这些信息的访问都将导致段错误。

    信号,介绍先到此,如若觉得又不对的地方,请指出,共同进步谢谢!

    参考博客有:

    https://www.ibm.com/developerworks/cn/linux/l-ipc/part2/index1.html

    http://www.cnblogs.com/dandingyy/articles/2653218.html

  • 相关阅读:
    [C++]DirectShow检测音视频输入设备及其采集参数
    [C#] 使用Accord.Net,实现相机画面采集,视频保存及裁剪视频区域,利用WriteableBitmap高效渲染
    [C#]使用第三方开源库iText7.pdfHtml,将Html转换成Pdf,以及如何以Html作为打印模板
    C# 佳能相机SDK对接,采集并保存视频,使用WriteableBitmap高效渲染
    wpf常用类型转换器,支持基元类型、可空基元类型、枚举
    wpf单位转换及DPI获取
    使用wpf技术实现画图工具
    InstallShield 创建 visual studio 工程的时候 指向 任意 visual studio 版本 方法 (修改 计算机 默认 visual studio shell 版本)
    WPF ScrollViewer(滚动条) 自定义样式表制作 再发一套样式 细节优化
    C#实现屏幕指定区域截屏
  • 原文地址:https://www.cnblogs.com/XLX-0327/p/10697884.html
Copyright © 2011-2022 走看看