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 的可靠实现