【sigaction系統調用】
功能描述:
處理訊號。既可用於設定對任意訊號的處理方式,也可用於檢驗該訊號的目前預設處置方式。
用法:
#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; } |