linux信号:signal和sigaction

目录

1、signal

2、sigaction


1、signal

signal()函数声明如下: 

/* Type of a signal handler.  */
typedef void (*__sighandler_t) (int);
/* Set the handler for the signal SIG to HANDLER, returning the old
   handler, or SIG_ERR on error.
   By default `signal' has the BSD semantic.  */
__BEGIN_NAMESPACE_STD
#ifdef __USE_MISC
extern __sighandler_t signal (int __sig, __sighandler_t __handler)
     __THROW;
#else

__sighandler_t是一个函数指针 ,signal函数的功能就是为信号__sig注册处理函数,函数的指针为__handler。

/*================================================================
*   Copyright (C) 2021 baichao All rights reserved.
*
*   文件名称:Signal.cpp
*   创 建 者:baichao
*   创建日期:2021年02月10日
*   描    述:
*
================================================================*/

#include <iostream>
#include <signal.h>
#include <unistd.h>

void do_handler(int _signal)
{
    if(_signal == SIGIO)
        std::cout<<"SIGIO"<<std::endl;
    else if(_signal == SIGUSR1)
        std::cout<<"SIGUSR1"<<std::endl;
    else if(_signal == SIGUSR2)
        std::cout<<"SIGUSR2"<<std::endl;
    else
        std::cout<<"啥也不是"<<std::endl;
}

int main()
{
    signal(SIGIO,do_handler);
    signal(SIGUSR2,do_handler);
    signal(SIGUSR1,do_handler);
    std::cout<<SIGIO<<std::endl;
    std::cout<<SIGUSR1<<std::endl;
    std::cout<<SIGUSR2<<std::endl;
    while(1)
        sleep(1);

    return 0;
}

 

通过kill发送信号到对应进程。 

2、sigaction

siginfo_t结构体定义如下:

/*/usr/include/x86_64-linux-gnu/bits/siginfo.h*/
typedef struct
{
    int si_signo;     /* Signal number.  */
    int si_errno;     /* If non-zero, an errno value associated with
                         this signal, as defined in <errno.h>.  */
    int si_code;      /* Signal code.  */

    union
    {
        int _pad[__SI_PAD_SIZE];

        /* kill().  */
        struct
        {
            __pid_t si_pid; /* Sending process ID.  */
            __uid_t si_uid; /* Real user ID of sending process.  */
        } _kill;

        /* POSIX.1b timers.  */
        struct
        {
            int si_tid;     /* Timer ID.  */
            int si_overrun; /* Overrun count.  */
            sigval_t si_sigval; /* Signal value.  */
        } _timer;

        /* POSIX.1b signals.  */
        struct
        {
            __pid_t si_pid; /* Sending process ID.  */
            __uid_t si_uid; /* Real user ID of sending process.  */
            sigval_t si_sigval; /* Signal value.  */
        } _rt;

        /* SIGCHLD.  */
        struct
        {
            __pid_t si_pid; /* Which child.  */
            __uid_t si_uid; /* Real user ID of sending process.  */
            int si_status;  /* Exit value or signal.  */
            __sigchld_clock_t si_utime;
            __sigchld_clock_t si_stime;
        } _sigchld;

        /* SIGILL, SIGFPE, SIGSEGV, SIGBUS.  */
        struct
        {
            void *si_addr;  /* Faulting insn/memory ref.  */
            short int si_addr_lsb;  /* Valid LSB of the reported address.  */
            struct
            {
                void *_lower;
                void *_upper;
            } si_addr_bnd;
        } _sigfault;

        /* SIGPOLL.  */
        struct
        {
            long int si_band;   /* Band event for SIGPOLL.  */
            int si_fd;
        } _sigpoll;

        /* SIGSYS.  */
        struct
        {
            void *_call_addr;   /* Calling user insn.  */
            int _syscall;   /* Triggering system call number.  */
            unsigned int _arch; /* AUDIT_ARCH_* of syscall.  */
        } _sigsys;
    } _sifields;
} siginfo_t __SI_ALIGNMENT;

sigaction声明如下: 

/*/usr/include/x86_64-linux-gnu/bits/sigaction.h*/
/* Structure describing the action to be taken when a signal arrives.  */
struct sigaction
  {
    /* Signal handler.  */
#ifdef __USE_POSIX199309
    union
      {
        /* Used if SA_SIGINFO is not set.  */
        __sighandler_t sa_handler;
        /* Used if SA_SIGINFO is set.  */
        void (*sa_sigaction) (int, siginfo_t *, void *);
      }
    __sigaction_handler;
# define sa_handler     __sigaction_handler.sa_handler
# define sa_sigaction   __sigaction_handler.sa_sigaction
#else
    __sighandler_t sa_handler;
#endif

    /* Additional set of signals to be blocked。就是当处理当前__sig信号时暂时将sa_mask指定的一组信号阻塞  */
    __sigset_t sa_mask;

    /* Special flags. 
    sa_flags用来设置信号处理的其他相关操作,下列的数值可用:
      A_NOCLDSTOP:如果参数signum为SIGHLD,则当前子进程暂停时并不会通知父进程
      SA_ONESHOT/SA_RESETHAND:当调用新的信号处理函数前,将此信号处理方式改为系统预设的方式
      SA_RESTART:被信号中断的系统调用会自行重启
      SA_NOMASK/SA_NODEFER:在处理此信号未结束前不理会此信号的再次到来,如果参数oldact不是NULL指针,则原来的信号处理方式会由此结构sigaction返回。
    */
    int sa_flags;

    /* Restore handler.  */
    void (*sa_restorer) (void);
  };


/*/usr/include/signal.h*/
/* Get and/or set the action for signal SIG. success return 1,else 0. */
/*__sig参数指出要捕获的信号类型,__restrict __act参数指定新的信号处理方式,__restrict __oact参数输出先前信号的处理方式(如果不为NULL的话)*/
extern int sigaction (int __sig, const struct sigaction *__restrict __act,
                      struct sigaction *__restrict __oact) __THROW;

 如果需要携带信息(即siginfo_t的指针有值)则使用sa_sigaction,否则使用sa_handler。

示例代码:

/*================================================================
 *   Copyright (C) 2021 baichao All rights reserved.
 *
 *   文件名称:Sigaction.cpp
 *   创 建 者:baichao
 *   创建日期:2021年02月15日
 *   描    述:
 *
 ================================================================*/

#include <iostream>
#include <signal.h>
#include <unistd.h>
#include <cstring>

void do_handler(int _signal, siginfo_t *act,void *context)
{
   std::cout<<"信号编号为:"<<_signal<<std::endl;
   std::cout<<"sigaction.si_signo:"<<act->si_signo<<std::endl;
   std::cout<<"sigaction.si_code:"<<act->si_code<<std::endl;
   std::cout<<*(std::string*)context<<std::endl;
}

int main()
{
    struct sigaction act,oldact;
    act.sa_sigaction = do_handler;
    act.sa_flags = SA_ONESHOT|SA_NOMASK;
    sigaction(SIGUSR1,&act,&oldact);
    while(1)
        sleep(1);
}

 

猜你喜欢

转载自blog.csdn.net/weixin_40179091/article/details/113780105