1、概念

    ctrl-c给进程发送一个SIGINT的信号,这个信号的默认处理动作是终止进程,ctrl-c产生的信号只能发给前台进程

    进程收到信号,不是立即处理,而是先记录起来恰当时候再处理

2、信号列表

     使用kill -l显示系统的所有信号,1-31为普通信号(31个),34-64为实时信号(31个)

3、产生信号

  (1)通过键盘发送信号给前台,例如ctrl-c产生SIGINT信号,ctrl-\产生SIGQUIT信号,ctrl-z产生SIGTSTP信号

信号

 (2)硬件异常


 (3)通过指令

 alarm函数

#include<stdio.h>
#include<unistd.h>
int  main()
{
 int count=0;
 alarm(1);
 for(;2;count++){
  printf("count=%d\n",count);
 }
 return 0;

}

信号

此函数作用为:1秒钟不停的数数,1秒钟到了就被SIGALRM信号终止

4、信号处理(信号递达)

 (1)忽略信号

 (2)执行默认处理动作

 (3)自定义处理信号的函数(捕捉信号)

5、阻塞信号

    实际执行信号的处理动作,称为信号递达;信号从产生到递达之间的状态,称为信号未决。进程可以选择阻塞某个信号,被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作。

    阻塞是暂时不处理此信号,而忽略则是处理此信号;信号产生与阻塞无关,递达与解除阻塞无关

信号在内核中的表示示意图 

信号


    POSIX.1允许系统递送该信号一次或多次,常规信号在递达之前产生多次只计一次,而实时信号在递达之前产生多次可以依次放在一个队列里。图中每个信号只有一个bit的未决标志,非0 即1,不记录该信号产生了多少次,阻塞信号也这样表示

     未决和阻塞标志用相同的数据类型sigset_t来存储,sigset_t称为信号集

     阻塞信号集也称为当前进程的信号屏蔽字

6、信号集操作函数

   #include<signal.h>

   int sigemptyset(sigset_t  *set)//使所有信号对应的bit清零(初始化状态)

   int sigfillset(sigset_t  *set)//使所有信号对应的bit置位(初始化)

   int sigaddset(sigset_t  *set, int signo)//添加某种信号

   int sigdelset(sigset_t  *set, int signo)//删除某种信号

   int sigismember(const sigset_t  *set, int signo)//布尔函数,判断信号集有效信号中是否包含某种信号,包含返回1,不包含返回0,出错返回-1

7、sigprocmask

     调用函数sigprocmask可以读取或更改进程的信号屏蔽字

函数原型:

  #include<signal.h>

  int sigprocmask(int how, const sigset_t *set, sigset_t *oset)

  返回值:若成功则为0,若出错为-1

  若oset是非空指针,则读取进程的当前信号屏蔽字通过oset参数传出;若set是非空指针,则更改进程的信号屏蔽字由how指示如何更改;若oset和set都是非空指针,则先将原来的信号屏蔽字备份到oset里,然后根据set和how参数更改信号屏蔽字

   如果调用sigprocmask解除了对当前若干个未决信号的阻塞,则在sigprocmask返回前,至少将其中一个信号递达。

 8、sigpending

   #include<signal.h>

   int sigpending(sigset_t *set)

  sigpending读取当前进程的未决信号集,通过set参数传出,调用成功返回0,出错返回-1

 

几个函数的代码实现:

#include<stdio.h>
#include<signal.h>
#include<unistd.h>

void printsigset(sigset_t *set)
{
 int i=0;
 for(;i<32;i++){
  if(sigismember(set, i)){  // 判断指定信号是否在目标集合中
   putchar('1');
  }else{
   putchar('0');
  }
 }
 puts("\0");
}
int main()
{
 sigset_t s,p;
 sigemptyset(&s);  // 定义信号集对象,并清空初始化
 sigaddset(&s,SIGINT);  // ctrl-c操作
 sigprocmask(SIG_BLOCK,&s,NULL); //设置阻塞信号集,设置SIGINT信号
  while(1){
   sigpending(&p);  //获取未决信号集
   printsigset(&p);
   sleep(1);
  }
 return 0;
}

信号