信号的使用

注册信号

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

功能:用于改变进程接收到特定信号后的行为。
参数:signum 除了SIGKILL 和SIGSTOP(为这两个信号定义自己的处理函数,将导致信号安装错误);
第二个参数是指向结构sigaction的一个实例的指针,在结构sigaction的实例中,制定了对特定信号的处理,可以为空,进程会以缺省方式对信号处理;
old用来保存原来对信号的处理,可以为NULL。
返回值:成功为0,失败-1

结构体sigaction

struct sigaction {
               void     (*sa_handler)(int);
               void     (*sa_sigaction)(int, siginfo_t *, void *);
               sigset_t   sa_mask;
               int        sa_flags;
               void     (*sa_restorer)(void);
           };

前两个参数sa_handler和sa_sigaction都是自定义信号处理函数,同样,sa_handler有两个默认值:SIG_DFL和SIG_IGN。区别在于sa_sigaction是为实时信号而设定的(也支持非实时信号),第二个参数是指向siginfo_t结构的指针,结构中包含信号携带的数据值,第三个参数暂时没有使用(POSIX没有规范使用该指针的标准)。

sa_flags有以下几个值:

           SA_NOCLDSTOP
                  If signum is SIGCHLD, do not receive notification when child processes stop (i.e., when they receive one of SIGSTOP, SIGTSTP, SIGTTIN, or SIGTTOU) or  resume  (i.e.,  they  receive
                  SIGCONT) (see wait(2)).  This flag is meaningful only when establishing a handler for SIGCHLD.

           SA_NOCLDWAIT (since Linux 2.6)
                  If  signum  is  SIGCHLD, do not transform children into zombies when they terminate.  See also waitpid(2).  This flag is meaningful only when establishing a handler for SIGCHLD, or
                  when setting that signal's disposition to SIG_DFL.

                  If the SA_NOCLDWAIT flag is set when establishing a handler for SIGCHLD, POSIX.1 leaves it unspecified whether a SIGCHLD signal is generated when a child  process  terminates.   On
                  Linux, a SIGCHLD signal is generated in this case; on some other implementations, it is not.

           SA_NODEFER
                  Do  not prevent the signal from being received from within its own signal handler.  This flag is meaningful only when establishing a signal handler.  SA_NOMASK is an obsolete, non‐
                  standard synonym for this flag.

           SA_ONSTACK
                  Call the signal handler on an alternate signal stack provided by sigaltstack(2).  If an alternate stack is not available, the default stack will be used.  This flag  is  meaningful
                  only when establishing a signal handler.

           SA_RESETHAND
                  Restore the signal action to the default upon entry to the signal handler.  This flag is meaningful only when establishing a signal handler.  SA_ONESHOT is an obsolete, nonstandard
                  synonym for this flag.

           SA_RESTART
                  Provide behavior compatible with BSD signal semantics by making certain system calls restartable across signals.  This flag is meaningful only when establishing a  signal  handler.
                  See signal(7) for a discussion of system call restarting.

           SA_RESTORER
                  Not intended for application use.  This flag is used by C libraries to indicate that the sa_restorer field contains the address of a "signal trampoline".  See sigreturn(2) for more
                  details.

           SA_SIGINFO (since Linux 2.2)
                  The signal handler takes three arguments, not one.  In this case, sa_sigaction should be set instead of sa_handler.  This flag is meaningful only when establishing  a  signal  han‐
                  dler.

重点掌握2个:一个是设置为0,表示默认属性;一个是设置为SA_SIGINFO,那么此时处理函数不再使用sa_handler,而是sa_sigaction.
那么sa_sigaction的结构体参数长什么样呢?

           siginfo_t {
               int      si_signo;    /* Signal number */
               int      si_errno;    /* An errno value */
               int      si_code;     /* Signal code */
               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 */
               void    *si_addr;     /* Memory location which caused fault */

天哪,肯定记不住。不需要记,用到的时候,查一下就好了。
这里掌握两个,一个是si_signum,不用说了吧,一个是si_value。这是什么?这是在发送信号时携带的一个数据,数据类是sigval,这是一个联合体。

typedef union sigval
 { 
    int sival_int; 
    void *sival_ptr; 
}sigval_t;

sigqueue函数

  #include < signal.h>
  int sigqueue(pid_t pid, int sig, const union sigval value);

sigqueue()类似于之前的kill()。是用来发送信号的,主要针对有带参的信号,与sigaction()配合使用。
第三个参数是一个联合数据结构union sigval,指定了信号传递的参数,即通常所说的4字节值。
具体代码如下:

#include <signal.h>                                                                
                                                                                   
void handler(int signo,siginfo_t *resdata,void *unknowp)                           
{                                                                                  
    printf("signo=%d\n",signo);                                                    
    printf("return data :%d\n",resdata->si_value.sival_int);                       
}                                                                                  
                                                                                   
int main()                                                                         
{                                                                                  
    int i = 5;                                                                     
    pid_t pid = 0;                                                                 
    pid = fork();                                                                  
    if(pid == -1)                                                                  
    {                                                                              
        perror("create fork");                                                     
        return -1;                                                                 
    }                                                                              
    else if(pid == 0)                                                              
    {                                                                              
        sleep(1);                                                                  
        //向父进程发送带整型数据的信号                                             
        union sigval sigvalue;                                                     
        sigvalue.sival_int = 111;                                                  
        //发送信号                                                                 
            sigqueue(getppid(),2,sigvalue);                                        
            printf("send signal:2 success!\n");                                    
            sigqueue(getppid(),34,sigvalue);                                       
            printf("send signal:34 success!\n");                                   
                                                                                   
    }                                                                              
    else                                                                           
    {                                                                              
                                                                                   
        struct sigaction act;                                                      
        //初始化sa_mask                                                            
        sigemptyset(&act.sa_mask);                                                 
        act.sa_sigaction=handler;                                                  
        //一旦使用了sa_sigaction属性,那么必须设置sa_flags属性的值为SA_SIGINFO  
        act.sa_flags=SA_SIGINFO;                                                   
                                                                                   
        //注册信号                                                                 
        sigaction(2,&act,NULL);                                                    
        sigaction(34,&act,NULL);                                                   
                                                                                   
    }                                                                              
                                                                                   
    while(1)                                                                       
    {                                                                              
    }                                                                              
}   

运行结果:

tom@tom-linuxer:~$ ./test4 
signo=2
return data :111
send signal:2 success!
send signal:34 success!
signo=34
return data :111
^Z
[3]+  已停止               ./test4

发送信号

发布了112 篇原创文章 · 获赞 7 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/chengbeng1745/article/details/102308486