10.14 sigaction函数
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了10.14 sigaction函数相关的知识,希望对你有一定的参考价值。
函数sigaction允许我们获取或者是修改(或者获取并修改)与特定信号相关联的处理函数,该函数替代了早期的UNIX系统发布版中的函数signal,实际上,在本节末尾,我们将会使用sigaction来实现一个signal函数。
#include<signal.h>
int sigaction(int signo,conststruct sigaction *restrict act,struct sigaction *restrict oact);
Returns:0if OK,-1 on error.
参数signo指定我们正在获取或者是修改的信号编号,如果act指针是非空指针,那么我们就正在修改信号处理动作,如果oact指针是非空指针,那么系统将会返回signo指定的信号的前一个处理。该函数使用的结构定义如下:
struct sigaction
{
void(*sa_handler)(int);/*addr of signal handler,or SIG_IGN or SIG_DFL*/
sigset_t sa_mask;/*additional signals to block*/
int sa_flags;/*signal options,Figure 10.16*/
/*alternate handler*/
void(*sa_sigaction)(int,siginfo_t,void*);
};
当修改函数的处理动作的时候,参数sa_handler用于传递信号处理函数,参数sa_mask用于指定一个信号集,该信号集在信号处理函数被调用之前增加到信号掩码中去,当信号处理函数返回的时候,信号掩码就会恢复到之前的数值。使用这种方式,我们可以在调用某一个信号处理函数的时候阻塞掉某些信号。如果操作系统会在信号掩码默认包含当前处理函数正在处理的信号,那么,无论何时只要我们正在处理给定信号,相同的信号的出现必须等待第一次出现的信号处理完毕才可以被发送。在10.8节中提到,相同信号的多次出现一般并不会被排队,如果信号出现多次,当我们接触信号阻塞的时候,该信号的信号处理函数通常只是被调用一次。
一旦我们对给定信号设置了处理动作,那么该动作就会保持有效,直到下一次我们显式地调用函数sigaction改变信号它。不像早期系统中的不可靠信号,POSIX.1要求信号处理函数一直保持安装状态,直到显式调用函数对其修改为止。
act结构的sa_flags数据域对于信号的处理指定了不同的选项,图10.16具体介绍了信号处理的不同选项,SUS列包含了*如果标识是作为POSIX.1标准的一部分定义的话,而如果是XSI的话就表示是XSI选项的一部分。
参数sa_sigaction域是另一个信号处理函数,仅仅当sigaction中的SA_SIGINFO标识被指定的时候使用,实现可能对于sa_sigaction域以及sa_handler域使用相同的存储,因此应用只需要使用这两个域中的其中之一就好了。
Option | SUS | FreeBSD 8.0 | Linux 3.2.0 | Mac OS X 10.6.8 | Solaris 10 | Description |
---|---|---|---|---|---|---|
SA_INTERRUPT | * | 被该信号中断的系统调用将不会自动重启,是sigaction的默认选择(For XSI) | ||||
SA_NOCLDSTOP | * | * | * | * | * | 如果信号是SIGCHLD,当子进程停止的时候,不要产生信号(job control),当然了,当子进程终止的时候,该信号还是会被产生的(但是还不需要看一下下面介绍的SA_NOCLDWAIT选项),如果实现支持XSI选项的话,如果该标志被设置,那么如果已经停止的子进程继续运行的时候,SIGCHLD将不会被发送。 |
SA_NOCLDWAIT | * | * | * | * | * | 如果信号是SIGCHLD,该选项用于防止系统创建僵尸进程(当调用进程的子进程终止的时候),如果再次之后调用函数wait,调用进程将会发生阻塞,直到其所有子进程都终止运行,然后wait函数将返回-1,并将errno设置为ECHILD |
SA_NODEFFER | * | * | * | * | * | 当该信号被出现,而且信号捕获函数正在执行的时候,信号并不会被系统自动阻塞(除非该信号也被包含在sa_mask中),注意该类型的操作对应于早期的不可靠信号 |
SA_ONSTACK | XSI | * | * | * | * | If an alternative stack has been declared with sigaltstack(2), this signal is delivered to the process on the alternative stack. |
SA_RESETHAND | * | * | * | * | * | 在信号处理函数被调用的时候,将该信号的动作重置为SIG_DFL,并且在信号处理函数的入口将SA_SIGINFO清除。注意这种类型的操作对应于早期的不可靠信号。对于信号SIGILL以及SIGTRAP并不能被自动重置。无论如何,设置该标志将会导致sigaction函数表现得就像SA_NODEFER也被设置时一样。 |
SA_RESTART | * | * | * | * | * | 被该信号中断掉的系统调用将会自动重启 |
SA_SIGINFO | * | * | * | * | * | 该选项可以提供一个额外的信息给信号处理函数:一个指向siginfo结构的指针,一个指向进程上下文的标识符的指针。 |
Figure 10.16 Option flags(sa_flags) for the handling of each signal
正常情况下,信号处理函数以如下形式被调用:
void handler(int signo);
但是如果设置了标识SA_SIGINFO,那么信号处理函数将以如下形式调用:
void handler(int signo, siginfo_t *info, void *context);
siginfo结构包含了为什么信号被生成的信息,该结构的一个例子如下所示。所有兼容POSIX.1的实现都至少包含si_signo以及si_code成员。此外,兼容XSI选项的实现至少需要包含如下的成员:
struct siginfo
{
int si_signo;/* signal number */
int si_errno;/* if nonzero,errno value from errno.h */
int si_code;/* additional info(depends on signal) */
pid_t si_pid;/* sending process ID */
uid_t si_uid;/* sending process real user ID */
void*si_addr;/* address that caused the default */
int si_status;/* exit value or signal number */
union sigval si_value;/* application-specific value */
/*possibly other fields also */
}
联合sigval包含了如下两个数据域:
int sival_int;
void*sival_ptr;
应用程序可以在发送信号的时候通过si_value.sival_int中传递一个整数或者是在si_value.sival_ptr中传递一个指针。
图10.17显示了对于不同信号si_code的数值,正如在Single UNIX Specification中定义的那样,注意实现还可能自定义额外的code值。
如果信号是SIGCHLD,那么si_pid,si_status以及si_uid将被设置,如果信号是SIGBUS,SIGILL,SIGFPE或者是SIGSEGV,那么si_addr包含了对应的错误地址,虽然地址可能并不准确。si_errno包含了对应于造成信号的条件的错误号,虽然其使用是由实现定义的。
信号处理函数的上下文参数是一个无类型的指针,可以被转换为类型ucontext_t结构,用于标识信号发送时的上下文,该结构至少包含了如下数据域:
ucontext_t*uc_link;/* pointer to context resumed when this context returns*/
sigset_t uc_sigmask;/* signals blocked when this context is active */
stack_t uc_stack;/* stack used by this context */
mcontext_t uc_mcontext;/* machine-specific representation of saved context */
域uc_stack描述了当前上下文使用的堆栈,至少包含了两个成员:
void*ss_sp;/* stack base or pointer */
size_t ss_size;/*stack size */
int ss_flags;/* flags */
当实现支持实时信号扩展的时候,使用SA_SIGINFO建立的信号处理函数将会被可靠地排队,并且信号编号中保留了一段专门用于实时应用,应用程序可以使用函数sigqueue(将在10.20章中讲解)通过信号传递信息。
Signal | Code | Reason |
---|---|---|
SIGILL | ILL_ILLOPC | 非法操作码 |
SIGILL | ILL_ILLOPN | 非法操作数 |
SIGILL | ILL_ILLADR | 非法寻址方式 |
SIGILL | ILL_ILLTRP | 非法陷阱 |
SIGILL | ILL_PRVOPC | 特权操作码 |
SIGILL | ILL_PRVREG | 特权寄存器 |
SIGILL | ILL_COPROC | 协处理器错误 |
SIGILL | ILL_BADSTK | 内部栈错误 |
SIGFPE | FPE_INTDIV | 整数除零 |
SIGFPE | FPE_INTOVF | 整数溢出 |
SIGFPE | FPE_FLTDIV | 浮点除零 |
SIGFPE | FPE_FLTOVF | 浮点溢出 |
SIGFPE | FPE_FLTUND | 浮点数下溢 |
SIGFPE | FPE_FLTRES | 浮点结果不准确 |
SIGFPE | FPE_FLTINV | 无效浮点操作 |
SIGFPE | FPE_FLTSUB | 下标溢出 |
SIGSEGV | SEGV_MAPERR | 无效映射地址 |
SIGSEGV | SEGV_ACCERR | 映射对象全向无效 |
SIGBUS | BUS_ADRALN | 无效地址对齐 |
SIGBUS | BUS_ADRERR | 不存在的物理地址 |
SIGBUS | BUS_OBJERR | 特定对象硬件错误 |
SIGTRAP | TRAP_BRKPT | 进程断点陷阱 |
SIGTRAP | TRAP_TRACE | process trace trap |
SIGCHLD | CLD_EXITED | 子进程退出 |
SIGCHLD | CLD_KILLED | 子进程异常终止(no core) |
SIGCHLD | CLD_DUMPED | 子进程异常终止(with core) |
SIGCHLD | CLD_TRAPPED | traced child has trap |
SIGCHLD | CLD_STOPPED | 子进程已经停止 |
SIGCHLD | CLD_CONTINUED | 停止的子进程已经继续运行 |
Any | SI_USER | 信号由kill发送 |
Any | SI_QUEUE | 信号由sigqueue发送 |
Any | SI_TIMER | time_settime设置的定时器结束 |
Any | SI_ASYNCIO | 异步IO请求完成 |
Any | SI_MESGQ | 一个消息队列中的消息到达(实时扩展) |
Figure 10.17 siginfo_t code values
以上是关于10.14 sigaction函数的主要内容,如果未能解决你的问题,请参考以下文章