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可以恢复进程的输出。



原创粉丝点击