APUE信号-程序汇总
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... "); if (sigprocmask(SIG_SETMASK, &savemask, NULL) < 0) return(-1); return(status); }
程序清单10-21 sleep 的可靠实现