APUE信号-程序汇总
近期重看APUE,发现对于非常多程序的要领还是没有全然理解。所以梳理下便于查看,并且有非常多值得思考的问题。
程序清单10- 1 捕获 SIGUSR1 和 SIGUSR2的简单程序
程序清单10- 2 在信号处理程序中调用不可重入函数
程序清单10- 3 SIGCLD处理程序(在Linux下等价于SIGCHLD)
程序清单10- 4 sleep 的简单而不完整的实现
#include<signal.h>
#include<unistd.h>
/**存在的问题是。可能在一个繁忙的系统中调用pause之前超时,
* 直接调用信号处理程序。pause后假设没有捕捉到其它信号,
* 该程序将永远被挂起
*/
static void
sig_alrm(int signo)
{
/* nothing to d o, just return to wake up the pause */
}
unsigned int
sleep1(unsigned int nsecs)
{
if (signal(SIGALRM, sig_alrm) == SIG_ERR)
return(nsecs);
alarm(nsecs);/* start the timer */
pause();/* next caught signal wakes us up */
return(alarm(0));/* turn off timer, return unslept time */
}
程序清单10- 5 sleep 的还有一个(不完好)实现
#include<setjmp.h>
#include<signal.h>
#include<unistd.h>
static jmp_buf env_alrm;
static void
sig_alrm(int signo)
{
longjmp(env_alrm, 1);
}
unsigned int
sleep2(unsigned int nsecs)
{
if (signal(SIGALRM, sig_alrm) == SIG_ERR)
return(nsecs);
if(setjmp(env_alrm) == 0){
alarm(nsecs);/* start the timer */
pause();/* next caught signal wakes us up */
}
return(alarm(0));/* turn off timer, return unslept time */
}
程序清单10- 6 在一个捕获其它信号的程序中调用sleep2
程序清单10- 7 具有超时限制的read调用
程序清单10- 8 使用longjmp。带超时限制,调用read
程序清单10- 9 sigaddset,sigdelset,sigismember的实现(假定信号集合是整型)
#include<signal.h>
#include<errno.h>
/**
* 如果把 sigset_t 视为整数。各种位操作
*/
/* <signal.h> usually defines NSIG to include signa l number 0 */
#define SIGBAD(signo)((signo) <= 0 || (signo) >= NSIG)
int sigaddset(sigset_t *set, int signo)
{
if (SIGBAD(signo)) { errno = EINVAL; return(-1); }
*set |= 1 << (signo - 1);/* turn bit on */
return(0);
}
int
sigdelset(sigset_t *set, int signo)
{
if (SIGBAD(signo)) { errno = EINVAL; return(-1); }
*set &= ~(1 << (signo - 1));/* turn bit off */
retur n(0);
}
int
sigismember(const sigset_t *set, int signo)
{
if (SIGBAD(signo)) { errno = EINVAL; return(-1); }
return((*set & (1 << (signo - 1))) != 0);
}程序清单10-10 为进程打印信号屏蔽字
程序清单10-11 信号设置和 sigpromask 实例
程序清单10-12 用 sigaction 实现的 signal 函数
程序清单10-13 阻止不论什么被中断系统调用重新启动动的的 signal 函数
程序清单10-14 信号屏蔽字,sigsetjmp。siglongjmp 实例
程序清单10-15 保护临界区不被信号中断
程序清单10-16 用sigsuspend等待一个全局变量被设置
程序清单10-17 父子进程能够用来实现同步的例程(TELL_WAIT)
程序清单10-18 abort 的 POSIX.1 实现
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void
abort(void) /* POSIX-style abort() function */
{
sigset_t mask;
struct sigaction action;
/*
* * Caller can't ignore SIGABRT, i f so reset to default.
* * */
sigaction(SIGABRT, NULL, &action);
if (action.sa_handler == SIG_IGN) {
action.sa_handler = SIG_DFL;
sigaction(SIGABRT, &action, NULL);
}
if (action.sa_handler == SIG_DFL)
fflush(NULL);/* flush all open stdio streams */
/*
* * * Caller can't block SIGA BRT; make sure it's unblocked.
* * */
sigfillset(&mask);
igdelset(&mask, SIGABRT);/* mask has only SIGABRT turned off */
sigprocmask(SIG_SETMASK, &mask, NULL);
kill(getpid(), SIGABRT);/* send the signal */
/*
* * * If we're here, p rocess caught SIGABRT and returned.
* * */
fflush(NULL);/* flush all open stdio streams */
action.sa_handler = SIG_DFL;
sigaction(SIGABRT, &action, NULL);/* reset to default */
igprocmask(SIG_SETMASK, &mask, NU LL);/* just in case ... */
kill(getpid(), SIGABRT);/* and one mor e time */
exit(1);/* this should never be executed ... */
}
程序清单10-19 用 system 调用 ed 编辑器
程序清单10-20 system 函数的 POSIX.1 正确实现
#include<sys/wait.h>
#include<errno.h>
#include<signal.h>
#include<unistd.h>
#include <stdio.h>
int
system( const char *cmdstring)/* with appropriate signal handling */
{
pid_t pid;
int status;
struct sigaction ignore, saveintr, savequit;
sigset_t chldmask, savemask;
if (cmdstring == NULL)
return(1); /* always a command processor with UNIX */
ignore.sa_handler = SIG_IGN;/* ignore SIGINT and SIGQUIT */
sigemptyset(&ignore.sa_mask);
ignore.sa_flags = 0;
if (sigaction(SIGINT, &ignore, &saveintr) < 0)
return(-1);
if (sigaction(SIGQUIT, &ignore, &savequit) < 0)
return(-1);
sigemptyset(&chldmask);/* now block SIGCHLD */
sigaddset(&chldmask, SIGCHLD);
if(sigprocmask(SIG_BLOCK, &chldmask, &savemask) < 0)
return(-1);
if ((pid = fork()) < 0) {
status = -1;/* probably out of processes */
} else if (pid == 0) {/* child */
/* restore previous signal actions & reset signal ma sk */
sigaction(SIGINT, &saveintr, NULL);
sigaction(SIGQUIT, &savequit, NULL);
sigprocmask(SIG_SETMASK, &savemask, NULL);
execl("/bin/sh", "sh", "-c", cmdstring, (char *)0);
_exit(127);/* exec error */
} else { /* parent */
while (waitpid(pid, &status, 0) < 0)
if (errno != EINTR) {
status = -1; /* error other than EINTR from waitpid() */
break;
}
}
/* restore previous signal actions & reset signal mask */
if (sigaction(SIGINT, &saveintr, NULL) < 0)
return(-1);
if (sigaction(SIGQUIT, &savequit, NULL) < 0)
return(-1);
printf("before unblock SIGCHLD...\n");
if (sigprocmask(SIG_SETMASK, &savemask, NULL) < 0)
return(-1);
return(status);
}
程序清单10-21 sleep 的可靠实现