首页 > 代码库 > APUE信号-程序汇总
APUE信号-程序汇总
APUE信号-程序汇总
最近重看APUE,发现对于很多程序的要领还是没有完全理解,所以梳理下便于查看,而且有很多值得思考的问题。
程序清单10- 1 捕获 SIGUSR1 和 SIGUSR2的简单程序
#include "util.h" static void sig_usr(int); int main(void){ if(signal(SIGUSR1,sig_usr) == SIG_ERR) err_sys("cannot catch SIGUSR1!"); if(signal(SIGUSR2,sig_usr) == SIG_ERR) err_sys("cannot catch SIGUSR2!"); for(;;) pause(); } static void sig_usr(int signo){ if(signo == SIGUSR1) printf("received SIGUSR1\n"); else if(signo == SIGUSR2) printf("received SIGUSR2\n"); else err_dump("received signal %d\n",signo); }
程序清单10- 2 在信号处理程序中调用不可重入函数
#include "util.h" #include <pwd.h> static void my_alarm(int signo){ struct passwd*rootptr; printf("in signal handler\n"); if ((rootptr = getpwnam("de15")) == NULL) err_sys("getpwnam(de15) error"); alarm(1); } int main(void){ struct passwd*ptr; signal(SIGALRM, my_alarm); alarm(1); for ( ; ; ) { if ((ptr = getpwnam("vonzhou")) == NULL) err_sys("getpwnam error"); if (strcmp(ptr->pw_name, "vonzhou") != 0) printf("return value corrupted!, pw_name = %s\n", ptr->pw_name); } }
程序清单10- 3 SIGCLD处理程序(在Linux下等价于SIGCHLD)
#include"util.h" #include<sys/wait.h> static void sig_cld(int); int main() { pid_t pid; if (signal(SIGCLD, sig_cld) == SIG_ERR) perror("signal error"); if ((pid = fork()) < 0) { perror("fork error"); } else if (pid == 0) {/* child */ sleep(2); _exit(0); } pause();/* parent */ exit(0); } static void sig_cld(int signo)/* interrupts pause() */ { pid_t pid; int status; printf("SIGCLD received\n"); if (signal(SIGCLD, sig_cld) == SIG_ERR)/* reestablish handler */ perror("signal error" ); if ((pid = wait(&status)) < 0)/* fetch child status */ perror("wait error"); printf("pid = %d\n", pid); }
程序清单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
#include "util.h" unsigned int sleep2(unsigned int); static void sig_int(int); int main(void) { unsigned int unslept; if (signal(SIGINT, sig_int) == SIG_ERR) err_sys("signal(SIGINT) error"); unslept = sleep2(5); printf("sleep2 returned: %u\n", unslept); exit(0); } static void sig_int(int signo) { int i, j; volatile int k; /* * Tune these loops to run for more than 5 seconds * on whatever system this test program is run. */ printf("\nsig_int starting\n"); for (i = 0; i < 300000; i++) for (j = 0; j < 4000; j++) k += i * j; printf("sig_int finished\n"); } /* vonzhou@de15:~/Coding/apue/signals$ ./a.out ^C sig_int starting sleep2 returned: 0 vonzhou@de15:~/Coding/apue/signals$ */
程序清单10- 7 具有超时限制的read调用
#include "util.h" static void sig_alrm(int); int main(void) { int n; char line[MAXLINE]; if (signal(SIGALRM, sig_alrm) == SIG_ERR) err_sys("signal(SIGALRM) error"); alarm(10); if ((n = read(STDIN_FILENO, line, MAXLINE)) < 0) err_sys("read error"); alarm(0); write(STDOUT_FILENO, line, n); exit(0); } static void sig_alrm(int signo) { /* nothing to do, just return to interrupt the read */ } /* vonzhou@de15:~/Coding/apue/signals$ ./a.out read error: Interrupted system call (如果长时间不输入,则发现系统调用被中断) vonzhou@de15:~/Coding/apue/signals$ ./a.out oewutjowerjtlewrt oewutjowerjtlewrt vonzhou@de15:~/Coding/apue/signals$ */
程序清单10- 8 使用longjmp,带超时限制,调用read
#include "util.h" #include <setjmp.h> static void sig_alrm(int); static jmp_buf env_alrm; int main(void) { int n; char line[MAXLINE]; if (signal(SIGALRM, sig_alrm) == SIG_ERR) err_sys("signal(SIGALRM) error"); if (setjmp(env_alrm) != 0) err_quit("read timeout"); alarm(10); if ((n = read(STDIN_FILENO, line, MAXLINE)) < 0) err_sys("read error"); alarm(0); write(STDOUT_FILENO, line, n); exit(0); } static void sig_alrm(int signo) { longjmp(env_alrm, 1); }
程序清单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 为进程打印信号屏蔽字
#include "util.h" #include<errno.h> void pr_mask(const char *str){ sigset_t sigset; int errno_save; errno_save = errno; if(sigprocmask(0, NULL, &sigset) < 0) err_sys("sigpromask failed."); printf("%s",str); if(sigismember(&sigset, SIGINT)) printf("SIGINT "); if(sigismember(&sigset, SIGQUIT)) printf("SIGQUIT "); if(sigismember(&sigset, SIGUSR1)) printf("SIGUSR1 "); if(sigismember(&sigset, SIGALRM)) printf("SIGARM "); //remaining signals can get here. printf("\n"); errno = errno_save; }
程序清单10-11 信号设置和 sigpromask 实例
#include "util.h" static void sig_quit(int); int main(void) { sigset_t newmask, oldmask, pendmask; if (signal(SIGQUIT, sig_quit) == SIG_ERR) err_sys("can't catch SIGQUIT"); /* * Block SIGQUIT and save current signal mask. */ sigemptyset(&newmask); sigaddset(&newmask, SIGQUIT); if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) err_sys("SIG_BLOCK error"); sleep(5);/* SIGQUIT here will remain pending */ if (sigpending(&pendmask) < 0) err_sys("sigpending error"); if (sigismember(&pendmask, SIGQUIT)) printf("\nSIGQUIT pending\n"); /* * Reset signal mask which unblocks SIGQUIT. */ if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) err_sys("SIG_SETMASK error"); printf("SIGQUIT unblocked\n"); sleep(5);/* SIGQUIT here will terminate with core file */ exit(0); } static void sig_quit(int signo) { printf("caught SIGQUIT\n"); if (signal(SIGQUIT, SIG_DFL) == SIG_ERR) err_sys("can't reset SIGQUIT"); }
程序清单10-12 用 sigaction 实现的 signal 函数
#include "util.h" // Reliable version of signal(),using POSIX sigaction; Sigfunc *signal(int signo,Sigfunc *func){ struct sigaction act,oact; act.sa_handler = func; sigemptyset(&act.sa_mask); act.sa_flags = 0; 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(SIG_ERR); return(oact.sa_handler); }
程序清单10-13 阻止任何被中断系统调用重启动的的 signal 函数
#include "util.h" // will stop all the inttrupted signal,that is sigaction's //default behavior ,so deal with the early aspects; Sigfunc * signal_intr(int signo, Sigfunc *func) { struct sigaction act, oact; act.sa_handler = func; sigemptyset(&act.sa_mask); act.sa_flags = 0; #ifdef SA_INTERRUPT act.sa_flags |= SA_INTERRUPT; #endif if (sigaction(signo, &act, &oact) < 0) return(SIG_ERR); return(oact.sa_handler); }
程序清单10-14 信号屏蔽字,sigsetjmp,siglongjmp 实例
#include "util.h" #include<setjmp.h> #include<time.h> static void sig_usr(int),sig_alrm(int); static sigjmp_buf jmpbuf; static volatile sig_atomic_t canjmp; int main(void){ if(signal(SIGUSR1,sig_usr) == SIG_ERR) err_sys("register signal SIGUSR1 error"); if(signal(SIGALRM,sig_alrm) == SIG_ERR) err_sys("register signal SIGALRM error"); pr_mask("starting main:"); if(sigsetjmp(jmpbuf,1)){ pr_mask("ending main:"); exit(0); } canjmp = 1;// now sigsetjmp is ok ,can jmp there for(;;) pause(); } static void sig_usr(int signo){ time_t starttime; if(canjmp == 0) return;//not prepare well,so ignore it ; pr_mask("starting sig_usr:"); alarm(3); // SIGALRM in 3 sec starttime = time(NULL); for(;;) if(time(NULL) > starttime + 5) break; pr_mask("ending sig_usr:"); canjmp = 0; siglongjmp(jmpbuf,1); } static void sig_alrm(int signo){ pr_mask("in sig_alrm:"); }
程序清单10-15 保护临界区不被信号中断
#include "util.h" static void sig_int(int); int main(void) { sigset_t newmask, oldmask, waitmask; pr_mask("program start: "); if (signal(SIGINT, sig_int) == SIG_ERR) err_sys("signal(SIGINT) error"); sigemptyset(&waitmask); sigaddset(&waitmask, SIGUSR1); sigemptyset(&newmask); sigaddset(&newmask, SIGINT); /* * Block SIGINT and save current signal mask. * */ if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) err_sys("SIG_BLOCK error"); /* * Critical region of code. */ pr_mask("in critical region: "); /* * * Pause, allowing all signals except SIGUSR1. */ if (sigsuspend(&waitmask) != -1) err_sys("sigsuspend error"); pr_mask("after return from sigsuspend: "); /* * Reset signal mask which unblocks SIGINT. */ if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) err_sys("SIG_SETMASK error"); /* * And continue processing ... */ pr_mask("program exit: "); exit(0); } static void sig_int(int signo) { pr_mask("\nin sig_int: "); }
程序清单10-16 用sigsuspend等待一个全局变量被设置
#include "util.h" volatile sig_atomic_t quitflag; /* set nonzero by signal handler */ static void sig_int(int signo) /* one signal handler for SIGINT and SIGQUIT */ { if (signo == SIGINT) printf("\ninterrupt\n"); else if (signo == SIGQUIT) quitflag = 1; /* set flag for main loop */ } int main(void) { sigset_t newmask, oldmask, zeromask; if (signal(SIGINT, sig_int) == SIG_ERR) err_sys("signal(SIGINT) error"); if (signal(SIGQUIT, sig_int) == SIG_ERR) err_sys("signal(SIGQUIT) error"); sigemptyset(&zeromask); sigemptyset(&newmask); sigaddset(&newmask, SIGQUIT); /* * Block SIGQUIT and save current signal mask. */ if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) err_sys("SIG_BLOCK error"); while (quitflag == 0) sigsuspend(&zeromask); // suspend will use zeromask to replace the new mask , this is to say , //here we temporarily change the signal mask, can catch any signal ; /* * SIGQUIT has been caught and is now blocked; do whatever. */ quitflag = 0; /* * Reset signal mask which unblocks SIGQUIT. */ if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) err_sys("SIG_SETMASK error"); exit(0); }
程序清单10-17 父子进程可以用来实现同步的例程(TELL_WAIT)
#include "util.h" static volatile sig_atomic_t sigflag; /* set nonzero by sig handler */ static sigset_t newmask, oldmask, zeromask; static void sig_usr(int signo) /* one signal handler for SIGUSR1 and SIGUSR2 */ { sigflag = 1; } void TELL_WAIT(void) { if (signal(SIGUSR1, sig_usr) == SIG_ERR) err_sys("signal(SIGUSR1) error"); if (signal(SIGUSR2, sig_usr) == SIG_ERR) err_sys("signal(SIGUSR2) error"); sigemptyset(&zeromask); sigemptyset(&newmask); sigaddset(&newmask, SIGUSR1); sigaddset(&newmask, SIGUSR2); /* * Block SIGUSR1 and SIGUSR2, and save current signal mask. */ if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) err_sys("SIG_BLOCK error"); } void TELL_PARENT(pid_t pid) { kill(pid, SIGUSR2); /* tell parent we're done */ } void WAIT_PARENT(void) { while (sigflag == 0) sigsuspend(&zeromask); /* and wait for parent */ sigflag = 0; /* * Reset signal mask to original value. */ if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) err_sys("SIG_SETMASK error"); } void TELL_CHILD(pid_t pid) { kill(pid, SIGUSR1); /* tell child we're done */ } void WAIT_CHILD(void) { while (sigflag == 0) sigsuspend(&zeromask); /* and wait for child */ sigflag = 0; /* * Reset signal mask to original value. */ if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) err_sys("SIG_SETMASK error"); }
程序清单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 编辑器
#include "util.h" static void sig_int(int signo){ printf("Caught SIGINT \n"); } static void sig_chld(int signo){ printf("Caught SIGCHLD \n"); } int main(){ if(signal(SIGINT, sig_int) == SIG_ERR) err_sys("signal(SIGINT) error"); if(signal(SIGCHLD, sig_chld) == SIG_ERR) err_sys("signal(SIGCHLD) error"); if(system("/bin/ed") < 0) err_sys("system(ed) error"); exit(0); }
程序清单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 的可靠实现
#include "util.h" static void sig_alrm(int signo) { /* nothing to do, just returning wakes up sigsuspend() */ } unsigned int sleep(unsigned int nsecs) { struct sigaction newact, oldact; sigset_t newmask, oldmask, suspmask; unsigned int unslept; /* set our handler, save previous information */ newact.sa_handler = sig_alrm; sigemptyset(&newact.sa_mask); newact.sa_flags = 0; sigaction(SIGALRM, &newact, &oldact); /* block SIGALRM and save current signal mask */ sigemptyset(&newmask); sigaddset(&newmask, SIGALRM); sigprocmask(SIG_BLOCK, &newmask, &oldmask); alarm(nsecs); suspmask = oldmask; sigdelset(&suspmask, SIGALRM);/* make sure SIGALRM isn't blocked */ sigsuspend(&suspmask);/* wait for any signal to be caught */ /* some signal has been caught, SIGALRM is now blocked */ unslept = alarm(0); sigaction(SIGALRM, &oldact, NULL);/* reset previous action */ /* reset signal mask, which unblocks SIGALRM */ sigprocmask(SIG_SETMASK, &oldmask, NULL); return(unslept); }
APUE信号-程序汇总
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。