linux信号详解,基于 linux的 信号详解

本文详细解析了Linux中的信号系统,包括信号命名、来源(终端按键、硬件故障、进程间通信及软件条件)、处理方式(忽略、捕捉和默认行为)、常见信号含义、信号处理函数(如signal和kill)以及信号集操作。特别关注了信号的异步特性、内核响应和信号传递机制,以及pause函数的作用。

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

1、信号:

每个信号都一个一个名字,都已SIG开头;不存在编号为0的信号;

2、产生信号的条件:

a、用户使用了终端按键;

b、硬件异常(如除0,无效的内存引用);

c、进程调用kill(2)函数,将信号发送给另一个进程;(注意,另一进程必须和发送进程的的所有者必须相同,或者发送信号的所有者必须是超级用户);

d、当检查到某种软件条件已经发生时,将其通知相关进程时,也产生信号;

3、信号是异步事件的经典;信号的产生是随机的,进程不能通过测试一个变量来测试是否出现了信号,而是必须告诉内核,在该信号出现时,请执行下列操作;

4、内核对出现的信号可有三种动作可选:

a、忽略此信号(注意:SIGKILL 信号 和 SIGSTOP信号,不可被忽略);

b、捕捉信号;简单来说,就是抓到该信号后,执行进程提供给内核的处理函数;注意,SIGKILL和SIGSTOP不可被捕获;

c、执行默认动作;每种信号都有默认动作,大多数信号的默认动作是终止进程;

5、常见信号解释:

a、SIGCHLD     在一个进程终止时,将SIGCHLD信号发送给其父进程;

b、SIGFPE        算数异常;

c、SIGPIPE       写管道,但是管道的读端已经终止,会产生此信号;

d、SIGPWR      不间断电源(UPS)失效;

e、SIGSEGV     无效的内存引用;

f、 SIGSTOP     终止进程;

g、SIGSYS       无效的系统调用;

h、SIGTERM     由kill(1)命令发送的终止信号;

i、 SIGXFSZ      进程超过了其软文件长度的限制;

6、信号处理函数:

Sigfunc *signal(int,  Sigfunc*);

参数1:信号宏;

参数2:处理函数;

特殊情况:有几个默认的函数宏,用户默认,忽略,错误处理;

#define SIG_ERR   (void (*)()) -1;

#define SIG_DFL   (void (*)()) 0;

#define SIG_IGN   (void (*)()) 1;

返回值:函数指针;

7、kill(1)  命令和kill(2)函数只是将一个信号送给一个进程或者进程组,信号是否终止,取决于信号的类型,以及进程是否安排了捕捉该信号;

8、当一个进程用fork时,其子进程继承父进程的信号处理方式;

9、  pause函数;

#include

int pause(void);

该函数,是本进程挂起,指导捕捉到一个信号;只有执行了信号处理函数,并从其中返回时,pause才会返回;在这种情况下,返回是-1;并将error设置为EINTR;

pause函数,使自己休眠,直到捕捉到一个信号;

10、当捕捉到某个信号是,被中断的是内核中执行的系统调用;

12、不可重入函数的原因:

a、该函数使用了静态数据结构;

b、调用了malloc或者free;

c、使用了表中I/O函数,因为表中I/O函数,很多实现都使用了全局的数据结构;

13、在信号产生和信号递达的间隔内,信号处于未决状态;

14、每个信号都有一个信号屏蔽字,该信号屏蔽字规定了要阻塞送到该进程的的信号集。当某个信号递送时即将到达时,发现对应位被设置,则他当前是被阻塞的;

15、kill函数:

#include

int kill(pid_t pid, int signo);

作用:将信号发送给某个进程或者进程组;

参数1: pid > 0,表示将该信号发送给ID 为pid的进程;

pid == 0 ; 将进程发送给本组所有进程;

pid < 0 ,将信号发送给进程组ID 等于 pid绝对值的组;

pid == -1; 表示该进程把信号发送给 “所有自己有权发送给”的那些进程;

16、将编号为0 的信号定义为空信号,使用kill时,signo为0 ,可以进行错误检查,但是不发任何信号,这常被用来测试一个进程是否存在,如果不存在,则返回-1;并将error置为ESRCH;

17、raise函数;

int raise(int signo)函数,用于向进程自身发送信号;

18、alarm函数:

#include

unsigned int alarm(unsigned int seconds);

使用该函数,设定一个定时器,定时器过期时,会产生SIGALRM信号,该信号的默认动作是终止进程;

每个进程同时只能有一个alarm,否则,新使用的alarm会替代旧的alarm,新alarm 会将旧alarm所剩余的时间返回;

将seconds可以取消以前的闹钟,返回余留值;

注意:如果要使用alarm函数,且在在捕捉到SIGALRM信号后,要做相应的处理,则应该在调用alarm函数之前,设置该信号的处理函数;

19、信号集:

信号集:告诉内核不允许发生该信号集中的信号;

五个基本的信号集操作函数:

#include

int sigemptyset(sigset_t *set);

信号集置空;

int sigfillset(sigset_t *set);

信号集置满;

int sigaddset(sigset_t *set, int signo);

增加信号;

int sigdelset(sigset_t *set, int signo);

删除信号;

int sigismember(const sigset_t *set, int signo);

判断signo是否是信号集成员;

20、sigprocmask函数

#include

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

成功则返回0,出错返回-1;

当oset 为非空指针时,进程的当前信号屏蔽字通过oset返回;

当set不是空指针时,how用来说明修改当前信号屏蔽字的方式,修改方式包括:SIG_BLOCK(set 和 oset的并集);SIG_UNBLOCK(oset与 “set 信号集的补集“的交集)

SIG_SETMASK(指定用set替代旧的信号集);

21、 sigpending 函数:

用于返回被阻塞而不能递送的信号集;

22、sigaction函数;

功能是检查或者修改与指定信号的相关联的处理动作;与signal作用类似;

#include

int sigaction(int signo, const struct sigaction *restrict act, struct sigaction *restrict oact);

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

signo : 表示要检查或者修改具体动作相关联的某个信号;

struct sigaction 结构体:

struct sigaction{

void  (*sa_handler)(int) ;            //与信号相关的处理函数或者SIG_IGN,SIG_DEF;

sigset_t sa_mask;                      //信号集;在调用该函数之前,首先应该用此设置信号集;

int sa_flags;                               //包含对信号处理的各个选项;

void  (*sa_sigaction)(int, siginfo_t *, void *);   当在flag中使用了SA_SIGINFO标志时,使用此处理程序;(注意,此函数指针和第一个处理信号的函数指针,两者只能使用其中之一;)zaisiginfo_t结构体中包含了信号产生原因的相关信息;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值