信号

一、信号的概述

  信号是linux操作系统中进程间通讯的一种有限制的方式。它是一种异步的通知机制,用来提醒进程一个事件已经发生。当一个信号发送给一个进程,操作系统中断了进程正常的控制流程,此时,原本操作将被中断。如果进程定义了信号的处理函数,那么它将被执行,否则就执行默认的处理函数。

1.信号的特点:简单、携带的信息量少、使用在某个特定场景

2.信号的状态:

  产生状态

  未决状态:信号未被处理

  递达状态:信号已被处理

3.处理方式:

  进程A给进程B发信号,首先使用系统函数或命令等,由内核产生信号,并发送给B进程。信号的优先级比较高,进程在收到信号后,暂停正在处理的工作,优先处理信号,处理完成之后再继续暂停的工作。

4.信号四要素:

  信号的名字

  信号的编号

  信号的默认处理动作

  信号的事件

5.通过man文档查看信号

man 7 signal

注意:SIGKILL和SIGSTOP信号不可被捕捉、忽略、阻塞

6.阻塞信号集和未决信号集

  阻塞信号集和未决信号集处于内核的PCB中,即进程控制块中,不能直接操作。

  阻塞信号集存放要屏蔽的信号;未决信号集存放没有被处理的信号。

 

二、信号相关函数

1.kill -- 发送信号给指定的进程

函数原型:int kill(pid_t pid,int sig);

参数:

  pid:>0 发送信号给指定的进程

     =0 发送信号给 和pid属于同一进程组的所有进程

     <-1 取 | pid | 发送给对应的进程

     =-1 发送给进程有权限发送的系统中的所有进程

  sig:信号参数,不推荐使用信号编号,应使用宏名

返回值:

  成功:0

  失败:-1(非法id,信号非法,权限问题)

 

2.raise -- 自己给自己发信号

函数原型:int raise(int sig);

返回值:

  成功:0

  失败:-1

 

3.abort -- 给自己发送异常终止信号

函数原型:void abort(void);

该函数没有返回值,没有参数

 

4.闹钟(定时器)

alarm -- 设置定时器(每个进程只有一个定时器)

alarm使用自然定时法,不受进程状态影响

函数原型:unisgned int alarm(unsigned int seconds);

作用:当设置的时间到达时,发出一个信号SIGALRM

参数:设置的秒数

返回值:

  正常数完:0

  中途更改秒数:上一次为数完的秒数

测试电脑1秒数多少数

 1 #include <stdio.h>
 2 #include <unistd.h>
 3 
 4 int main()
 5 {
 6         int i = 0;
 7         alarm(1);
 8         while(1){
 9                 printf("%d\n",i++);
10         }
11         return 0;
12 }

测试程序运行时间:time 可运行程序

 

setitimer -- 可实现周期性定时的定时器

函数原型:int setitimer(int which,const struct itimerval *new_value,struct itimerval *old_value);

参数:

  which:定时器类型:

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

       ITIMER_VIRTUAL : -以该进程在用户态下花费的时间来计算,它送出SIGVTALRM信号。  

       ITIMER_PROF : 以该进程在用户态下和内核态下所费的时间来计算,它送出SIGPROF信号。

  new_value:指定间隔时间

  old_value:上一次定时间隔时间

返回值:

  成功:0

  失败:-1

struct itimerval{

  struct timerval it_interval;定时器循环周期

  struct timerval it_value;第一次触发定时器时间

}

struct timerval{

  time_t tv_sec;秒

  suseconds_t tv_usec;微秒

}

 

三、信号集

  当内核给进程发送一个信号时,信号处于未决状态。收到信号后,信号被放入进程的未决信号集。

  放入未决信号集的中的信号等待处理,在处理之前需要先判断在阻塞信号集中该信号对应的的标志位是否为1,如果为1则不处理,为0则则处理该信号。

  当阻塞信号集中该信号对应的标志位为0时,该信号被处理。

 

1.信号集操作相关函数

自定义信号集:

int sigemptyset(sigset_t *set);将set集合置空(全部置0)

int sigfillset(sigset_t *set);将所有信号加入set集合(全部置1)

int sigaddset(sigset_t *set,int signo);将signo信号加入到set集合中

int sigdelset(sigset_t *set,int signo);将signo信号从set集合中删除

int sigismember(const sigset_t *set,int signo);判断信号是否存在

 

sigprocmask函数

将自定义信号集设置给阻塞信号集

函数原型:int sigprocmask(int how,const sigset_t *set,sigset_t *oldset);

 

sigpending函数

读取当前进程的未决信号集

函数原型:int sigpending(sigset_t *set);

参数:set -- 内核将未决信号集写入set

设置信号阻塞

 1 #include <stdio.h>
 2 #include <unistd.h>
 3 #include <sys/time.h>
 4 #include <signal.h>
 5 
 6 int main()
 7 {
 8         //创建自定义信号集
 9         sigset_t mysignals;
10         //置空
11         sigemptyset(&mysignals);
12         //设置阻塞的信号
13         sigaddset(&mysignals,SIGINT);//ctrl+c
14         sigaddset(&mysignals,SIGQUIT);//ctrl+反斜杆
15         sigaddset(&mysignals,SIGKILL);
16 
17         //将自定义信号加入阻塞信号集
18         sigprocmask(SIG_BLOCK,&mysignals,NULL);
19 
20         while(1){
21                 int i;
22                 sigset_t pending;
23                 //读取未决信号集
24                 sigpending(&pending);
25                 for(i=1;i<32;i++){
26                         if(sigismember(&pending,i)){
27                                 printf("1");
28                         }else{
29                                 printf("0");
30                         }
31                 }
32                 printf("\n");
33                 sleep(1);
34         }
35         return 0;
36 }

 

四、捕捉信号

1.signal函数

函数原型:sighandler_t signal(int signum,sighandler_t handler);

参数:

  signum:要捕捉的信号

  handler:typedef void (*sighandler_t)(int);

      函数指针,捕捉到信号后执行的操作

捕捉ctrl+c信号(SIGINT)

 1 #include <unistd.h>
 2 #include <stdio.h>
 3 #include <signal.h>
 4 
 5 void myfunc(int no)
 6 {
 7         printf("捕捉到信号:%d\n",no);
 8 }
 9 
10 int main()
11 {
12         //注册捕捉函数
13         signal(SIGINT,myfunc);
14 
15         while(1){
16                 sleep(1);
17                 printf("wait...\n");
18         }
19         return 0;
20 }

 

2.sigaction函数

函数原型:int sigaction(int signum,const struct sigaction *act,struct sigaction *oldact);

参数:

  signum:要捕捉的信号

  act:结构体指针,可设置要执行内容的各项参数

struct sigaction{

  void (*sa_handler)(int);//捕捉信号后执行的函数

  void (*sa_sigaction)(int,siginfo_t *,void *);//同上

  sigset_t sa_mask;//在信号处理函数执行过程中,临时屏蔽指定的信号,执行完成后处理

  int sa_flags;//为0则执行sa_handler,不为0则执行sa_sigaction

};

设置临时屏蔽信号

 1 #include <unistd.h>
 2 #include <stdio.h>
 3 #include <signal.h>
 4 
 5 void myfunc(int no)
 6 {
 7         printf("捕捉到信号:%d\n",no);
 8         sleep(5);
 9         printf("over\n");
10 }
11 
12 int main()
13 {
14         struct sigaction act;
15 
16         act.sa_flags = 0;
17 
18         act.sa_handler = myfunc;
19 
20         sigemptyset(&act.sa_mask);
21         //设置临时屏蔽信号
22         sigaddset(&act.sa_mask,SIGQUIT);
23 
24         sigaction(SIGINT,&act,NULL);
25         while(1){
26         }
27         return 0;
28 }

 

posted @ 2021-02-19 10:10  さくらむすび  阅读(251)  评论(0)    收藏  举报