首页 > 技术文章 > C/C++ 进程间通信 signal

dk666 2017-08-22 15:43 原文

signal.h是C标准函数库中的信号处理部分, 定义了程序执行时如何处理不同的信号。信号用作进程间通信, 报告异常行为(如除零)、用户的一些按键组合(如同时按下Ctrl与C键,产生信号SIGINT)。

C++中的对应头文件是csignal

/**linux下signum.h**/
/* Signals.  */
#define    SIGHUP        1    /* Hangup (POSIX).  */
#define    SIGINT        2    /* Interrupt (ANSI).  */
#define    SIGQUIT        3    /* Quit (POSIX).  */
#define    SIGILL        4    /* Illegal instruction (ANSI).  */
#define    SIGTRAP        5    /* Trace trap (POSIX).  */
#define    SIGABRT        6    /* Abort (ANSI).  */
#define    SIGIOT        6    /* IOT trap (4.2 BSD).  */
#define    SIGBUS        7    /* BUS error (4.2 BSD).  */
#define    SIGFPE        8    /* Floating-point exception (ANSI).  */
#define    SIGKILL        9    /* Kill, unblockable (POSIX).  */
#define    SIGUSR1        10    /* User-defined signal 1 (POSIX).  */
#define    SIGSEGV        11    /* Segmentation violation (ANSI).  */
#define    SIGUSR2        12    /* User-defined signal 2 (POSIX).  */
#define    SIGPIPE        13    /* Broken pipe (POSIX).  */
#define    SIGALRM        14    /* Alarm clock (POSIX).  */
#define    SIGTERM        15    /* Termination (ANSI).  */
#define    SIGSTKFLT    16    /* Stack fault.  */
#define    SIGCLD        SIGCHLD    /* Same as SIGCHLD (System V).  */
#define    SIGCHLD        17    /* Child status has changed (POSIX).  */
#define    SIGCONT        18    /* Continue (POSIX).  */
#define    SIGSTOP        19    /* Stop, unblockable (POSIX).  */
#define    SIGTSTP        20    /* Keyboard stop (POSIX).  */
#define    SIGTTIN        21    /* Background read from tty (POSIX).  */
#define    SIGTTOU        22    /* Background write to tty (POSIX).  */
#define    SIGURG        23    /* Urgent condition on socket (4.2 BSD).  */
#define    SIGXCPU        24    /* CPU limit exceeded (4.2 BSD).  */
#define    SIGXFSZ        25    /* File size limit exceeded (4.2 BSD).  */
#define    SIGVTALRM    26    /* Virtual alarm clock (4.2 BSD).  */
#define    SIGPROF        27    /* Profiling alarm clock (4.2 BSD).  */
#define    SIGWINCH    28    /* Window size change (4.3 BSD, Sun).  */
#define    SIGPOLL        SIGIO    /* Pollable event occurred (System V).  */
#define    SIGIO        29    /* I/O now possible (4.2 BSD).  */
#define    SIGPWR        30    /* Power failure restart (System V).  */
#define SIGSYS        31    /* Bad system call.  */
#define SIGUNUSED    31

/**windows下gcc signal.h**/
#define    SIGINT        2    /* Interactive attention */
#define    SIGILL        4    /* Illegal instruction */
#define    SIGFPE        8    /* Floating point error */
#define    SIGSEGV        11    /* Segmentation violation */
#define    SIGTERM        15    /* Termination request */
#define SIGBREAK    21    /* Control-break */
#define    SIGABRT        22    /* Abnormal termination (abort) */

#define NSIG 23     /* maximum signal number + 1 */
View Code
static void sig_handler(int signum){
    switch(signum){
        case SIGUSR1:
           cout<<"SIGUSR1";
           stop();
           break;
        case SIGUSR2:
           cout<<"SIGUSR2";
           stop();
           break;
        case SIGTERM:
           cout<<"SIGTERM";
           stop();
           break;
    }  
    exit(0);
}

int main(){
    signal(SIGUSR1,sig_handler);
    signal(SIGUSR2,sig_handler);
    signal(SIGTERM,sig_handler);
    return 0;
}

库函数raise()或者系统调用kill()可以产生信号。raise()发送一个信号给当前进程,kill()发送一个信号给特定进程。

除了两个信号SIGKILL与SIGSTOP不能被捕获(caught)、阻塞(blocked)或者忽略,其它的信号都可以指定处理函数(handler)。一个信号的处理函数在信号到达时,被目标环境调用。目标环境挂起当前进程的执行,直到信号处理函数返回或者调用了longjmp()。为了最大的兼容性,异步信号处理只应:

  • 成功调用了signal()指定的函数;
  • 给类型为sig_atomic_t的对象赋值;
  • 把控制返回给它的调用者。

如果信号报告了进程的错误,信号处理函数应该调用abort()exit()longjmp()

kill():

头文件:#include <sys/types.h>   #include <signal.h>

定义函数:int kill(pid_t pid, int sig);

函数说明:kill()可以用来送参数sig 指定的信号给参数pid 指定的进程。参数pid 有几种情况:
1、pid>0 将信号传给进程识别码为pid 的进程.
2、pid=0 将信号传给和目前进程相同进程组的所有进程
3、pid=-1 将信号广播传送给系统内所有的进程
4、pid<0 将信号传给进程组识别码为pid 绝对值的所有进程参数 sig 代表的信号编号可参考附录D

返回值:执行成功则返回0, 如果有错误则返回-1.

错误代码:
1、EINVAL 参数sig 不合法
2、ESRCH 参数pid 所指定的进程或进程组不存在
3、EPERM 权限不够无法传送信号给指定进程

范例

#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
main()
{
    pid_t pid;
    int status;
    if(!(pid= fork()))
    {
        printf("Hi I am child process!\n");
        sleep(10);
        return;
    }
    else
    {
        printf("send signal to child process (%d) \n", pid);
        sleep(1);
        kill(pid, SIGABRT);
        wait(&status);
        if(WIFSIGNALED(status))
            printf("chile process receive signal %d\n", WTERMSIG(status));
    }
}

执行:
sen signal to child process(3170) Hi I am child process! child process receive
signal 6
View Code

 

推荐阅读