LINUX 信号

[复制链接]
发表于 2025-11-15 10:34:16 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
信号是什么

信号是一种用于在软件层面关照进程发生了某个事故的机制。这些事故可以是来自其他进程的关照、非常环境、用户的交互等。当体系检测到某个事故时,会向相应的进程发送一个信号。进程可以事先界说信号的处理惩罚方式,比如忽略、捕获、或实行默认操纵。
因此综合起来,将信号称为软制止是由于它雷同于硬制止的概念,但它是在软件层面实现的。信号提供了一种轻量级的通讯和事故处理惩罚机制,答应进程在运行时相应各种事故,而不必要像硬制止那样涉及到硬件层面的处理惩罚。
干系函数

kill

  1. int kill(pid_t pid,int sig);
复制代码
作用:向指定进程发送信号
raise

  1. int raise(int sig);
复制代码
作用:向自身进程发送信号
signal

  1. typedef void (*sighandler_t)(int);//中断函数类型
  2. sighandler_t signal(int signum,sighandler_t handler);
复制代码
作用:
为指定信号指定一个处理惩罚函数
sigaction

  1. int sigaction(int signum,const struct sigaction *act,struct sigaction *oldact);
复制代码
作用:
为指定信号注册制止函数,通过struct sigaction 布局体赋值,通过生存oldact生存旧的制止服务函数。
该函数的第一个参数为信号的值,可以为除SIGKILL及SIGSTOP外的任何一个特定有用的信号(为这两个信号界说本身的处理惩罚函数,将导致信号安装错误)。第二个参数是指向布局sigaction的一个实例的指针,在布局sigaction的实例中,指定了对特定信号的处理惩罚,可以为空,进程会以缺省方式对信号处理惩罚;第三个参数oldact指向的对象用来生存原来对相应信号的处理惩罚,可指定oldact为NULL。假如把第二、第三个参数都设为NULL,那么该函数可用于查抄信号的有用性。
sigaction和signal

ignal比sigaction简朴,但signal注册的信号在sa_handler被调用之前把会把信号的sa_handler指针规复,而sigaction注册的信号在处理惩罚信号时不会规复sa_handler指针。以是用signal函数注册的信号处理惩罚函数只会被调用一次,之后收到这个信号将按默认方式处理惩罚,假如想不停处理惩罚这个信号的话就得在信号处理惩罚函数中再次用signal注册一次。sigaction注册的函数多次调用不会规复初始值。这两个函数可以为除SIGKILL和SIGSTOP外的任何一个特定有用的信号。
sigqueue

  1. int sigqueue(pid_t pid, int signo, const union sigval value);
复制代码
函数作用:新的发送信号体系调用,告急是针对实时信号提出的支持信号带有参数,与函数sigaction共同利用。
第一个参数: 指定吸取信号的进程id
第二个参数:确定即将发送的信号
第三个参数:是一个团结布局体union sigval,指定了信号转达的参数,即通常所说的4字节值
alarm

  1. unsigned int alarm(unsigned int section);
复制代码
作用:
定时,指定时间之后向进程发送SIGALRM信号
指定时间为0,取消前一个定时。
只能利用一次,下一次利用必要再次设置
ualarm

设置定时器,相比于alarm,ualarm可以循环利用。
pause

  1. int pause(void);
复制代码
挂起进程,直到吸取到一个信号好,并处理惩罚完信号后才返回。
strsignal 和 psignal

将信号量转化为字符形貌。
信号集


壅闭信号集也叫做当进步程的信号屏蔽字(Signal Mask),这里的“屏蔽”应该明白为壅闭而不是忽略。内核为每个进程都维护了一个信号掩码(信号集)
信号在内核中的表现:递达(Delivery)、未决(Pending)、壅闭(Block)
递达(Delivery):实行信号的动作
未决(Pending):被壅闭的信号处在的状态,信号从产生到递达之间的状态
壅闭(Block):可以明白为屏蔽信号,一个信号可以若被壅闭,它将保持在未决状态,直到进程扫除对此信号的壅闭,才实行递达的动作。
注意,壅闭和忽略是差别的,只要信号被壅闭就不会递达,而忽略是在递达之后可选的一种处理惩罚动作。信号在内核中的表现可以看作是如许的:

   图中:
block集(壅闭集、屏蔽集):一个进程所要屏蔽的信号,在对应要屏蔽的信号位置1
pending集(未决信号集):假如某个信号在进程的壅闭集之中,则也在未决会合对应位置1,表现该信号不能被递达,不会被处理惩罚
handler(信号处理惩罚函数集):表现每个信号所对应的信号处理惩罚函数,当信号不在未决会适时,将被调用
每个信号都有两个标记位分别表现壅闭和未决,尚有一个函数指针表现处理惩罚动作。信号产生时,内核在进程控制块中设置该信号的未决标记,直到信号递达才扫除该标记。在上图的例子中,
SIGHUP信号未壅闭也未产生过,当它递达时实行默认处理惩罚动作。
SIGINT信号产生过,但正在被壅闭,以是暂时不能递达。固然它的处理惩罚动作是忽略,但在没有扫除壅闭之前不能忽略这个信号,由于进程仍有机遇改变处理惩罚动作之后再扫除壅闭。
SIGQUIT信号未产生过,一旦产生SIGQUIT信号将被壅闭,它的处理惩罚动作是用户自界说函数sighandler。
  原文链接:https://blog.csdn.net/z5z5z5z56/article/details/107597308
  1. #include <signal.h>
  2. int sigemptyset(sigset_t *set);/* Clear all signals from SET.  清空信号集*/
  3.   int sigfillset(sigset_t *set);// 把所有信号的对应bit置位=把64种信号都放入信号集(没有32 33)   /* Set all signals in SET. */
  4.   int sigaddset(sigset_t *set, int signo);// 增加某个指定信号
  5.   int sigdelset(sigset_t *set, int signo);//删除某个指定信号
  6.   int sigismember(const sigset_t *set, int signo);// 查看信号是否在集合里面 /* Return 1 if SIGNO is in SET, 0 if not. */
复制代码
注意,在利用sigset_t范例的变量之前,肯定要调用sigemptyset或sigfillset做初始化,使信号集处于确定的状态。初始化sigset_t变量之后就可以在调用sigaddset和sigdelset在该信号会合添加或删除某种有用信号。上面四个函数都是乐成返回0,堕落返回-1。sigismember是一个布尔函数,用于判断一个信号集的有用信号中是否包罗某种信号,若包罗则返回1,不包罗则返回0,堕落返回-1。
sigprocmask

  1. int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
复制代码
假如oldset好坏空指针,则读取进程的当前信号屏蔽字通过oldset参数传出。假如set好坏空指针,则更改进程的信号屏蔽字,参数how指示怎样更改。假如oldset和set都好坏空指针,则先将原来的信号屏蔽字备份到oldset里,然后根据set和how参数更改信号屏蔽字。假设当前的信号屏蔽字为mask,下表阐明确how参数的可选值。

sigpending

  1. int sigpending(sigset_t *set);
复制代码
查察全部未决信号集的值==>那些信号被壅闭。
sigsuspend

  1. int sigsuspend(const sigset_t * mask);
复制代码
作用:利用mask值更换信号掩码,并挂起进程(原子操纵);
实时信号的处理惩罚

信号编号小于即是31的好坏实时信号,这种信号不可靠,当多个同类信号到达时大概会发生信号的覆盖。
信号编号大于即是34的是实时信号,这种信号可靠,当多个同类信号到达时不会发生信号的覆盖,利用队列存储。
在处理惩罚传统信号时,操纵体系默认环境下只保存一个挂起的信号。假如在处理惩罚信号时,雷同范例的信号再次到达进程,且之前的信号尚未处理惩罚完毕,则后续到达的信号会被抛弃。
实时信号利用了队列的机制,纵然在处理惩罚实时信号时,多个雷同范例的信号会被列队等候处理惩罚。
实时信号有一个优先级的概念,具有更高优先级的实时信号会在低优先级实时信号之前得到处理惩罚。
sigaction和sigqueue处理惩罚实时函数

sigqueue在发送信号时可以通过一个团结体携带一些数据,这个数据可以被sigaction指定的制止函数的第二个参数吸取,但利用的条件是sigaction绑定时要通过布局体参数struct sigaction指定SA_SIGINFO。

sa_handler的原型是一个参数为int,返回范例为void的函数指针。参数即为信号值,以是信号不能转达除信号值之外的任何信息;
sa_sigaction的原型是一个带三个参数,范例分别为int,struct siginfo *,void *,返回范例为void的函数指针。第一个参数为信号值;第二个参数是一个指向struct siginfo布局的指针,此布局中包罗信号携带的数据值;第三个参数没有利用。
sa_mask指定在信号处理惩罚步调实行过程中,哪些信号应当被壅闭。默认当前信号本身被壅闭。
sa_flags包罗了很多标记位,比力告急的一个是SA_SIGINFO,当设定了该标记位时,表现信号附带的参数可以转到达信号处理惩罚函数中。纵然sa_sigaction指定信号处理惩罚函数,假如不设置SA_SIGINFO,信号处理惩罚函数同样不能得到信号转达过来的数据,在信号处理惩罚函数中对这些信息的访问都将导致段错误。
sa_restorer已过期,POSIX不支持它,不应再利用。
因此,当你的信号必要吸取附加信息的时间,你必须给sa_sigaction赋信号处理惩罚函数指针,同时还要给sa_flags赋SA_SIGINFO,雷同下面的代码:
  1.      #include <signal.h>
  2.      ……
  3.      void sig_handler_with_arg(int sig,siginfo_t *sig_info,void *unused){……}
  4.    
  5.      int main(int argc,char **argv)
  6.      {
  7.               struct sigaction sig_act;
  8.               ……
  9.               sigemptyset(&sig_act.sa_mask);
  10.               sig_act.sa_sigaction=sig_handler_with_arg;
  11.               sig_act.sa_flags=SA_SIGINFO;
  12.   
  13.                ……
  14.      }
复制代码
假如你的应用步调只必要吸取信号,而不必要吸取额外信息,那你必要的设置的是sa_handler,而不是sa_sigaction,你的步调大概雷同下面的代码:
  1.      #include <signal.h>
  2.      ……
  3.      void sig_handler(int sig){……}
  4.    
  5.      int main(int argc,char **argv)
  6.      {
  7.               struct sigaction sig_act;
  8.               ……
  9.               sigemptyset(&sig_act.sa_mask);
  10.               sig_act.sa_handler=sig_handler;
  11.               sig_act.sa_flags=0;
  12.                ……
  13.       }
复制代码
为什么没有信号32和33

posix尺度未界说这两个信号
kill 和 sigqueue

1、kill 和 sigqueue 指定的sig为0可以判断pid指向的进程是否存在。
2、kill发送信号,但是不能带参数
3、aigqueue发送信号可以通过团结体带参数到制止处理惩罚函数。
pause sigsuspend sleep的区别

1)pause()会令如今的进程停息(进入就寝状态),直至信号(signal)出现,处理惩罚完制止后返回。而且返回值是导致它返回的谁人信号的编号。
2)sigsuspend函数和pause函数一样,可以是进程挂起(进入就寝状态),直至有信号发生。但是sigsuspend函数的参数是一个信号集,这个信号集是用来屏蔽信号的,信号会合存放了要屏蔽的信号。被屏蔽的信号无法唤醒进程。假如该信号集为空的话,sigsuspend就不屏蔽任何信号,任何信号都可以使进程从挂起状态唤醒,这就与pause函数一样了。
3)sleep让进程停息指定时间,指定时间后主动唤醒进程。时间以秒为单元。不必要外部信号。在POSIX体系上,sleep() 函数返回0。但是,假如调用被信号制止,它大概返回剩余必要就寝的时间(只管这种举动依赖于具体的实现)。
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表