泉州做网站哪家好,体育西网站开发方案,上海开办企业一窗通,自己做网站卖什么信号的基本属性#xff1a;软中断#xff0c;由内核发送#xff0c;内核处理。某个进程通过内核向另一个进程发送信号时#xff08;引起信号产生的五个因素#xff09;#xff0c;另一个进程将会陷入内核进行中断处理#xff0c;未决信号集中相应信号置1#xff0c;当递…信号的基本属性软中断由内核发送内核处理。某个进程通过内核向另一个进程发送信号时引起信号产生的五个因素另一个进程将会陷入内核进行中断处理未决信号集中相应信号置1当递达后置0。如果阻塞信号集相应信号为1则该信号处于未决状态。处于未决状态中的信号多次发送时只是执行一次因为在未决信号集中只是记录了该信号的状态没有记录发送的次数。信号抵达后内核进行处理。处理方式有三默认处理方式5种忽略丢弃和捕捉。下面说明捕捉机制。
signal和sigaction函数只是完成对一个信号进行注册的功能而对信号的捕捉的处理都是由内核完成的。当对一个信号进行注册后内核对其捕捉同时调用其注册时对应的用户处理函数。
1signal函数
typedef void (*sighandler_t)(int); //定义一个函数类型 sighandler_t
sighandler_t signal(int signum, sighandler_t handler);
作用注册一个信号捕捉函数
返回值成功返回sighandler_t类型的函数或函数首地址失败则返回一个宏SIG_ERR。注意判断该函数的返回值 sighandler ret signal·······if(retSIG_ERR)
第一个参数为信号第二个参数为sighandler_t类型函数即返回值为void形参为int。
注意该函数由ANSI定义由于历史原因在不同版本的Unix和不同版本的Linux中可能有不同的行为。因此应该尽量避免使用它取而代之使用sigaction函数。
#include signal.h
#include stdio.h
#include errno.h
#include stdlib.h
#include unistd.htypedef void (*sighandler_t) (int); //定义sighandler_t类型void catchsigint(int signo)
{printf(-----------------catch\n);
}int main(void)
{sighandler_t handler;handler signal(SIGINT, catchsigint); //注册2号信号if (handler SIG_ERR) {perror(signal error);exit(1);} //判断返回值while (1);return 0;
}
[rootlocalhost 01_signal_test]# ./signal2
^C-----------------catch //CtrlC
^C-----------------catch //CtrlC
^\Quit (core dumped) //Ctrl\
只要一发送2号信号就会执行相应函数。
2sigaction函数
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
作用对某个信号进行注册同signal即对某个信号之前对应的处理方式函数进行修改。
返回值成功0失败-1设置errno。
参数
act传入参数新的处理方式。
oldact传出参数旧的处理方式。
struct sigaction结构体 struct sigaction { void (*sa_handler)(int); void (*sa_sigaction)(int, siginfo_t *, void *); sigset_t sa_mask; int sa_flags; void (*sa_restorer)(void); }; //最后一个成员不用舍弃了第二成员不常用
sa_restorer该元素是过时的不应该使用POSIX.1标准将不指定该元素。(弃用)
sa_sigaction当sa_flags被指定为SA_SIGINFO标志时使用该信号处理程序。(很少使用)
重点掌握
sa_handler指定信号捕捉后的处理函数名(即注册函数)。也可赋值为SIG_IGN表忽略 或 SIG_DFL表执行默认动作
sa_mask: 调用信号处理函数时所要屏蔽的信号集合信号屏蔽字。注意仅在处理函数被调用期间屏蔽生效是临时性设置sa_mask也是一个字64位只是在执行相应的用户处理函数期间生效。即在执行用户处理函数期间 sa_mask屏蔽的信号也不能递达处于未决状态。如果sa_mask未屏蔽则响应信号中断嵌套。相当于此期间sa_mask代替了mask。
sa_flags通常设置为0表示用默认属性。默认属性即为sa_mask中将自己屏蔽即该信号的注册函数执行期间再次向进程发送该信号该信号不能递达处于未决状态。
最后一个参数如果不关心之前的处理方式可以为NULL。
3信号捕捉机制
进程正常运行时默认PCB中有一个信号屏蔽字假定为mask它决定了进程自动屏蔽哪些信号。当注册了某个信号捕捉函数捕捉到该信号以后要调用该函数。而该函数有可能执行很长时间在这期间所屏蔽的信号不由mask来指定。而是用sa_mask来指定。调用完信号处理函数再恢复为mask。
sa_flags为0时XXX信号捕捉函数执行期间XXX信号自动被屏蔽。
阻塞的常规信号1-31不支持排队产生多次只记录一次。后32个实时信号支持排队
内核实现信号捕捉的过程如下 首先处于用户态user mode的某个进程在执行到某个指令时突然接收某个信号软中断终端按键产生硬件异常产生命令产生系统调用产生或者软件条件产生会暂停执行下一条指令而陷入内核进入内核态。
内核在处理这一异常后在准备会用户态之前先处理可以递达该进程的信号。
如果该信号的处理方式为捕捉则内核对该信号进行捕捉同时调用相应的用户处理函数回到用户态执行相应的用户处理函数注意不是回到主控制流程。
在用户处理函数执行完返回时再次执行系统调用sigretum再次进入内核。因为函数执行完需要返回到该函数的调用点而该函数是内核调用的因此需要再次返回到内核。
最后从内核再次返回到用户模式从上次中断处继续执行下一条指令。 //练习1为某个信号设置捕捉函数验证在信号处理函数执行期间该信号多次递送那么只在处理函数之行结束后处理一次验证sa_mask在捕捉函数执行期间的屏蔽作用。
#include stdio.h
#include unistd.h
#include stdlib.h
#include signal.hvoid docatch(int signo) //用户处理函数
{printf(the %dth signal is catched\n, signo);sleep(10); printf(-------finish------\n);
}
int main(void)
{int ret;struct sigaction act;act.sa_handler docatch;sigemptyset(act.sa_mask);sigaddset(act.sa_mask, SIGQUIT); //sa_mask屏蔽字中3号信号置1act.sa_flags 0; //默认属性 信号捕捉函数执行期间自动屏蔽本信号ret sigaction(SIGINT, act, NULL); //注册2号信号if (ret -1) {perror(sigaction error);exit(1);}while (1);return 0;
}
[rootlocalhost 01_signal_test]# ./test_sigac
^Cthe 2th signal is catched // 发2号信号 Ctrl C
-------finish------
^Cthe 2th signal is catched // 发2号信号 Ctrl C
^C^C^C^C^C^C^C^C^C^C^C^C^C-------finish------ // 执行期间发多个2号信号
the 2th signal is catched
-------finish------ //但是只是执行了一次
^Cthe 2th signal is catched
^\^\^\^\^\^\^\^\^\^\^\^\-------finish------ // 执行期间发多个3号信号
Quit (core dumped) //2号信号处理完后处理2号则退出进程结束。