Linux系统应用编程---信号

一、信号产生种类

1、特殊终端按键

Ctrl+C                  SIGINT

Crtl+Z                  SIGTSTP

Ctrl+\                   SIGQUIT

2、硬件异常

除0操作

访问非法内存

3、Kill函数或者kill指令

#include <sys/types.h>

#include <signal.h>

int kill(pid_t pid, int sig);

pid参数说明

Pid参数

说明

Pid > 0

Sig发送给ID为pid的进程

Pid = 0

Sig信号发送给与调用kill的那个进程同组的所有进程

Pid = -1

sig信号将送往所有调用进程有权给其发送信号的进程,除了进程1(init)。

Pid < -1

sig发送给组ID为|-pid|的进程,并且发送进程具有向其发送信号的权限

sig参数为kill –l看到的前32个信号

4、某种软件条件已经发生

比喻定时器定时1s

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


int main(void)
{
       int counter;
       alarm(1);
       /*

              sleep(1)与alarm(1)的区别
              sleep(1)就是睡在这里,下面的代码不去执行
              alarm(1)只是定时1s,下面的代码还是会继续执行
       */

       for(counter=0; 1; counter++)
              printf("counter = %d.\n", counter);
             
       return 0;
}

 

二、进程处理信号行为

manpage里信号有3种处理方式

1.默认处理动作(man 7 signal可以看到)

term                     终止此信号

core                     终止当前进程并且产生段错误

ign                       忽略此信号

stop                     暂停(挂起)此信号

cont                     继续此进程的执行(暂停之后继续)

2.忽略

3.捕捉(用户自定义信号处理函数,类似于中断服务程序)

三、信号处理函数

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

 

下图给出信号从产生到抵达的执行过程

1、阻塞信号集是用户可以设置的,未决信号集是用户不能设置的;

2、系统规定有2个信号不能被阻塞,SIGKILL和SIGSTOP

3、内核向进程发送一个信号,到信号的执行过程分为以下步骤

(1)首先未决信号集对应的信号位会置1,

(2)去判断阻塞信号集对应的信号位是否为1,若为1则阻塞,若为0则信号递达,并执行handle

(3)当执行完之后,未决信号集对应的信号位被翻转成0

4、未决和阻塞标志都可以用相同的数据类型sigset_t来存储,sigset_t称为信号集,这个类型可表示每个信号的“有效”或“无效”状态。阻塞信号集中“有效”和“无效”分别表示该信号是否被阻塞;未决信号集中“有效”和“无效”的含义是该信号是否处于未决状态。

5、阻塞信号集也叫当前进程的信号屏蔽字(Signal mask),这里的屏蔽应该理解为阻塞而不是忽略。

信号集处理函数 

sigaction函数

四、C标准库提供的信号处理函数

signal函数和system函数

typedef void (*sighandler_t)(int)

sighandler_t signal(int signum, sighandler_t handler)

程序:

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


void do_sig(int n)
{
       printf("hello.\n");
}

int main(void)
{
       signal(SIGINT,do_sig);
      
       while(1){
              printf("*******************\n");
              sleep(1);
       }

       return 0;
}

执行结果如下:

按下Ctrl+C 发送SIGINT信号,执行do_sig函数,打印hello

猜你喜欢

转载自blog.csdn.net/weixin_42445727/article/details/89054965