在第三篇笔记中提到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_sigaction是一个比较复杂的函数类型,可以在收信号的同时还能接收参数。
在结构体中还有个sa_flags的变量,在这个标志位中有一个参数SA_SIGINFO的作用是使用扩展信号响应函数而不是标准响应函数,也就是说想使用sa_sigaction时需要将sa_flags置为SA_SIGINFO,否则默认还是使用sa_handler函数。
使用man sigqueue查看sigqueue函数的原型如下:
int sigqueue(pid_t pid, int sig, const union sigval value)
该函数需要三个参数,相比kill函数的pid和sig以外还多了一个sigval的联合体,该联合体用于保存所要传递信息。
union sigval {
int sival_int;
void *sival_ptr;
};
所以第三个参数sigval在调用函数传参时不能直接将int类型的数字填入其中,而是需要定义一个sigval类型的变量,并赋值,然后再将该变量填入函数的参数中。
sa_sigaction 那么sa_sigaction这个函数会将接收到的数据存入siginfo的结构体中。那么第三个参数在LINUX中给出的解释如下 (百度翻译可能不是很通顺) :
是指向ucontext_t结构的指针,强制转换为void* 。该字段指向的结构包含内核保存在用户空间堆栈上的信号上下文信息;有关详细信息,请参见SIGROUNT(2)。关于ucontext_t结构的更多信息可以在getcontext(3)中找到。通常, 处理函数不使用第三个参数 。
(*sa_sigaction)(int, siginfo_t *, void *);siginfo_t结构体
查看siginfo_t结构体中的内容如下:
siginfo_t {
int si_signo;
int si_errno;
int si_code;
int si_trapno;
pid_t si_pid;
uid_t si_uid;
int si_status;
clock_t si_utime;
clock_t si_stime;
sigval_t si_value;
int si_int;
void *si_ptr;
int si_overrun;
int si_timerid;
void *si_addr;
long si_band;
int si_fd;
short si_addr_lsb;
void *si_lower;
void *si_upper;
int si_pkey;
void *si_call_addr;
int si_syscall;
unsigned int si_arch;
}
sigval传来的参数存放在其中si_int和si_ptr中,如果我传了整型,那就使用si_int即可。
测试代码 那么 (sigqueue()这个函数能不能在终端使用啊,有明白的教教我) 只能用接收程序先输出进程号,再将该进程号输入到发送程序中,发送程序向该进程号发送15信号,并附带一个12138的数据,接收程序的处理函数在接收到15信号时会输出信号值,以及info中的si_int值。
接收程序:
#include#include #include #include #include void handle(int sig,siginfo_t* info,void* arg) { printf("receive signal %d. with information:%dn",sig,info->si_int); } int main() { struct sigaction sigact; printf("%dn",getpid()); memset(&sigact,0,sizeof(sigact)); sigact.sa_sigaction=handle; sigact.sa_flags=SA_SIGINFO; sigaction(15,&sigact,NULL); pause(); }
发送程序:
#include#include #include #include #include int main() { pid_t pid; scanf("%d",&pid); union sigval info; info.sival_int=12138; sigqueue(pid,15,info); }
输出结果如下:
~$ ./demo_11_recv 3626 receive signal 15. with information:12138ps
在sigval中还有个成员是sival_ptr,这是个指针,但是由于内存保护的原因,进程是没办法访问操作系统分配以外的空间,所以也就没办法访问发送方所发送的地址,不过这个问题可以进程之间只用共享内存来解决 (这个坑等我学明白了再填) 。



