功能描述:
处理信号。既可用于设定对任意信号的处理方式,也可用于检验该信号的目前预设处置方式。
用法:
#include <signal.h>
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
参数:
signum:除了SIGKILL和SIGSTOP之外的其它任何信号编码。
act:如果值非NULL,将安装为signum关联信号的新处理方式。
oldact:如果值非NULL,存储以前对signum关联信号的处理方式。
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和sa_sigaction共用一个联合体(union),所以不要同时指定两个字段的值。
sa_restorer字段已淘汰,不应该再被使用。
sa_handler字段指定与signum信号关联的行为,可能是SIG_DFL默认行为,SIG_IGN忽略接送到的信号,或者一个信号处理函数指针。这个函数以一个信号编码作为它的唯一参数。
如果sa_flags中存在SA_SIGINFO标志,那么sa_sigaction将作为signum信号的处理函数。这个函数的第一参数是信号编码,第二参数是siginfo_t结构的指针,第三参数是ucontext_t结构指针(造型为void *)。
sa_mask指定信号处理函数执行的过程中应被阻塞的信号。另外,除了SA_NODEFER标志被指定外,触发信号处理函数执行的那个信号也会被阻塞。
sa_flags指定一系列用于修改信号处理过程行为的标志,由下面的0个或多个标志通过or运算组合而成:
SA_NOCLDSTOP //此标志为on时,假如signum的值是SIGCHLD,则在子进程停止或恢复执行时不会传信号给调用本系统调用的进程。
SA_NOCLDWAIT //此标志为on时,当调用此系统调用的进程之子进程终止时,系统不会建立zombie进程。
SA_RESETHAND //此标志为on时,信号处理函数接收到信号后,会先将对信号处理的方式设为预设方式,而且当函数处理该信号时,后来发生的信号将不会被阻塞。
SA_ONSTACK //如果利用sigaltstack()建立信号专用堆栈,则此标志会把所有信号送往该堆栈。
SA_RESTART //此标志为on时,核心会自动重启信号中断的系统调用,否则返回EINTR错误值。
SA_NODEFER //当此标志为on时,在信号处理函数处置信号的时段中,核心程序不会把这个间隙中产生的信号阻塞。
SA_SIGINFO //此标志为on时,指定信号处理函数需要三个参数,所以应使用sa_sigaction替代sa_handler。
sa_sigaction第二个参数siginfo_t结构的原型如下:
siginfo_t {
int si_signo; /* Signal number */
int si_errno; /* An errno value */
int si_code; /* Signal code */
pid_t si_pid; /* Sending process ID */
uid_t si_uid; /* Real user ID of sending process */
int si_status; /* Exit value or signal */
clock_t si_utime; /* User time consumed */
clock_t si_stime; /* System time consumed */
sigval_t si_value; /* Signal value */
int si_int; /* POSIX.1b signal */
void * si_ptr; /* POSIX.1b signal */
void * si_addr; /* Memory location which caused fault */
int si_band; /* Band event */
int si_fd; /* File descriptor */
}
开 头的三个字段si_signo,si_errno 和 si_code为所有信号使用(Linux中si_signo不被使用),结构的剩下部分可看作联合体,所以应该只读取对给定信号有意义的字段。 POSIX.1b信号和SIGCHLD填写si_pid 和 si_uid两个字段。SIGCHLD信号同时填写si_status, si_utime 和 si_stime。si_int 和 si_ptr为POSIX.1b信号发送者而指定。SIGILL,SIGFPE,SIGSEGV 和 SIGBUS用出错地址填写si_addr字段。
si_code指示信号发送的原因。它是一个值,而不是位掩码。下面表中列出任何信号的可能值:
+-------------------------------------------------------------------+
| si_code |
+-----------+-------------------------------------------------------+
|Value | Signal origin |
+-----------+-------------------------------------------------------+
|SI_USER | kill(), sigsend(), or raise() |
+-----------+-------------------------------------------------------+
|SI_KERNEL | The kernel |
+-----------+-------------------------------------------------------+
|SI_QUEUE | sigqueue() |
+-----------+-------------------------------------------------------+
|SI_TIMER | POSIX timer expired |
+-----------+-------------------------------------------------------+
|SI_MESGQ | POSIX message queue state changed (since Linux 2.6.6) |
+-----------+-------------------------------------------------------+
|SI_ASYNCIO | AIO completed |
+-----------+-------------------------------------------------------+
|SI_SIGIO | queued SIGIO |
+-----------+-------------------------------------------------------+
|SI_TKILL | tkill() or tgkill() (since Linux 2.4.19) |
+-----------+-------------------------------------------------------+
+-------------------------------------+
| SIGILL |
+-----------+-------------------------+
|ILL_ILLOPC | illegal opcode |
+-----------+-------------------------+
|ILL_ILLOPN | illegal operand |
+-----------+-------------------------+
|ILL_ILLADR | illegal addressing mode |
+-----------+-------------------------+
|ILL_ILLTRP | illegal trap |
+-----------+-------------------------+
|ILL_PRVOPC | privileged opcode |
+-----------+-------------------------+
|ILL_PRVREG | privileged register |
+-----------+-------------------------+
|ILL_COPROC | coprocessor error |
+-----------+-------------------------+
|ILL_BADSTK | internal stack error |
+-----------+-------------------------+
+----------------------------------------------+
| SIGFPE |
+-----------+----------------------------------+
|FPE_INTDIV | integer divide by zero |
+-----------+----------------------------------+
|FPE_INTOVF | integer overflow |
+-----------+----------------------------------+
|FPE_FLTDIV | floating point divide by zero |
+-----------+----------------------------------+
|FPE_FLTOVF | floating point overflow |
+-----------+----------------------------------+
|FPE_FLTUND | floating point underflow |
+-----------+----------------------------------+
|FPE_FLTRES | floating point inexact result |
+-----------+----------------------------------+
|FPE_FLTINV | floating point invalid operation |
+-----------+----------------------------------+
|FPE_FLTSUB | subscript out of range |
+-----------+----------------------------------+
+----------------------------------------------------+
| SIGSEGV |
+------------+---------------------------------------+
|SEGV_MAPERR | address not mapped to object |
+------------+---------------------------------------+
|SEGV_ACCERR | invalid permissions for mapped object |
+------------+---------------------------------------+
+--------------------------------------------+
| SIGBUS |
+-----------+--------------------------------+
|BUS_ADRALN | invalid address alignment |
+-----------+--------------------------------+
|BUS_ADRERR | non-existent physical address |
+-----------+--------------------------------+
|BUS_OBJERR | object specific hardware error |
+-----------+--------------------------------+
+--------------------------------+
| SIGTRAP |
+-----------+--------------------+
|TRAP_BRKPT | process breakpoint |
+-----------+--------------------+
|TRAP_TRACE | process trace trap |
+-----------+--------------------+
+----------------------------------------------------------------+
| SIGCHLD |
+--------------+-------------------------------------------------+
|CLD_EXITED | child has exited |
+--------------+-------------------------------------------------+
|CLD_KILLED | child was killed |
+--------------+-------------------------------------------------+
|CLD_DUMPED | child terminated abnormally |
+--------------+-------------------------------------------------+
|CLD_TRAPPED | traced child has trapped |
+--------------+-------------------------------------------------+
|CLD_STOPPED | child has stopped |
+--------------+-------------------------------------------------+
|CLD_CONTINUED | stopped child has continued (since Linux 2.6.9) |
+--------------+-------------------------------------------------+
+-----------------------------------------+
| SIGPOLL |
+---------+-------------------------------+
|POLL_IN | data input available |
+---------+-------------------------------+
|POLL_OUT | output buffers available |
+---------+-------------------------------+
|POLL_MSG | input message available |
+---------+-------------------------------+
|POLL_ERR | i/o error |
+---------+-------------------------------+
|POLL_PRI | high priority input available |
+---------+-------------------------------+
|POLL_HUP | device disconnected |
+---------+-------------------------------+
返回说明:
成功执行时,返回0。失败返回-1,errno被设为以下的某个值
EFAULT:act或oldact指向的内存区并非有效的进程地址空间
EINVAL:指定无效的信号,或者尝试改变SIGKILL 或 SIGSTOP信号的处理方式
例子:
2007-10-02 13:13
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <setjmp.h>
void sig_handler(int);
void count_prime(int);
int main(int argc, char **argv)
{
struct sigaction nact;
int i;
if(argc < 2) {
printf("Usage: argv[0] <number> \n\n");
exit(1);
}
i = atoi(argv[1]);
nact.sa_handler = sig_handler;
nact.sa_flags = SA_RESTART;
sigaction(SIGINT, &nact, NULL);
printf("****************************************************************************\n");
count_prime(i);
printf("****************************************************************************\n");
exit(0);
}
void sig_handler(int sig)
{
printf("SIGINT is caught\n");
return;
}
void count_prime(int num)
{
static int j, k = 2;
static unsigned int total = 0;
puts("counting ...");
for(; k <= num; ++k) {
j = 2;
while(k % j != 0)
++j;
if(j == k) {
printf("%d\t", k);
if(total % 10 == 0)
printf("\n");
++total;
}
}
printf("\n");
printf("Total number of primes between 0~%d is %d \n", num, total);
return;
}