读书笔记:第5章 Posix消息队列 (10)

《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顺序递交。

你可能感兴趣的:(读书笔记,《UNIX网络编程》)