linux-进程通信(4)信号

本文详细介绍了Linux信号机制,包括信号的概述、处理方式、常用API如signal和sigaction,以及如何捕获和发送信号。通过示例代码展示了如何注册信号处理函数、忽略信号以及通过kill命令发送信号。信号不仅是进程间通信的一种方式,还能用于处理异步事件,如中断程序。文中还提到了sigqueue函数,用于在信号中携带额外信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

信号

对于 Linux来说,实际信号是软中断,许多重要的程序都需要处理信号。信号,为 Linux 提供了一种处理异步事件的方法。比如,终端用户输入了 ctrl+c 来中断程序,会通过信号机制停止一个程序。

信号的概述
每个信号都有一个名字和编号,这些名字都以“SIG”开头,例如“SIGIINT”、“SIGUP”等等。
信号定义在signal.h头文件中,信号名都定义为正整数。
具体的信号名称可以 使用kill -l来查看信号 的名字以及序号,
信号是 从1开始编号的,不存在0号信号。kill对于信号0有特殊的应用。
在这里插入图片描述
信号的处理:

忽略信号:大多数信号可以使用这个方式来处理,但是有两种信号不能被忽略(分别是 SIGKILL和SIGSTOP)。因为他们向内核和超级用户提供了进程终止和停止的可靠方法,如果忽略了,那么这个进程就变成了没人能管理的的进程。
捕捉信号:需要告诉内核,用户希望如何处理某一种信号,说白了就是写一个信号处理函数,然后将这个函数告诉内核。当该信号产生时,由内核来调用用户自定义的函数,以此来实现某种信号的处理。
系统默认动作:对于每个信号来说,系统都对应由默认的处理动作,当发生了该信号,系统会自动执行。

其实对于常用的 kill 命令就是一个发送信号的工具,kill -9 PID来杀死进程。比如,我在后台运行了一个 top 工具,通过 ps命令可以查看他的 PID,通过 kill 9 来发送了一个终止进程的信号来结束了 top 进程。如果查看信号编号和名称,可以发现9对应的是“9-SIGKILL”,正是杀死该进程的信号。而以下的执行过程实际也就是执行了9号信号的默认动作——杀死进程。

kill -9 进程PID
kill -SIGKILL 进程PID

对于信号来说,最大的意义不是为了杀死信号,而是实现一些异步通讯的手段。

常用API

信号处理函数的注册
入门版:函数signal
高级版:函数sigaction

信号处理发送函数
1.入门版:kill
2.高级版:sigqueue
对于入门版的信号处理API的重点在于动作,但kill 函数发送的信号是无法携带数据
对于高级版的信号处理API的重点是信号携带的信息

signal

函数原型:

#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);

函数原型由两部分组成,一个是真实处理信号的函数,另一个是注册函数

注册函数:

sighandler_t signal(int signum, sighandler_t handler);

参数
signum :指出要设置处理方法的信号
handler :第二个参数handler是一个处理函数(一个函数地址),或者是

SIG_IGN:忽略参数signum所指的信号。

SIG_DFL:恢复参数signum所指信号的处理方法为默认值。

handler函数:
真实处理信号的函数:

typedef void (*sighandler_t)(int);

传中断函数的原型中,有一个参数是 int 类型,显然也是信号产生的类型,方便使用一个函数来处理多个信号。

捕捉信号 示例

键盘上敲ctrl c 的时候,会发出SIGINT的信号,被代码中的signal(SIGINT,handler)捕获了,这时候会进入handler进行函数处理,因为SIGINT对应的整数是2,会把2传到handler函数里面的signum参数里,进而在handler函数里面进行处理。

signalDemo1.c 捕获信息(使用kill里面的指令发送信号,供程序捕获信号)


//真实处理信号的函数
void handler(int signum)
{
   
        printf("get signum=%d\n",signum);
        switch(signum){
   
                case 2:
                        printf("SIGINT\n");
                        break;
                case 10:
                        printf("SIGUSR1\n");
                        break;
        }
}
int main()
{
   
        signal(SIGINT,handler);//信号处理函数的注册
        signal(SIGUSR1,handler);//信号处理函数的注册
        while(1);
        return 0;
}

在这里插入图片描述

对于已注册的信号,使用 kill 发送都可以正常接收到,但是如果发送了未注册的信号,则会使得应用程序终止进程(结束程序 ,大部分信号默认都是使进程终止)
在这里插入图片描述

signalDemo1Ctrl.c (用程序来执行kill命令)
主要是将kill信号处理发送函数置于程序中,同时也可以使用system来实现kill
kill补充
函数原型

int kill(pid_t pid, int sig);

参数
pid: 指定的进程pid
sig:信号的编号
返回值:
成功返回0 ,出错返回-1


int main(int argc,char *argv[])
{
   
        int signum=0;
        int pid=0;
        signum= atoi(argv[1]);//转为整型
        pid= atoi(argv[2]);//转为整型
        printf<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值