signal, sigaction,信号集合操作
2013-12-20 18:06
246 查看
信号是与一定的进程相联系的,而建立其信号和进程的对应关系,这就是信号的安装登记。
Linux主要有两个函数实现信号的安装登记:signal和sigaction。其中signal在系统调用的基础上实现,是库函数。它只有两个参数,不支持信号传递信息,主要是用于前32个非实时信号的安装;而sigaction是较新的函数(由两个系统调用实现:sys_signal以及sys_rt_sigaction),有三个参数,支持信号传递信息,主要用来与sigqueue系统调用配合使用。当然,sigaction同样支持非实时信号的安装,sigaction优于signal主要体现在支持信号带有参数。
对于应用程序自行处理的信号来说,信号的生命周期要经过信号的安装登记、信号集操作、信号的发送和信号的处理四个阶段。
在signal函数中,有两个形参,分别代表需要处理的信号编号值和处理信号函数的指针。它主要是用于前32种非实时信号的处理,不支持信号的传递信息。但是由于使用简单,易于理解,因此在许多场合被程序员使用。
对于Unix系统来说,使用signal函数时,自定义处理信号函数执行一次后失效,对该信号的处理回到默认处理方式。下面以一个例子进行说明,例如一程序中使用signal(SIGQUIT, my_func)函数调用,其中my_func是自定义函数。应用进程收到SIGQUIT信号时,会跳转到自定义处理信号函数my_func处执行,执行后信号注册函数my_func失效,对SIGQUIT信号的处理回到操作系统的默认处理方式,当应用进程再次收到SIGQUIT信号时,会按操作系统默认的处理方式进行处理(即不再执行my_func处理函数)。而在Linux系统中,signal函数已被改写,由sigaction函数封装实现,则不存在上述问题。
(2)signal函数原型
signal函数原型比较复杂,如果使用下面的typedef,则可使其简化。
typedef void sign(int);
sign *signal(int, handler *);
可见,该函数原型首先整体指向一个无返回值带一个整型参数的函数指针,也就是信号的原始配置函数。接着该原型又带有两个参数,其中的第二个参数可以是用户自定义的信号处理函数的函数指针。对这个函数格式可以不理解,但需要学会模仿使用。
(3) signal函数使用实例
该示例表明了如何使用signal函数进行安装登记信号处理函数。当该信号发生时,登记的信号处理函数会捕捉到相应的信号,并做出给定的处理。这里,my_func就是信号处理的函数指针。读者还可以将my_func改为SIG_IGN或SIG_DFL查看运行结果。
signal.c源代码如下:
2. sigaction函数
(1)sigaction函数原型
sigaction函数用来查询和设置信号处理方式,它是用来替换早期的signal函数。sigaction函数原型及说明如下:
(2)sigaction函数使用实例
sigaction.c源代码如下:
View Code
Linux主要有两个函数实现信号的安装登记:signal和sigaction。其中signal在系统调用的基础上实现,是库函数。它只有两个参数,不支持信号传递信息,主要是用于前32个非实时信号的安装;而sigaction是较新的函数(由两个系统调用实现:sys_signal以及sys_rt_sigaction),有三个参数,支持信号传递信息,主要用来与sigqueue系统调用配合使用。当然,sigaction同样支持非实时信号的安装,sigaction优于signal主要体现在支持信号带有参数。
对于应用程序自行处理的信号来说,信号的生命周期要经过信号的安装登记、信号集操作、信号的发送和信号的处理四个阶段。
1)信号的安装登记指的是在应用程序中,安装对此信号的处理方法。
2)信号集操作的作用是用于对指定的一个或多个信号进行信号屏蔽。
3)信号的发送指的是发送信号,可以通过硬件(如在终端上按下Ctrl-C)发送的信号和软件(如通过kill函数)发送的信号。
4)信号的处理指的是操作系统对接收信号进程的处理,处理方法是先检查信号集操作函数是否对此信号进行屏蔽,如果没有屏蔽,操作系统将按信号安装函数中登记注册的处理函数完成对此进程的处理。
1. signal函数
(1)函数说明在signal函数中,有两个形参,分别代表需要处理的信号编号值和处理信号函数的指针。它主要是用于前32种非实时信号的处理,不支持信号的传递信息。但是由于使用简单,易于理解,因此在许多场合被程序员使用。
对于Unix系统来说,使用signal函数时,自定义处理信号函数执行一次后失效,对该信号的处理回到默认处理方式。下面以一个例子进行说明,例如一程序中使用signal(SIGQUIT, my_func)函数调用,其中my_func是自定义函数。应用进程收到SIGQUIT信号时,会跳转到自定义处理信号函数my_func处执行,执行后信号注册函数my_func失效,对SIGQUIT信号的处理回到操作系统的默认处理方式,当应用进程再次收到SIGQUIT信号时,会按操作系统默认的处理方式进行处理(即不再执行my_func处理函数)。而在Linux系统中,signal函数已被改写,由sigaction函数封装实现,则不存在上述问题。
(2)signal函数原型
signal(设置信号处理方式) | ||
所需头文件 | #include <signal.h> | |
函数说明 | 设置信号处理方式。signal()会依参数signum指定的信号编号来设置该信号的处理函数。当指定的信号到达时就会跳转到参数handler指定的函数执行 | |
函数原型 | void (*signal(int signum,void(* handler)(int)))(int) | |
函数传入值 | signum | 指定信号编号 |
handle | SIG_IGN:忽略参数signum指定的信号 | |
SIG_DFL:将参数signum指定的信号重设为核心预设的信号处理方式,即采用系统默认方式处理信号 | ||
自定义信号函数处理指针 | ||
函数返回值 | 成功 | 返回先前的信号处理函数指针 |
出错 | SIG_ERR(-1) | |
附加说明 | 在Unix环境中,在信号发生跳转到自定的handler处理函数执行后,系统会自动将此处理函数换回原来系统预设的处理方式,如果要改变此情形请改用sigaction函数。在Linux环境中不存在此问题 |
typedef void sign(int);
sign *signal(int, handler *);
可见,该函数原型首先整体指向一个无返回值带一个整型参数的函数指针,也就是信号的原始配置函数。接着该原型又带有两个参数,其中的第二个参数可以是用户自定义的信号处理函数的函数指针。对这个函数格式可以不理解,但需要学会模仿使用。
(3) signal函数使用实例
该示例表明了如何使用signal函数进行安装登记信号处理函数。当该信号发生时,登记的信号处理函数会捕捉到相应的信号,并做出给定的处理。这里,my_func就是信号处理的函数指针。读者还可以将my_func改为SIG_IGN或SIG_DFL查看运行结果。
signal.c源代码如下:
#include <signal.h> #include <stdio.h> #include <stdlib.h> /*自定义信号处理函数*/ void my_func(int sign_no) { if(sign_no==SIGINT) printf("I have get SIGINT\n"); else if(sign_no==SIGQUIT) printf("I have get SIGQUIT\n"); } int main() { printf("Waiting for signal SIGINT or SIGQUIT \n "); /*发出相应的信号,并跳转到信号处理函数处*/ signal(SIGINT, my_func); signal(SIGQUIT, my_func); pause(); exit(0); } 编译 gcc signal.c –o signal。 执行 ./signal, 执行结果如下: Waiting for signal SIGINT or SIGQUIT I have get SIGINT /*按下Ctrl+C,操作系统就会向进程发送SIGINT信号*/ I have get SIGQUIT /*按下Ctrl-\(退出),操作系统就会向进程发送SIGQUIT信号*/
2. sigaction函数
(1)sigaction函数原型
sigaction函数用来查询和设置信号处理方式,它是用来替换早期的signal函数。sigaction函数原型及说明如下:
sigaction(查询和设置信号处理方式) |
所需头文件 | #include <signal.h> | |
函数说明 | sigaction()会依参数signum指定的信号编号来设置该信号的处理函数 | |
函数原型 | int sigaction(int signum,const struct sigaction *act ,struct sigaction *oldact) | |
函数传入值 | signum | 可以指定SIGKILL和SIGSTOP以外的所有信号 |
act | 参数结构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_handler:此参数和signal()的参数handler相同,此参数主要用来对信号旧的安装函数signal()处理形式的支持 ② sa_sigaction:新的信号安装机制,处理函数被调用的时候,不但可以得到信号编号,而且可以获悉被调用的原因以及产生问题的上下文的相关信息。 ③ sa_mask:用来设置在处理该信号时暂时将sa_mask指定的信号搁置 ④ sa_restorer: 此参数没有使用 ⑤ sa_flags:用来设置信号处理的其他相关操作,下列的数值可用。可用OR 运算(|)组合 A_NOCLDSTOP:如果参数signum为SIGCHLD,则当子进程暂停时并不会通知父进程 SA_ONESHOT/SA_RESETHAND:当调用新的信号处理函数前,将此信号处理方式改为系统预设的方式 SA_RESTART:被信号中断的系统调用会自行重启 SA_NOMASK/SA_NODEFER:在处理此信号未结束前不理会此信号的再次到来 SA_SIGINFO:信号处理函数是带有三个参数的sa_sigaction | |
oldact | 如果参数oldact不是NULL指针,则原来的信号处理方式会由此结构sigaction返回 | |
函数返回值 | 成功:0 | |
出错:-1,错误原因存于error中 | ||
附加说明 | 信号处理安装的新旧两种机制: ① 使用旧的处理机制:struct sigaction act; act.sa_handler=handler_old; ② 使用新的处理机制:struct sigaction act; act.sa_sigaction=handler_new; 并设置sa_flags的SA_SIGINFO位 | |
错误代码 | EINVAL:参数signum不合法,或是企图拦截SIGKILL/SIGSTOP信号 EFAULT:参数act,oldact指针地址无法存取 EINTR:此调用被中断 |
sigaction.c源代码如下:
编译 gcc sigset.c -o sigset。 执行 ./sigset,执行结果如下: blocked SIGINT in set /*按下Ctrl+C */ signal SIGINT is pending If you want to quit,please try SIGQUIT /*按下Ctrl+C */ 退出
View Code
相关文章推荐
- linux信号机制之sigaction结构体浅析,signal 函数,信号捕捉(转)
- Linux信号(signal、sigaction) 机制分析
- 信号处理:signal和sigaction的区别
- C++ signal和sigaction信号处理
- 信号:signal以及sigaction
- linux信号机制之sigaction结构体浅析,signal 函数,信号捕捉
- linux的信号学习 ,signal(),sigaction()
- signal函数、sigaction函数及信号集(sigemptyset,sigaddset)操作函数
- linux 信号signal和sigaction理解
- linux 信号 为什么使用sigaction而非signal
- linux信号机制之sigaction结构体浅析,signal 函数,信号捕捉
- linux 0.11版本内核中信号signal()和sigaction()的区别
- linux信号机制之sigaction结构体浅析,signal 函数,信号捕捉
- Linux 信号:signal 与 sigaction
- linux 下 signal 与sigaction 对信号的处理差异
- linux 信号signal和sigaction理解
- ReactiveCocoa框架菜鸟入门——信号(Signal)详解 第二课:信号(Signal)的各种操作
- 信号 signal sigaction补充
- linux信号机制之sigaction结构体浅析,signal 函数,信号捕捉
- siginalExample.c(使用signal和sigaction函数捕捉和处理信号)