Linux System Programming 學習筆記(十) 信號

1. 信號是軟中斷,提供處理異步事件的機制

異步事件能夠是來源於系統外部(例如用戶輸入Ctrl-C)也能夠來源於系統內(例如除0)
 
內核使用如下三種方法之一來處理信號:
(1) 忽略該信號SIGKILL和SIGSTOP不能被忽略
(2) 捕捉而且處理該信號。The kernel will suspend execution of the process’s current code path and jump to a previously registered function.
SIGKILL和SIGSTOP不能被捕捉
(2) 執行默認操做
 
SIGCHLD:進程終止時,內核向其父進程發送SIGCHLD信號,默認是忽略,若是父進程須要子進程終止信息,而須要顯式處理,一般是調用wait函數
SIGINT:用戶輸入中斷字符 Ctrl-C
SIGKILL,SIGSTOP:kill系統調用發出的信號,不能被忽略,不能被捕捉,結果老是終止進程
SIGSEGV:段錯誤
 

2. 基本的信號管理

 

#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal (int signo, sighandler_t handler);

signal() removes the current action taken on receipt of the signal signo and instead handles the signal with the signal handler specified by handlershell

 

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
/* handler for SIGINT and SIGTERM */
static void signal_handler (int signo)
{
        if (signo == SIGINT)
                printf ("Caught SIGINT!\n");
        else if (signo == SIGTERM)
                printf ("Caught SIGTERM!\n");
        else {
                /* this should never happen */
                fprintf (stderr, "Unexpected signal!\n");
                exit (EXIT_FAILURE);
        }
        exit (EXIT_SUCCESS);
}
int main (void)
{
        /*
         * Register signal_handler as our signal handler
         * for SIGINT.
         */
        if (signal (SIGINT, signal_handler) == SIG_ERR) {
                fprintf (stderr, "Cannot handle SIGINT!\n");
                exit (EXIT_FAILURE);
        }
        /*
         * Register signal_handler as our signal handler
         * for SIGTERM.
         */
        if (signal (SIGTERM, signal_handler) == SIG_ERR) {
                fprintf (stderr, "Cannot handle SIGTERM!\n");
                exit (EXIT_FAILURE);
        }
        /* Reset SIGPROF's behavior to the default. */
        if (signal (SIGPROF, SIG_DFL) == SIG_ERR) {
                fprintf (stderr, "Cannot reset SIGPROF!\n");
                exit (EXIT_FAILURE);
        }
        /* Ignore SIGHUP. */
        if (signal (SIGHUP, SIG_IGN) == SIG_ERR) {
                fprintf (stderr, "Cannot ignore SIGHUP!\n");
                exit (EXIT_FAILURE);
        }
        for (;;)
                pause ();
        return 0;
}

 

#include <signal.h>
int sigaction (int signo, const struct sigaction *act, struct sigaction *oldact);

struct sigaction {
        void (*sa_handler)(int);   /* signal handler or action */
        void (*sa_sigaction)(int, siginfo_t *, void *);
        sigset_t sa_mask;          /* signals to block */
        int sa_flags;              /* flags */
        void (*sa_restorer)(void); /* obsolete and non-POSIX */
};
sigaction() changes the behavior of the signal identified by signo, signo不能爲SIGKILL和SIGSTOP
If act is not NULL, the system call changes the current behavior of the signal as specified by act
 
信號行爲的繼承:
 
 

3. 發送信號

 
int ret;
ret = kill (1722, SIGHUP);
if (ret)
        perror ("kill");
上述代碼表示:向pid爲1722的進程發送SIGHUP信號
上述代碼與如下shell語句等同:
$ kill -HUP 1722

 

/*  a simple way for a process to send a signal to itself */
#include <signal.h>
int raise (int signo);
raise (signo);

等同於:app

kill (getpid (), signo);

 

4. 可重入

A reentrant function is a function that is safe to call from within itself (or concurrently, from another thread in the same process).
爲了確保可重入,函數 不能操做static變量,只能操做 stack-allocated data,而且不能調用 不可重入函數
相關文章
相關標籤/搜索