网站做常规优化,公司的企业邮箱怎么查询,小白如何免费做网站,wordpress怎么访问数据库信号#xff1a;在生活中#xff0c;我们遇到过不同种类的信号#xff0c;比如#xff1a;#xff08;交通信号#xff0c;乃至某个人的表情#xff0c;动作等带给你不同的信号#xff09;然而#xff0c;在我们的linux下#xff0c;我们最熟悉的就是#xff0c;当遇…信号在生活中我们遇到过不同种类的信号比如交通信号乃至某个人的表情动作等带给你不同的信号然而在我们的linux下我们最熟悉的就是当遇到一个死循环的程序时我们第一想到的就是按ctrlc此时这个进程立马终止这是一种通过键盘产生的信号。而说起ctrlc就引出了前台进程和后台进程。当ctrlc产生的信号只能发给前台进程。
用kill -l命令就可以查看信号了 产生信号的另一种方式是信号异常触发系统使该进程终止
例子 运行结果 还有一种方式通过指令来使该进程终止 然后直接运行./test: 还有一种方式通过alarm使进程终止
说起alarm给大家举个例子吧alarm意思是闹钟在这里也同样代表着当你执行某个进程时突然用alarm定时的时间到了这时闹钟发挥了作用使得你的进程被迫停止比如 这是一个统计1秒钟计数的程序当一秒钟到时就会被SIGALRM信号终止。
运行结果 下面我们来说一下处理信号的几种方式吧
忽略信号执行默认执行自定义信号的捕捉三种方式。那么问题来了什么时候处理呢答案是适当的时候处理 执行信号的处理动作称为信号递达信号从产生到递达之间的状态称为信号未决。进程可以选择阻塞某个信号被阻塞的信号产生时将保持在未决状态直到进程解除对此信号的阻塞才执行递达的动作。
阻塞和忽略是不同只要信号被阻塞就不会递达而忽略则是在递达之后可选的一种处理动作。
信号在内核中是这样表示的 block:代表屏蔽状态字1表示阻塞0表示不阻塞
pending代表未决1表示未决0表示可以递达
handler代表信号的处理方式默认忽略自定义
每个信号都有两个标志位分别表示阻塞(block)和未决(pending),还有一个函数指针表示处理动作。信号产生时,内核在进程控制块中设置该信号的未决标志,直到信号递达才清除该标志。
上面那张表说明SIGHUP是没有阻塞也没有产生所以处理动作为默认处理动作
SIGINT的block为1pending也为1表示正在阻塞无法递达。它的处理动作为忽略但是在没有解除阻塞之前不能忽略该信号很可能在解除阻塞前改变为其他的处理动作。
对于上述的三张表操作系统中的每个进程运行时都会存在。
SIGQUIT的block为1pending为0说明正在被阻塞解除阻塞后就可以递达。处理动作为用户自定义的处理动作。
还有一种现象是对于解除阻塞之前可能会发送多次信号这时操作系统该作何处理呢。这里主要是分为普通信号和实时信号普通信号出现发送多次的情况会当做是一次信号进行处理。而实时信号发送多次的情况会将这多个信号存在一个队列中分别处理各个信号。我们一般讨论的是普通信号因此只记录一次我们将未决和阻塞状态用同一个数据类型来存储sigset_t信号集为sigset_t。还需要注意的一点是阻塞信号集也叫做当前进程的信号屏蔽字。
说了信号集我们之前说过这些普通信号是以位图的形式存放的。每一个bit位表示一种信号是否存在。
对于信号的操作我们有一组信号集操作函数如下 函数sigemptyset初始化set所指向的信号集,使其中所有信号的对应bit清零,表示该信号集不包含任何有效信号。
函数sigfillset初始化set所指向的信号集,使其中所有信号的对应bit置位,表⽰示 该信号集的有效信号包括系统支
持的所有信号。
在使⽤用sigset_t类型的变量之前,⼀一定要调 ⽤用sigemptyset或sigfillset做初始化,使信号集处于确定的状态。
做完初始化之后调用sigaddset和sigdelset来添加或者删除信号。
这四个函数成功返回0失败返回-1
sigismember用来表示某种信号是否出现在有效信号集中。出现返回1不出现返回0.
*还有函数sigprocmask读取或更改进程的信号屏蔽字
#include signal.h int sigprocmask(int how, const sigset_t *set, sigset_t *oset);
成功返回0出错返回-1
这里的oset为输出型参数如果oset为非空则输出当前进程的信号屏蔽字通过oset输出。如果set为非空则更改信号屏蔽字how指示如何更改。如果set和oset都为非空则将当前进程的信号屏蔽字备份在oset中然后再通过how参数更改信号屏蔽字。
how主要有三种表示SIG_BLOCK(包含了我们希望添加的信号屏蔽字),SIG_UNBLOCK(包含了我们希望从信号屏蔽字中阻塞的信号),SIG_SETMASK(设置了当前的信号屏蔽字的值);
*函数sigpending:读取当前进程的未决信号集
#include signal.h int sigpending(sigset_t *set);
set为输出型参数将信号通过set输出 小栗子 #includestdio.h
#includesignal.hvoid PrintSigset(sigset_t *sig)
{int i 0;for(i 1; i 32; i){if(sigismember(sig,i)){printf(1 );}else{printf(0 );}}printf(\n);
}int main()
{sigset_t sigset,osigset;sigemptyset(sigset);sigemptyset(osigset);sigaddset(sigset,SIGINT);sigprocmask(SIG_BLOCK,sigset,osigset);while(1){sigpending(sigset);PrintSigset(sigset);sleep(1);}return 0;
}
这个程序实现了将2号信号设置为阻塞信号。所以一直无法递达。程序运行时,每秒钟把各信号的未决状态打印一遍,由于我们阻塞了SIGINT信号,按Ctrl-C将会使SIGINT信号处于未决
状态,按Ctrl-\和ctrlz仍然可以终止程序,因为SIGQUIT信号没有阻塞。
运行结果 还有一个小栗子我们将2号信号阻塞之后5秒后解除阻塞。并打印原来信号的状态。 #includestdio.h
#includesignal.hvoid PrintSigset(sigset_t *sig)
{int i 0;for(i 1; i 32; i){if(sigismember(sig,i)){printf(1 );}else{printf(0 );}}printf(\n);
}void handler(int sig)
{printf(pid: %d sig:%d \n,getpid(),sig);
}
int main()
{sigset_t sigset,osigset;sigemptyset(sigset);sigemptyset(osigset);sigaddset(sigset,SIGINT);sigprocmask(SIG_BLOCK,sigset,osigset);int count 0;signal(2,handler);//signal(2,SIG_DFL);while(1){sigpending(sigset);PrintSigset(sigset);sleep(1);if(count 5){sigprocmask(SIG_SETMASK,osigset,NULL);count 0;}}return 0;
}运行结果