zoukankan      html  css  js  c++  java
  • 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
    ");
    	else if(signo == SIGUSR2)
    		printf("received SIGUSR2
    ");
    	else err_dump("received signal %d
    ",signo);
    }



    程序清单10- 2  在信号处理程序中调用不可重入函数
    #include "util.h"
    #include <pwd.h>
    
    static void
    my_alarm(int signo){
        struct passwd*rootptr;
        printf("in signal handler
    ");
        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
    ", 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
    ");
        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
    ", 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
    ", 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("
    sig_int starting
    ");
        for (i = 0; i < 300000; i++)
            for (j = 0; j < 4000; j++)
                k += i * j;
        printf("sig_int finished
    ");
    }
    /*
     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("
    ");
    	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("
    SIGQUIT pending
    ");
        
        /*
        * Reset signal mask which unblocks SIGQUIT.
        */
        if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
            err_sys("SIG_SETMASK error");
        printf("SIGQUIT unblocked
    ");
        
        sleep(5);/* SIGQUIT here will terminate with core file */
        exit(0);
    }
    
    static void
    sig_quit(int signo)
    {
        printf("caught SIGQUIT
    ");
        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("
    in 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("
    interrupt
    ");
    	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 
    ");
    }
    static void sig_chld(int signo){
        printf("Caught SIGCHLD 
    ");
    }
    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...
    ");
        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);
    }




  • 相关阅读:
    链表的逆置(无聊而写)
    C
    大型分布式站点的技术需求
    leetcode第一刷_Best Time to Buy and Sell Stock
    微商行业面临洗礼,微盟萌店是否能完毕“神补刀”?
    oracle函数 CONCAT(c1,c2)
    oracle函数 CHR(n1)
    oracle函数 ASCII(x1)
    oracle函数 INTERVAL c1 set1
    oracle函数 SESSIONTIMEZONE
  • 原文地址:https://www.cnblogs.com/wzjhoutai/p/6698767.html
Copyright © 2011-2022 走看看