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 handler

 

#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
 
信号行为的继承:
Linux System Programming 学习笔记(十) 信号 
 

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);

等同于:

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,并且不能调用 不可重入函数
 

你可能感兴趣的:(programming)