Linux提供了信号传递进程消息的机制,什么是信号?它是一种非常短的消息,短到只有一个数字。值得强调的是信号和信号量只少了一个字,但他们完全是不同的概念,信号量仅用于同步代码段,而信号则用于传递消息。
一 、信号的编号:通过kill -l 命令可以看到
二、信号机制 可以通过man 7 signal
三、几种默认处理信号的方式:
Term表示终止当前进程.
Core表示终止当前进程并且Core Dump 生成core文件用于调试(Core Dump 用于gdb调试).
Ign表示忽略该信号.
Stop表示停止当前进程.
Cont表示继续执行先前停止的进程.
值得强调是SIGKILL和SIGSTOP两个信号是不能被捕获的、阻塞(屏蔽),忽略。
四、信号产生种类
终端特殊按键: ctl+c SIGINT ctl+z SIGTSTP ctl+\ SIGQUIT
硬件异常:除 0操作 访问非法内存
kill函数或kill命令
五、进程处理信号行为
1.默认处理(上面五种情况)
2.忽略处理
3.捕获处理(用户自定义信号处理函数),类似于中断。
六、信号在内核中的表示示意图
七、信号集处理函数
#include <signal.h>
int sigemptyset(sigset_t *set);//清空设置,把全部置1
int sigfillset(sigset_t *set);//全部置1
int sigaddset(sigset_t *set, int signum);//把信号集的某一个信号置1
int sigdelset(sigset_t *set, int signum);//把信号集的某一个信号置0
int sigismember(const sigset_t *set, int signum);//判断信号集的某一个信号是否被置1
调用函数sigprocmask可以读取或更改进程的信号屏蔽字,用于注册信号集。
#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
how 参数
SIG_BLOCK 设置数包含了我们希望添加到当前信号屏蔽字的信号,相当于mask=mask|set *(这里mask是原有的信号集)
SIG_UNBLOCK 设置包含了我们希望从当前信号屏蔽字中解除阻塞的信号,相当于mask=mask&~set (这里mask是原有的信号集)
SIG_SETMASK 设置当前信号屏蔽字为set所指向的值,相当于mask=set (这里mask是原有的信号集)
set 参数是要设置信号集,oldset是原有的信号集(可以为空)传出参数.
如果调用sigprocmask解除了对当前若干个未决信号的阻塞,则在sigprocmask返回前,至少将其中一个信号递达。
#include <signal.h>
int sigpending(sigset_t *set);//sigpending读取当前进程的未决信号集,通过set参数传出
八、简单测试程序:
#include <stdio.h>
#include<signal.h>
#include<errno.h>
void printset(const sigset_t *set)
{
int i=1;
for(i=1;i<32;i++)
{
if(sigismember(set,i)==1)
{
putchar('1');
}
else
{
putchar('0');
}
}
printf("\n");
}
int main(int argc, char *argv[])
{
sigset_t set,pset;
sigemptyset(&set);//置为0
sigaddset(&set,SIGINT);//将SIGINT置为1
if(sigprocmask(SIG_BLOCK,&set,NULL)==-1)//改进程的信号屏蔽字
{
perror("sigprocmask");
return 0;
}
while(1)
{
if(sigpending(&pset)==-1) //获取未决信号集
{
perror("sigpending");
return 0;
}
printset(&pset);//打印未决信号集
sleep(1);
}
return 0;
}
按下ctrl+c 程序无法结束,可以看到未决信号集SIGINT为1