带参的信号发送与捕获
-
可以让不同进程之间发送信号时,带上一些简易数据,完成不同进程之间简单通信,这叫带参数的信号发送
#include <signal.h> int sigaction (int signum, const struct sigaction* act,struct sigaction* oldact); 功能:设置信号的处理方案 signum:信号码 act:信号处理方式 oldact:原信号处理方式,可为NULL struct sigaction { void (*sa_handler)(int); // 信号处理函数指针1 void (*sa_sigaction)(int,siginfo_t*,void*); // 信号处理函数指针2 带附加数据 sigset_t sa_mask; // 信号掩码 //在信号函数函数执行过程中,默认屏蔽当前信号,如果想屏蔽其它信号可以向sa_mask中添加 int sa_flags; // 信号处理标志 void (*sa_restorer)(void); // 保留,NULL }; sa_flags可为以下值的位或: SA_ONESHOT/SA_RESETHAND 执行完一次信号处理后,即对此信号的处理恢复为默认,这也是老版本signal函数的缺省行为。 SA_NODEFER/SA_NOMASK 在信号处理函数的执行过程中,不屏蔽这个正在被处理的信号。 SA_NOCLDSTOP 若signum参数取SIGCHLD,则当子进程暂停时,不通知父进程。 SA_RESTART 系统调用一旦被signum参数所表示的信号中断,会自行重启。 SA_SIGINFO 使用信号处理函数指针2,通过该函数的第二个参数,提供更多信息。 typedef struct siginfo { pid_t si_pid; // 发送信号的PID sigval_t si_value; // 信号附加值(需要配合sigqueue函数) ... }siginfo_t; typedef union sigval { int sival_int; 整数 void* sival_ptr; 指针 }sigval_t; int sigqueue (pid_t pid, int sig,const union sigval value); 功能:向pid进程发送sig信号,附加value值(整数或指针)。
在默认情况下,在信号处理函数的执行过程中,会自动屏蔽这个正在被处理的信号,而对于其它信号则不会屏蔽,通过sigaction::sa_mask成员可以人为指定。 在信号处理函数的执行过程中,需要加入进程信号掩码中的信号,并在信号处理函数执行完之后,自动解除对这些信号的屏蔽。
// 进程A #include <stdio.h> #include <unistd.h> #include <signal.h> void sigint1 (int signum) { printf ("收到SIGINT信号!睡眠中...\n"); sleep (3); printf ("睡醒了。\n"); } void sigint2 (int signum, siginfo_t* si, void* pv) { printf ("收到发自%u进程的SIGINT信号!\n", si -> si_pid); printf("附加的数据是:%d\n",si->si_value.sival_int); //printf("%s\n",si->si_value.sival_ptr); } int main () { printf("我是进程%u\n",getpid()); struct sigaction act = {}; act.sa_handler = sigint1; act.sa_sigaction = sigint2; act.sa_flags = SA_SIGINFO; sigaction (SIGINT, &act, NULL); for (;;) pause (); return 0; }
// 进程B 给进程A发送附带数据的信号 #include <sys/wait.h> int main (void) { pid_t pid; printf("请输入进程号:"); scanf("%u",&pid); sigval_t sv; sv.sival_int = 6666; // sv.sival_ptr = "hehehe"; if (sigqueue (pid, SIGINT, sv) == -1) { perror ("sigqueue"); return -1; } return 0; }