2023年10月27日 星期五

syscall sigaction()

系統呼叫 sigaction() 用來改變接收到特定 signal 時執行的動作。

#include <signal.h>
int sigaction(
    int signum, // signal 號碼,除了 SIGKILL 和 SIGSTOP
    const struct sigaction *act, // 不是 NULL 時安裝新動作
    struct sigaction *oldact); // 不是 NULL 時存舊動作

struct sigaction {
    void     (*sa_handler)(int signum);
    void     (*sa_sigaction)(int signum, siginfo_t *, void *ucontext);
    sigset_t   sa_mask;
    int        sa_flags;
    void     (*sa_restorer)(void);
};
  • sa_handler 和 sa_sigaction 指定相關的執行動作,sa_flags 有 SA_SIGINFO 用後者否則用前者,有些架構 sa_handler 和 sa_sigaction 是 union。
  • sa_handler 可以是 SIG_DFL 用預設動作,SIG_IGN 忽略這個 signal,或指到只收 signal number 的 signal handling 函數。
  • sa_sigaction 接收 3 個的引數,signum 是 signal number,siginfo_t 是包含 signal 進一步資訊的 structure,ucontext。
  • sa_mask 指定 siganl 發生執行動作時,要遮蔽的 signal。此外,驅動的 signal 也會遮蔽,除非使用 SA_NODEFER flag。
  • sa_flags 指定 a set of flags which modify the behavior of the signal. It is formed by the bitwise OR of zero or more of the following:
    • SA_NOCLDSTOP:
    • SA_NOCLDWAIT:
    • SA_NODEFER:
    • SA_ONSTACK
    • SA_RESETHAND
    • SA_RESTART
    • SA_RESTORER
    • SA_SIGINFO
  • The sa_restorer field is not intended for application use. (POSIX does not specify a sa_restorer field.) Some further details of the purpose of this field can be found in sigreturn(2).

void (*sa_sigaction)(int sig, siginfo_t *info, void *ucontext); 有三個引數,sig 是 singal number,siginfo_t 資料結構如下:

siginfo_t {
    int      si_signo;     /* Signal number */
    int      si_errno;     /* An errno value,在 Linux 一般不使用 */
    int      si_code;      /* Signal code */
    int      si_trapno;    /* Trap number that caused hardware-generated signal
                              (unused on most architectures) */
    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 */
    int      si_overrun;   /* Timer overrun count; POSIX.1b timers */
    int      si_timerid;   /* Timer ID; POSIX.1b timers */
    void    *si_addr;      /* Memory location which caused fault */
    long     si_band;      /* Band event (was int in glibc 2.3.2 and earlier) */
    int      si_fd;        /* File descriptor */
    short    si_addr_lsb;  /* Least significant bit of address (Linux 2.6.32+) */
    void    *si_lower;     /* Lower bound when address violation occurred (Linux 3.19+) */
    void    *si_upper;     /* Upper bound when address violation occurred (Linux 3.19+) */
    int      si_pkey;      /* Protection key on PTE that caused fault (Linux 4.6+) */
    void    *si_call_addr; /* Address of system call instruction (Linux 3.5+) */
    int      si_syscall;   /* Number of attempted system call (Linux 3.5+) */
    unsigned int si_arch;  /* Architecture of attempted system call (Linux 3.5+) */
}

ucontext 其實是指到 ucontext_t 結構 (為什麼要 cast to void *?),包含 signal context information that was saved on the user-space stack by the kernel; for details, see sigreturn(2). Further information about the ucontext_t structure can be found in getcontext(3).

sigaction, rt_sigaction - examine and change a signal action

參考

  1. man sigaction
  2. man sigreturn

沒有留言:

張貼留言

SIP header Via

所有 SIP 訊息 都要有 Via,縮寫 v。一開始的 UAC 和後續途經的每個 proxy 都會疊加一個 Via 放傳送的位址,依序作為回應的路徑。 格式 sent-protocol sent-by [ ;branch= branch ][ ; 參數 ...] s...