APUE函数笔记八: 信号
来源:互联网 发布:封装json数据 编辑:程序博客网 时间:2024/05/22 07:47
第十章 信号:
0 < signo < NSIG#include <signal.h>void (*signal(int signo, void(*func)(int)))(int); if error return SIG_ERR, else return previous handler#include <signal.h>int kill(pid_t pid, int signo); pid: == -1, send to any process > 0, send to the process which process-id == pid == 0, send to any process which pgid == this-pgid < -1, send to any process which pgid == abs(pid) this process need have privilege to send to receiver otherwise will not send particular: if signo == SIGCONT, will send to any process which sid == this-sid if signo is 0, not real to send, but check the receiver is alive or not? if receiver is not exist, return -1, error is ESRCH if success return 0, else return -1int raise(int signo); same as kill(getpid(), signo) if success return 0, else return -1#include <unistd.h>unsigned int alarm(unsigned int seconds); return 0 or rest seconds of last alarm#include <unistd.h>int pause(void); only catch a signal and handler it, will return always return -1, errno is EINTR#include <signal.h>int sigemptyset(sigset_t * set); if success return 0, else return -1int sigfillset(sigset_t * set); if success return 0, else return -1int sigaddset(sigset_t * set, int signo); if success return 0, else return -1int sigdelset(sigset_t * set, int signo); if success return 0, else return -1int sigismember(const sigset_t * set, int signo); ret: 1 means true, 0 means false, -1 means error#include <signal.h>int sigprocmask(int how, const sigset_t * restrict set, sigset_t * restrict oset); how: SIG_BLOCK, SIG_UNBLOCK, SIG_SETMASK if success return 0, else return -1#include <signal.h>int sigpending(sigset_t * set); if success return 0, else return -1#include <signal.h>int sigaction(int signo, const struct sigaction * restrict act, struct sigaction * restrict oact); if success return 0, else return -1 struct sigaction { void (*sa_handler)(int); sigset_t sa_mask; int sa_flags; void (*sa_sigaction)(int, siginfo_t *, void *); }; sa_flags: SA_INTERRUPT, SA_NOCLDSTOP, SA_NOCLDWAIT, SA_NODEFER SA_ONSTACK, SA_RESETHAND, SA_RESTART, SA_SIGINFO#include <setjmp.h>int sigsetjmp(sigjmp_buf env, int savemask); savemask: 0, not save mask to env; not 0, save mask to env if callback by siglongjmp return non-zero, else return 0void siglongjmp(sigjmp_buf env, int val);#include <signal.h>int sigsuspend(const sigset_t * sigmask); always return -1, errno is EINTR#include <stdlib.h>void abort(void); cannot be block and ignore#include <unistd.h>unsigned int sleep(unsigned int seconds); return 0 or rest seconds#include <signal.h>void psignal(int signo, const char * msg);#include <string.h>#include <siginfo.h> /* Solaris need it */char * strsignal(int signo);#include <signal.h>int sig2str(int signo, char * str); SIG2STR_MAX defined by Solaris Never change errno if success return 0, else return -1int str2sig(const char * str, int * signop); Never change errno if success return 0, else return -1
示例:
#include <stdio.h>#include <signal.h>void sig_usr(int signo){ if (signo == SIGUSR1) { printf("received SIGUSR1\n"); } else if (signo == SIGUSR2) { printf("received SIGUSR2\n"); } else { printf("error: received signal %d\n", signo); }}int main(void){ if (signal(SIGUSR1, sig_usr) == SIG_ERR) { printf("can not catch SIGUSR1\n"); return -1; } if (signal(SIGUSR2, sig_usr) == SIG_ERR) { printf("can not catch SIGUSR2\n"); return -1; } while (1) { pause(); } return 0;}
#include <stdio.h>#include <stdlib.h>#include <pwd.h>#include <signal.h>void my_alarm(int signo){ struct passwd * rootptr; printf("int signal handler\n"); if ((rootptr = getpwnam("root")) == NULL) { printf("getpwnam(root) error\n"); exit(127); } alarm(1); }int main(void){ struct passwd * ptr; if (signal(SIGALRM, my_alarm) == SIG_ERR) { printf("signal(SIGALRM) error\n"); exit(127); } printf("alarm\n"); alarm(1); while (1) { if ((ptr = getpwnam("adwardink")) == NULL) { printf("getpwnam(adwardink) error\n"); exit(127); } if (strcmp(ptr->pw_name, "adwardink") != 0) { printf("return value corrupted!, pw_name = %s\n", ptr->pw_name); } }}
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <signal.h>void sig_cld(int signo){ pid_t pid; int status; printf("SIGCLD reccived\n"); if (signal(SIGCLD, sig_cld) == SIG_ERR) { /* may error in some old sys*/ printf("signal error\n"); exit(127); } if ((pid = wait(&status)) < 0) { printf("wait error\n"); exit(127); } printf("pid = %d\n", pid);}int main(void){ pid_t pid; if (signal(SIGCLD, sig_cld) == SIG_ERR) { printf("signal error\n"); exit(127); } if ((pid = fork()) < 0) { printf("fork error\n"); exit(127); } else if (pid == 0) { sleep(2); _exit(0); /* test exit(0), get same answer*/ } else { pause(); exit(0); }}
#include <stdio.h>#include <stdlib.h>#include <setjmp.h>#include <unistd.h>#include <signal.h>jmp_buf jmpbuf;void sig_alm(int signo){ longjmp(jmpbuf, 1);}int main(void){ int i; int n; char buff[BUFSIZ]; if (signal(SIGALRM, sig_alm) == SIG_ERR) { printf("signal error\n"); exit(127); } if (setjmp(jmpbuf) != 0) { printf("time out\n"); exit(127); } for (i = 0; i < 5; ++i) { alarm(5); if ((n = read(STDIN_FILENO, buff, BUFSIZ)) < 0) { printf("read error\n"); exit(127); } alarm(0); if (write(STDOUT_FILENO, buff, n) != n) { printf("write error\n"); exit(127); } } exit(0);}
#include <stdio.h>#include <errno.h>#include <stdlib.h>#include <signal.h>void sig_quit(int signo){ printf("caught SIGQUIT\n"); if (signal(SIGQUIT, SIG_DFL) == SIG_ERR) { printf("cannot reset SIGQUIT\n"); exit(127); }}int main(void){ sigset_t newmask; sigset_t oldmask; sigset_t pendmask; if (signal(SIGQUIT, sig_quit) == SIG_ERR) { printf("signal error\n"); exit(127); } /* * block SIGQUIT and save current signal mask */ if (sigemptyset(&newmask) < 0) { printf("sigemptyset error\n"); exit(127); } if (sigaddset(&newmask, SIGQUIT) < 0) { printf("sigaddset error\n"); exit(127); } if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) { printf("sigprocmask error\n"); exit(127); } sleep(5); /* SIGQUIT here will remain pending */ if (sigpending(&pendmask) < 0) { printf("sigpending error\n"); exit(127); } if (sigismember(&pendmask, SIGQUIT) == 1) { printf("\nSIGQUIT pending\n"); } /* * reset signal mask which unblocks SIGQUIT */ if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) { printf("sigprocmask error\n"); exit(127); } printf("SIGQUIT unblocked\n"); sleep(5); /* SIGQUIT here will terminate with core file */ exit(0);}
#include <stdio.h>#include <errno.h>#include <time.h>#include <setjmp.h>#include <stdlib.h>#include <signal.h>sigjmp_buf jmpbuf;volatile sig_atomic_t canjump;void pr_mask(const char * str){ sigset_t sigset; int errno_save; errno_save = errno; if (sigprocmask(0, NULL, &sigset) == -1) { printf("sigprocmask error\n"); return; } printf("%s", str); if (sigismember(&sigset, SIGINT) == 1) { printf("SIGINT "); } if (sigismember(&sigset, SIGQUIT) == 1) { printf("SIGQUIT "); } if (sigismember(&sigset, SIGUSR1) == 1) { printf("SIGUSR1 "); } if (sigismember(&sigset, SIGUSR2) == 1) { printf("SIGUSR2 "); } if (sigismember(&sigset, SIGALRM) == 1) { printf("SIGALRM "); } printf("\n"); errno = errno_save;}void sig_usr1(int signo){ time_t starttime; if (canjump = 0) { return; /* unexpected signal, ignore */ } pr_mask("starting sig_usr1: "); alarm(3); /* SIGALRM in 3 seconds */ starttime = time(NULL); while (1) { if (time(NULL) > starttime + 5) { /* busy wait for 5 seconds */ break; } } pr_mask("finishing sig_usr1: "); canjump = 0; siglongjmp(jmpbuf, 1); /* jump back to main, donot return */}void sig_alrm(int signo){ pr_mask("in sig_alrm: ");}int main(void){ if (signal(SIGUSR1, sig_usr1) == SIG_ERR) { printf("signal(SIGUSR1) error\n"); exit(127); } if (signal(SIGALRM, sig_alrm) == SIG_ERR) { printf("signal(SIGALRM) error\n"); exit(127); } pr_mask("starting main: "); if (sigsetjmp(jmpbuf, 1) != 0) { pr_mask("ending main: "); exit(0); } canjump = 1; /* now sigsetjmp() is OK */ while (1) { pause(); }}
#include <stdio.h>#include <errno.h>#include <stdlib.h>#include <signal.h>void pr_mask(const char * str){ sigset_t sigset; int errno_save; errno_save = errno; if (sigprocmask(0, NULL, &sigset) == -1) { printf("sigprocmask error\n"); return; } printf("%s", str); if (sigismember(&sigset, SIGINT) == 1) { printf("SIGINT "); } if (sigismember(&sigset, SIGQUIT) == 1) { printf("SIGQUIT "); } if (sigismember(&sigset, SIGUSR1) == 1) { printf("SIGUSR1 "); } if (sigismember(&sigset, SIGUSR2) == 1) { printf("SIGUSR2 "); } if (sigismember(&sigset, SIGALRM) == 1) { printf("SIGALRM "); } printf("\n"); errno = errno_save;}void sig_int(int signo){ pr_mask("\nin sig_int: ");}int main(void){ sigset_t newmask; sigset_t oldmask; sigset_t waitmask; if (signal(SIGINT, sig_int) == SIG_ERR) { printf("signal error\n"); exit(127); } if (sigemptyset(&newmask) < 0) { printf("sigemptyset error\n"); exit(127); } if (sigaddset(&newmask, SIGINT) < 0) { printf("sigaddset error\n"); exit(127); } if (sigemptyset(&waitmask) < 0) { printf("sigemptyset error\n"); exit(127); } if (sigaddset(&waitmask, SIGUSR1) < 0) { printf("sigaddset error\n"); exit(127); } /* * block SIGINT and save current signal mask */ if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) { printf("sigprocmask error\n"); exit(127); } /* * critical region of code */ pr_mask("in critical region: "); /* * pause, allowing all signals, except SIGUSR1 */ if (sigsuspend(&waitmask) != -1) { printf("sigsuspend error\n"); exit(127); } pr_mask("after return from sigsuspend: "); /* * reset signal mask which unblocks SIGINT */ if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) { printf("sigprocmask error\n"); exit(0); } /* * and continue processing ... */ pr_mask("program exit: "); exit(0);}
#include <stdio.h>#include <stdlib.h>#include <signal.h>volatile sig_atomic_t quitflag; /* set nonzero by signal handler */void sig_int(int signo){ if (signo == SIGINT) { printf("\ninterrupt\n"); } else if (signo == SIGQUIT) { quitflag = 1; }}int main(void){ sigset_t newmask; sigset_t oldmask; sigset_t zeromask; if (signal(SIGINT, sig_int) == SIG_ERR) { printf("signal error\n"); exit(127); } if (signal(SIGQUIT, sig_int) == SIG_ERR) { printf("signal error\n"); exit(127); } if (sigemptyset(&zeromask) < 0) { printf("sigemptyset error\n"); exit(127); } if (sigemptyset(&newmask) < 0) { printf("sigemptyset error\n"); exit(127); } if (sigaddset(&newmask, SIGQUIT) < 0) { printf("sigaddset error\n"); exit(127); } /* * block SIGQUIT and save current signal mask */ if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) { printf("sigprocmask error\n"); exit(127); } /* * pause, allowing all signals */ while (quitflag == 0) { if (sigsuspend(&zeromask) != -1) { printf("sigsuspend error\n"); exit(127); } } /* * SIGQUIT has been caught and is now blocked, do whatever */ quitflag = 0; /* * reset signal mask which unblocks SIGINT */ if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) { printf("sigprocmask error\n"); exit(0); } exit(0);}
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <signal.h>#define BUFFSIZE (1024)void sig_tstp(int signo) /* signal handler for SIGTSTP */{ sigset_t mask; /* ... move cursor to lower left corner, reset tty mod ... */ /* * unblock SIGTSTP, since it is blocked while we are handling it */ sigemptyset(&mask); sigaddset(&mask, SIGTSTP); sigprocmask(SIG_UNBLOCK, &mask, NULL); signal(SIGTSTP, SIG_DFL); /* reset disposition to default */ kill(getpid(), SIGTSTP); /* and send the signal to ourselves */ /* we wonnot return from the kill until we are continued */ signal(SIGTSTP, sig_tstp); /* reestablish signal handler */ /* ... reset tty mode, redraw screen ... */}int main(void){ int n; char buf[BUFFSIZE]; /* * only catch SIGTSTP if we are running with a job-control shell */ if (signal(SIGTSTP, SIG_IGN) == SIG_DFL) { signal(SIGTSTP, sig_tstp); } while ((n = read(STDIN_FILENO, buf, BUFFSIZE)) > 0) { if (write(STDOUT_FILENO, buf, n) != n) { printf("write error\n"); exit(127); } } if (n < 0) { printf("read error\n"); exit(127); } exit(0);}
#ifndef __MY_SIGNAL_H__#define __MY_SIGNAL_H__#include <stdio.h>#include <errno.h>#include <signal.h>typedef void Sigfunc(int);Sigfunc * my_signal(int signo, Sigfunc * func){ struct sigaction act; struct sigaction 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; } else { return oact.sa_handler; }}Sigfunc * my_signal_intr(int signo, Sigfunc * func){ struct sigaction act; struct sigaction 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; } else { return oact.sa_handler; }}#endif
#include <stdlib.h>#include <signal.h>void sig_alrm(int signo){ /* nothing to do, just returning wakes up sigsuspend() */}unsigned intsleep(unsigned int seconds){ struct sigaction newact; struct sigaction oldact; sigset_t newmask; sigset_t oldmask; sigset_t pendmask; 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(seconds); pendmask = oldmask; sigdelset(&pendmask, SIGALRM); /* make sure SIGALRM is not blocked */ sigsuspend(&pendmask); /* 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;}
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <signal.h>void my_abort(void) /* POSIX-style abort() function */{ sigset_t mask; struct sigaction action; /* * caller cannot ignore SIGABRT, if 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 cannot block SIGABRT, make sure it is unblocked */ sigfillset(&mask); sigdelset(&mask, SIGABRT); /* make has only SIGABRT turned off */ sigprocmask(SIG_SETMASK, &mask, NULL); kill(getpid(), SIGABRT); /* send the signal */ /* * if we are here, process caught SIGABRT and returned */ fflush(NULL); /* flush all open stdio streams */ action.sa_handler = SIG_DFL; sigaction(SIGABRT, &action, NULL); /* reset to default */ sigprocmask(SIG_SETMASK, &mask, NULL); /* just in case ... */ kill(getpid(), SIGABRT); /* and one more time */ exit(1); /* this should never be executed ... */}
#include <errno.h>#include <signal.h>#include <unistd.h>#include <sys/wait.h>int my_system(const char * cmdstring) /* with appropriate signal handling */{ pid_t pid; int status; struct sigaction ignore; struct sigaction saveintr; struct sigaction savequit; sigset_t chldmask; sigset_t 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); sigaddset(&chldmask, SIGCHLD); /* now block SIGCHLD */ if (sigprocmask(SIG_BLOCK, &chldmask, &savemask) < 0) { return -1; } if ((pid = fork()) < 0) { status = -1; /* probably out of processes */ } else if (pid == 0) { /* restore previous signal actions, reset signal mask */ 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 { 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; } if (sigprocmask(SIG_SETMASK, &savemask, NULL) < 0) { return -1; } return status;}
#include <stdio.h>#include <stdlib.h>#include <signal.h>#include "signal.h"volatile sig_atomic_t sigflag; /* set nonzero by sig handler */sigset_t newmask, oldmask, zeromask;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) { printf("signal(SIGUSR1) error\n"); exit(127); } if (signal(SIGUSR2, sig_usr) == SIG_ERR) { printf("signal(SIGUSR2) error\n"); exit(127); } if (sigemptyset(&zeromask) < 0) { printf("sigemptyset error\n"); exit(127); } if (sigemptyset(&newmask) < 0) { printf("sigemptyset error\n"); exit(127); } if (sigaddset(&newmask, SIGUSR1) < 0) { printf("sigaddset error\n"); exit(127); } if (sigaddset(&newmask, SIGUSR2) < 0) { printf("sigaddset error\n"); exit(127); } /* * block SIGUSR1 and SIGUSR2, and save current signal mask */ if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) { printf("sigprocmask(SIG_BLOCK) error\n"); exit(127); }}void TELL_PARENT(pid_t pid){ kill(pid, SIGUSR2); /* tell parent we are done */}void WAIT_PARENT(void){ while (sigflag == 0) { if (sigsuspend(&zeromask) != -1) { /* and wait for parent */ printf("sigsuspend error\n"); exit(127); } } sigflag = 0; /* * reset signal mask to original value */ if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) { printf("sigprocmask(SIG_SETMASK) error\n"); exit(0); }}void TELL_CHILD(pid_t pid){ kill(pid, SIGUSR1); /* tell child we are done */}void WAIT_CHILD(void){ while (sigflag == 0) { if (sigsuspend(&zeromask) != -1) { /* and wait for child */ printf("sigsuspend error\n"); exit(127); } } sigflag = 0; /* * reset signal mask to original value */ if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) { printf("sigprocmask(SIG_SETMASK) error\n"); exit(0); }}
关于SIGKILL/SIGSTOP/SIGTSTP:http://blog.sina.com.cn/s/blog_53a7e8a3010155hx.html
SIGKILL和SIGSTOP的区别SIGKILL提供给管理员杀死进程的权利, SIGSTOP提供给管理员暂停进程的权利, 所以这两个信号不能被忽略和重定义。Kill父进程后, 子进程的父进程号为1; 但是stop父进程后子进程的父进程号还是该父进程。SIGSTOP和SIGTSTP的区别SIGSTOP提供给管理员暂停进程的特权, 所以不能忽略和重定义。当用户按下CTRL-Z时, 向前台进程组发送SIGTSTP信号以暂停进程(默认动作), 该信号可以被忽略和重定义。另外用户在控制终端上输入CTRL-S可以暂停进程的输出, 输入CTRL-Q可以恢复进程的输出。
- APUE函数笔记八: 信号
- APUE 信号学习笔记
- apue-第十章 信号 笔记
- 《APUE》笔记-第十章-信号
- APUE学习笔记——10信号——信号接口函数 signal 和 sigaction
- APUE函数笔记: 附录
- apue-alarm和pause函数,关于信号
- APUE学习笔记—— 信号实现系统sleep和system函数,解决进程竞争实例
- APUE学习笔记——10.9 信号发送函数kill、 raise、alarm、pause
- APUE学习笔记(17)-线程和信号
- APUE学习笔记——信号
- APUE学习笔记——信号
- APUE学习笔记(17)-线程和信号
- APUE学习笔记——10 信号
- apue学习笔记(第十章 信号)
- APUE信号
- APUE------信号
- APUE函数笔记九: 线程
- Tomcat实现多个webapps共享session的解决方法
- 几种数据库检索结果与Endnote的衔接(转)
- VC6.0编译器参数设置
- jquery对话框插件
- windows下socket开发udp程序
- APUE函数笔记八: 信号
- C++什么情况会合成构造函数
- Word2003 和 Word2010 中插入页码的方法
- 网络嗅探 使用Sniffer Pro监控ARP协议欺骗
- json相关笔记
- 数据库(一)数据库基础之数据库系统概述
- Android开发之短信拦截--BroadcastReceiver学习
- 第六周作业
- ffmpeg 从mp4上提取H264的nalu