天天看點

信号之函數kill、raise、alarm、pause、sigprocmask、sigpending以及信号集

本文來自個人部落格: https://dunkwan.cn

文章目錄

    • 函數`kill`和`raise`
    • 函數`alarm`和`pause`
    • 信号集
    • 函數`sigprocmask`
    • 函數`sigpending`

函數

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種情形:

  1. pid

    > 0 将該信号發送給程序ID為

    pid

    的程序。
  2. pid

    == 0 将該信号發送給與發送程序屬于同一程序組的所有程序,而且發送程序具有權限向這些程序發送信号。這裡所用的術語“所有程序”不包括實作定義的系統程序集。對于大多數UNIX系統,系統程序集包括核心程序和

    init

    (pid為1)。
  3. pid

    < 0 将該信号發送給其程序組ID等于

    pid

    絕對值,而且發送程序具有權限向其發送信号的所有程序。
  4. pid

    == -1 将該信号發送給發送程序有權限向它們發送信号的所有程序。這裡的所有程序不包括系統程序集中的程序。

函數

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

函數用于檢測或更改,或同時檢測和更改程序的信号屏蔽字。

#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

的取值如下表:

信号之函數kill、raise、alarm、pause、sigprocmask、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");
}
           

結果如下:

信号之函數kill、raise、alarm、pause、sigprocmask、sigpending以及信号集