linux下信号介绍及如何安装信号

1, 信号介绍

介绍信号前先复习一下中断,中断的意思就是比如你在写作业,忽然有人打电话过来了,你就得去接电话,这里电话铃声就是一种信号,你去接电话的动作就是中断处理程序。

信号是软件中断,它提供了一种处理异步事件的方法。每个信号都有一个名字,这些名字都是以SIG开头。 使用命令kill -l 可以查看当前系统支持的信号。
信号列举
信号值位于SIGRTMINSIGRTMAX之间的信号都是可靠信号,可靠信号克服了信号可能丢失的问题。

  • 下面是常用的信号
信号编号信号名信号说明默认动作
2SIGINTCtrl+C按键终止程序运行的信号程序终止
4SIGILL非法的指令程序终止
7SIGBUS运行非本CPU相关编译器编译的程序程序终止
9SIGKILL强制杀死程序信号,任何程序都不可以捕捉该信号程序终止,不可被捕捉
10SIGUSR1用户自定义信号1程序终止
11SIGSEGV段错误系统给程序发送的信号程序终止
12SIGUSR2用户自定义信号2程序终止
13SIGPIPE管道破裂信号程序终止
14SIGALRMalarm()系统调用发送的信号程序终止
15SIGTERMkill命令默认发送的信号,默认动作是终止信号程序终止
17SIGCHLD子进程退出信号忽略该信号

编号为0的信号有特殊用途,我们可以给某个进程发0号信号来判断该进程是否正在运行。在某个信号发生时,可以告诉内核按照下面三种方式进行处理:
1, 忽略此信号 //还是上面的例子,当听到手机铃声响起的时候,你可以选择忽略这个声音,假装没听见继续写作业
2,捕捉此信号 //当然你也可以选择接听这个电话1
3,执行系统默认动作。//比如你妈妈在早上出门前就跟你说下午打电话给你就代表她回家了,你不用接电话,而是去开门就行


kill 命令默认发 SIGTERM信号,如果SIGTERM被捕捉后,那么kill命令就不能停止该进程运行,
这时需要使用kill -9(SIGKILL)可以强制杀死某个进程。
在这里插入图片描述

  • 上面例子中我们创建了ping进程,首先我们按 ctrl+z,这是给进程发送了挂起的信号,我们发现当我们ps后,这个信号是杀不死这个进程的。
  • 后面我们kill 3219, 这其实只是发送了信号编号为15的默认信号 SIGTERM, 我么发现同样杀不死ping这个进程
  • 最后我们加了9号信号SIGKILL,因为这个信号是不可被捕捉的,最后成功杀死这个进程。

另外我们看看下面的例子进一步了解信号的概念
在这里插入图片描述

  • 上面我们按了 CTRL+c,ps 后发现ping命令被成功杀死,这里其实给进程发送了编号为2的SIGINT信号

2, 安装信号

信号是进程间通信机制中唯一的异步通信机制
signal()和sigaction()为信号安装函数
这两个函数的最大区别在于,经过sigaction安装的信号都能传递信息给信号处理函数,而经过signal安装的信号不能向信号处理函数传递信息。
简单说就是sigaction()比 signal()更加安全,信号不会丢失。所以我们一般使用sigaction(),而且它的功能更多。

  • 下面是两个函数的原型
    signal()
#include <signal.h>
typedef void (*sighandler_t)(int); 
sighandler_t    signal(int signum, sighandler_t handler); 
 //第一个参数是信号的编号,第二个是收到信后后需要执行的函数名称

下面是signal()函数的简单例子

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

void    sig_handl(int signum)
{
        printf("catch siganl [%d]\n",signum);  //打印收到信号的编号
}



int main(int argc, char *argv[])
{
        signal(SIGINT, sig_handl);  //这里表示给程序安装了2号信号,即当按(ctrl+c)时程序就会去执行sig_handl函数里的内容
        while (1)
        {
         ;
        }
         return 0;
}

在这里插入图片描述

  • 因为程序安装了信号SIG_INT后执行sig_handl()函数,所以当我们按下ctrl +c 后并不能像之前杀死ping进程那样杀死进程了。

sigaction()

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

参数:
 signum:信号值
 act:信号的处理参数
 oldact:保存信号上次安装时的处理参数(备份的作用)
返回值:0(success),-1(error)

  • 下面是结构体
struct sigaction {
         void     (*sa_handler)(int); //信号处理函数
         void     (*sa_sigaction)(int, siginfo_t *, void *);
         sigset_t   sa_mask; //信号屏蔽集
         int        sa_flags; 
         void     (*sa_restorer)(void);// 已废弃
};
  • 下面给出和上面signal()相同功能的等价程序
void    sig_handl(int signum)
{
        printf("catch siganl [%d]\n",signum);
}



int main(int argc, char *argv[])
{
        struct      sigaction    sigact; //定义结构体

//下面三条语句初始化结构体
        sigemptyset(&sigact.sa_mask);
        sigact.sa_flags = 0;
        sigact.sa_handler = sig_handl;


        sigaction(SIGINT, &sigact, 0); //安装信号

        while (1)
        {
         ;
        }
         return 0;
}


  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值