《UNIX网络编程:卷2》P81-P84:图5-17、5-18
--------------------------------------------
该程序先调用fork,子进程阻塞三种实时信号,父进程随后发送9个信号(三种实时信号每种3个),子进程接着解阻塞信号,我们于是看到每种信号各有多少个递交以及它们的先后递交顺序。
/* * test1.c * 图5-17 演示实时信号的简单测试程序 */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> #include <string.h> #include <errno.h> typedef void sigfunc_rt(int, siginfo_t *, void *); sigfunc_rt *signal_rt(int signo, sigfunc_rt *func, sigset_t *mask); static void sig_rt(int signo, siginfo_t *info, void *context); int main(int argc, char *argv[]) { int i, j; pid_t pid; sigset_t newset; union sigval val; // 输出最小和最大实时信号值 printf("SIGRTMIN = %d, SIGRTMAX = %d\n", SIGRTMIN, SIGRTMAX); // 派生一个子进程 if ((pid = fork()) < 0) { fprintf(stderr, "fock error %s\n", strerror(errno)); exit(1); } else if (pid == 0) { // 子进程 sigemptyset(&newset); // 初始化信号集 sigaddset(&newset, SIGRTMAX); // 添加三种实时信号 sigaddset(&newset, SIGRTMAX - 1); sigaddset(&newset, SIGRTMAX - 2); sigprocmask(SIG_BLOCK, &newset, NULL); // 阻塞这三种实时信号 // 建立三种实时信号的处理程序 signal_rt(SIGRTMAX , sig_rt, &newset); signal_rt(SIGRTMAX - 1, sig_rt, &newset); signal_rt(SIGRTMAX - 2, sig_rt, &newset); sleep(6); // 等待6秒,以允许父进程产生信号 sigprocmask(SIG_UNBLOCK, &newset, NULL); // 为这三种实时信号的解除阻塞 sleep(3); // 等待3秒,以便信号处理程序调用printf函数9次 exit(0); } // 父进程 sleep(3); // 等待3秒,以便子进程阻塞所有信号 // 为三种实时信号各产生3个信号 for (i = SIGRTMAX; i >= SIGRTMAX - 2; i--) { for (j = 0; j <= 2; j++) { val.sival_int = j; // 同种信号伴随不同整数 sigqueue(pid, i, val); // 向指定进程发送信号,携带不同整数 printf("sent signal %d, val = %d\n", i, j); } } exit(0); } static void sig_rt(int signo, siginfo_t *info, void *context) { printf("received signal #%d, code = %d, ival = %d\n", signo, info->si_code, info->si_value.sival_int); } /* * signal_rt.c * P84 图5-18 提供实时行为的signal_rt函数 */ sigfunc_rt *signal_rt(int signo, sigfunc_rt *func, sigset_t *mask) { struct sigaction act, oact; act.sa_sigaction = func; // 信号处理程序地址 act.sa_mask = *mask; // 执行信号处理程序时阻塞的信号集 act.sa_flags = SA_SIGINFO; // 实时信号必须指定的标志 if (signo == SIGALRM) { #ifdef SA_INTERRUPT act.sa_flags |= SA_INTERRUPT; #endif } else { #ifdef SA_RESTART act.sa_flags |= SA_RESTART; #endif } // 信号与信号动作关联 if (sigaction(signo, &act, &oact) < 0) return((sigfunc_rt *)SIG_ERR); return(oact.sa_sigaction); }
运行程序:
$ ./test1 SIGRTMIN = 34, SIGRTMAX = 64 sent signal 64, val = 0 sent signal 64, val = 1 sent signal 64, val = 2 sent signal 63, val = 0 sent signal 63, val = 1 sent signal 63, val = 2 sent signal 62, val = 0 sent signal 62, val = 1 sent signal 62, val = 2 $ received signal #62, code = -1, ival = 0 父进程终止,shell提示符输出 received signal #62, code = -1, ival = 1 received signal #62, code = -1, ival = 2 received signal #63, code = -1, ival = 0 received signal #63, code = -1, ival = 1 received signal #63, code = -1, ival = 2 received signal #64, code = -1, ival = 0 received signal #64, code = -1, ival = 1 received signal #64, code = -1, ival = 2
父进程发送的9个信号排队后按我们期待的顺序递交:值最小的信号最先递交。对于一种给定信号,它的三次发送按FIFO顺序递交。