信号
信号描述
信号的共性: 简单 不能携带大量数据 满足某一特定条件才发送 信号的特质: 信号软件层面的中断,一旦信号产生,无论程序执行到什么位置,必须立即停止,处理信号,处理结束后,再继续执行后续指令。 所有的信号的产生和处理都是由内核完成。 信号的实现手段导致信号有很强的延时。对用户而言依然感觉不到
信号相关的概念
未决: 产生与递达(处理)之间的状态,该状态主要受阻塞(屏蔽)影响。 递达: 内核产生信号后递送并且成功到达进程。递达的信号会被内核立即处理。 信号处理方式: 执行默认动作。 忽略(丢弃)。 捕捉(调用用户指定的函数)。 阻塞信号集: 本质:位图。用来记录信号的屏蔽状态。 该信号集中的信号,表示成功被设置屏蔽。再次受到该信号,其处理动作将延后至解除屏蔽。此期间该信号一直处于未决态。 未决信号集: 本质:位图。记录信号的处理状态。 该信号集中的信号表示信号已经产生但尚未被处理。
信号四要素
编号 名称 事件 默认处理动作
使用命令kill -l
查看 Linux 系统中支持的所有信号。 SIGKILL 和 19) SIGSTOP信号,不允许忽略和捕捉,只能执行默认动作,不能将其设置为阻塞。
信号产生
按键产生 Ctrl + c -> 2) SIGINT(终止/中断) Ctrl + \ -> 3) SIGQUT(退出) 系统调用产生 软件条件产生 alarm() -> 14) SIGALRM setitimer() -> 14) SIGALRM 硬件异常产生信号 段错误:内存访问异常 -> SIGSEGV 浮点数例外:除零 -> 8) SIGFPE 命令产生
kill 函数、命令产生信号
# include <signal.h> int kill ( pid_t pid, int sig) ;
参:pid:> - 1 :发送信号给指定进程。= 0 :发送信号给跟调用 kill 函数的那个进程,处于统一进程组的进程。< - 1 :取绝对值,发信号给所有该组的组员。- 1 :发送信号给有权限发送的所有进程。sig:信号编号返回值:成功:0 失败:- 1 ,errno
alarm函数产生信号
unsigned int alarm ( unsigned int seconds) ;
seconds:定时的秒数
返回值:上次定时剩余时间。不会出错。
使用 time 命令查看程序执行消耗的时间。 实际时间 = 用户时间 + 内核时间 + 等待时间 time ./alarm > out —— 程序优化的瓶颈在 IO
信号集操作函数
# include <signal.h> sigset_set 自定义信号集int sigemptyset ( sigset_t * set) ;
清空自定义信号集int sigfillset ( sigset_t * set) ;
将信号集全部置1 int sigaddset ( sigset_t * set, int signum) ;
将一个信号添加到信号集int sigdelset ( sigset_t * set, int signum) ;
将一个信号从信号集中清除以上四个函数返回值:
成功:0 失败:- 1 ,errnoint sigismember ( const sigset_t * set, int signum) ;
判断一个信号是否在集合中
在:1
不在:0
操作信号屏蔽字
设置屏蔽信号、接触屏蔽,都使用 sigpromask
int sigprocmask ( int how, const sigset_t * set, sigset_t * oldset) ;
参:how:SIG_BLOCK: 设置阻塞SIG_UNBLOCK:解除屏蔽SIG_SIEMASK:用自定义信号集替换 maskset:自定义 set。oldset:保存修改前的 mask 状态,以便将来恢复。
返回值:成功:0 失败:- 1 ,errno
# include <signal.h> int sigpending ( sigset_t * set) ;
参 set:传出参数。未决信号集。
返回值:成功:0 失败:- 1 ,errno
信号捕捉
signal 函数
# include <signal.h> typedef void ( * sighandler_t) ( int ) ; sighandler_t signal ( int signum, sighandler_t handler) ;
参 1 :待捕捉的信号编号。
参 2 :一旦捕捉到该信号,执行的回调函数
返回值:
sigacton 函数
int sigaction ( int signum, const struct sigaction * act, struct sigaction * oldact) ;
参 1 :待捕捉的信号
参 2 :传入参数,指定新的处理方式
参 3 :传出参数,保存就有的信号处理方式。
返回值:成功 0 失败:- 1 ,errnostruct sigaction { void ( * sa_handler) ( int ) ; 捕捉函数名,复制 SIG_IGN 表示忽略,赋值 SIG_DEF 表示默认动作void ( * sa_sigaction) ( int , siginfo_t * , void * ) ; 信号传参。sigset_t sa_mask; 信号捕捉函数调用期间所要屏蔽的信号int sa_flags; 通常为 0 ,使用默认属性void ( * sa_restorer) ( void ) ;
} ;
信号捕捉特性
捕捉函数执行期间,信号屏蔽字由原来的 mask 改为sa_mask,捕捉函数执行结束,恢复回 mask。 捕捉函数执行期间,本信号自动被屏蔽(sa_flags = 0) 捕捉函数执行期间,被屏蔽的信号执行多次,解除屏蔽后只处理一次
借助信号捕捉,完成子进程回收
SIGCHLD 产生的条件
子进程的运行状态发生变化,就会给父进程发送 SIGCHLD