本文來自個人部落格: https://dunkwan.cn
文章目錄
-
- 函數`kill`和`raise`
- 函數`alarm`和`pause`
- 信号集
- 函數`sigprocmask`
- 函數`sigpending`
函數 kill
和 raise
kill
raise
kill
函數将信号發送給程序或程序組。
raise
函數則允許程序向自身發送信号。
#include <signal.h>
int kill(pid_t pid, int signo);
int raise(int signo);
兩個函數傳回值:若成功,傳回0;若出錯,傳回-1。
調用
raise(signo);
等價于
kill(getpid(), signo);
。
kill
函數的
pid
參數有以下4種情形:
-
> 0 将該信号發送給程序ID為pid
的程序。pid
-
== 0 将該信号發送給與發送程序屬于同一程序組的所有程序,而且發送程序具有權限向這些程序發送信号。這裡所用的術語“所有程序”不包括實作定義的系統程序集。對于大多數UNIX系統,系統程序集包括核心程序和pid
(pid為1)。init
-
< 0 将該信号發送給其程序組ID等于pid
絕對值,而且發送程序具有權限向其發送信号的所有程序。pid
-
== -1 将該信号發送給發送程序有權限向它們發送信号的所有程序。這裡的所有程序不包括系統程序集中的程序。pid
函數 alarm
和 pause
alarm
pause
alarm
函數用于設定一個定時器(鬧鐘時間),在将來的某個時刻該定時器會逾時。當定時器逾時時,産生
SIGALRM
信号。如果忽略或不捕捉此信号,則其預設動作是終止調用該
alarm
函數的程序。
pause
函數用于使調用程序挂起直至捕捉到一個信号。
#include <unistd.h>
unsigned int alarm(unsigned int seconds);
傳回值:0或以前設定的鬧鐘時間的餘留秒數。
int pause(void);
傳回值:-1,errno設定為EINTR。
信号集
不同的信号的編号可能超過一個整型量所包含的位數,是以一般而言,不能用整型量中的一位來代表一種信号,也就是不能用一個整型量表示信号集。POSIX.1定義資料類型
sigset_t
以包含一個信号集,并且定義了下列5個處理信号集的函數。
#include <signal.h>
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set, int signo);
int sigdelset(sigset_t *set, int signo);
4個函數傳回值:若成功,傳回0;若出錯,傳回-1。
int sigismember(const sigset_t *set, int signo);
傳回值:若真,傳回1;若假,傳回0。
以下是上述函數的具體實作:
#include <signal.h>
#include <errno.h>
#define SIGBAD(signo) ((signo) <= 0 || (signo) >= NSIG)
int sigaddset(sigset_t *set, int signo)
{
if(SIGBAD(signo)){
errno = EINVAL;
return (-1);
}
(*set) |= 1 << (signo - 1);
return (0);
}
int sigdelset(sigset_t *set, int signo)
{
if(SIGBAD(signo)){
errno = EINVAL;
return (-1);
}
*set &= ~(1 <<(signo -1));
return (0);
}
int sigismember(const sigset_t *set, int signo)
{
if(SIGBAD(signo)){
errno = EINVAL;
return (-1);
}
return ((*set & (1 << (signo -1))) != 0);
}
函數 sigprocmask
sigprocmask
sigprocmask
函數用于檢測或更改,或同時檢測和更改程序的信号屏蔽字。
#include <signal.h>
int sigprocmask(int how, const sigset_t *restrict set, sigset_t *restrict oset);
傳回值:若成功,傳回0;若出錯,傳回-1。
若是非空指針,那麼程序的目前信号屏蔽字通過
oset
oset
傳回。
若
是非空指針,則參數
set
how
訓示如何修改目前信号屏蔽字。
若
是空指針,則不改變該程序的信号屏蔽字,
set
值此時無意義。
how
how
的取值如下表:
函數 sigpending
sigpending
sigpending
函數傳回一信号集,對于調用程序而言,其中的各信号是阻塞不能遞送的,因而也一定是目前未決的。該信号集通過
set
參數傳回。
#include <signal.h>
int sigpending(sigset_t *set);
傳回值:若成功,傳回0;若出錯,傳回-1。
測試示例:
#include "../../include/apue.h"
static void sig_quit(int);
int main(void)
{
sigset_t newmask, oldmask, pendmask;
if(signal(SIGQUIT, sig_quit) == SIG_ERR)
err_sys("can't catch SIGQUIT");
sigemptyset(&newmask);
sigaddset(&newmask, SIGQUIT);
if(sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
err_sys("SIG_BLOCK error");
sleep(5);
if(sigpending(&pendmask) < 0)
err_sys("sigpending error");
if(sigismember(&pendmask, SIGQUIT))
printf("\nSIGQUIT pending\n");
if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
err_sys("SIG_SETMASK error");
printf("SIGQUIT unblocked\n");
sleep(5);
return 0;
}
static void sig_quit(int signo)
{
printf("caught SIGQUIT\n");
if(signal(SIGQUIT, SIG_DFL) == SIG_ERR)
err_sys("can't reset SIGQUIT");
}
結果如下: