介绍sigqueue()
#include <sys/types.h>
#include <signal.h>
int sigqueue(pid_t pid, int sig, const union sigval val)
调用成功返回 0;否则,返回 -1。

sigqueue()是比较新的发送信号系统调用,主要是针对实时信号提出的(当然也支持前32种),支持信号带有参数,与函数sigaction()配合使用。

sigqueue的第一个参数是指定接收信号的进程ID,第二个参数确定即将发送的信号,第三个参数是一个联合数据结构union sigval,指定了信号传递的参数,即通常所说的4字节值。

 


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

sigqueue()比kill()传递了更多的附加信息,但sigqueue()只能向一个进程发送信号,而不能发送信号给一个进程组。如果 signo=0,将会执行错误检查,但实际上不发送任何信号,0值信号可用于检查pid的有效性以及当前进程是否有权限向目标进程发送信号。

在调用sigqueue时,sigval_t指定的信息会拷贝到3参数信号处理函数(3参数信号处理函数指的是信号处理函数由sigaction安 装,并设定了sa_sigaction指针,稍后将阐述)的siginfo_t结构中,这样信号处理函数就可以处理这些信息了。由于sigqueue系统 调用支持发送带参数信号,所以比kill()系统调用的功能要灵活和强大得多。

注:sigqueue()发送非实时信号时,第三个参数包含的信息仍然能够传递给信号处理函数; sigqueue()发送非实时信号时,仍然不支持排队,即在信号处理函数执行过程中到来的所有相同信号,都被合并为一个信号

 

 

实例:

头文件:apue.h

#ifndef _APUE_H_
#define _APUE_H_

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <assert.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <errno.h>
#include <dirent.h>
#include <signal.h>

void err_exit(char *m){
        perror(m);
        exit(EXIT_FAILURE);
}

#endif /* _APUE_H_ */

 

接收sigqueue函数发送信号的程序recv.c

#include "./apue.h"


void sighandler(int sig, siginfo_t *info, void *ctx){
        printf("sig=%d,data=%d\n", sig, info->si_value.sival_int);

}

int main(int argc, char *argv[]){
        struct sigaction act;
        act.sa_sigaction=sighandler;
        sigemptyset(&act.sa_mask);
        act.sa_flags=SA_SIGINFO;
        if(sigaction(SIGINT, &act, NULL)<0){
                err_exit("sigaction error");
        }
        for(;;)
                pause();
        return 0;

}

发送信号的程序send.c

#include "./apue.h"

int main(int argc, char *argv[]){
        if(argc != 2){
                fprintf(stderr, "usage: ./%s pid\n", argv[0]);
        }
        pid_t pid=atoi(argv[1]);
        union sigval v;
        v.sival_int=100;
        sigqueue(pid, SIGINT, v);
        return 0;
}

 

 

在一个窗口执行./recv

再开一个窗口执行./send pid(pid为./recv的进程号)

输出如下:

sig=2,data=100