zoukankan      html  css  js  c++  java
  • 《UNIX级别编程环境》注意读出信号(2)

    1.功能sigaction

    sigaction动与指定信号相关联的处理动作。其函数原型例如以下:

    #inlcude <signal.h>

    int sigaction(int signo,const struct sigaction * restrict act,struct sigaction * restrict act);

    当中參数signo是要检測或改动其详细动作的信号编号。

    若act指针非空,则要改动其动作。假设oact指针非空。则系统经由oact指针返回该信号的上一个动作。结构体sigaction的结构例如以下:


    一旦对给定的信号设置了一个动作,那么在调用signation显式的改变它之前,该设置就一直有效。

    act结构的sa_flags字段指定对信号进行处理的各个选项。下图具体列出了这些选项的意义。


    sigaction结构的sa_sigaction字段是一个替代的信号处理程序。

    当sa_flags设置了SA_SIGINFO标志时,使用该信号处理程序。

    通常,信号处理函数的形式是这种:void handler(int signo)。

    但假设设置了SA_SIGINFO标志,则信号处理函数的原型是这种:void handler(int signo,siginfo_t *info,void *context)。siginfo_t结构包括了信号产生原因的有关信息。

    该结构的样式例如以下所看到的:


    context參数是无类型指针。它可被强制类型转换为ucontext_t结构类型,该结构标识信号传递时的上下文信息。


    2.函数sigsetjmp和siglongjmp

    在信号处理程序中进行非局部转移时使用这两个函数。

    #include <setjmp.h>

    int sigsetjmp(sigjmp_buf env,int savemask);//若直接调用,返回0。若从siglongjmp调用返回,则返回非0。

    void siglongjmp(sigjmp_buf env,int val);

    在调用sigsetmask时。假设savemask值为1,则将进程当前的屏蔽字保存在env中。

    调用siglongjmp时,假设带非0savemask的sigsetjmp调用已经将进程的屏蔽字保存在env中了。则siglongjmp从中恢复保存的信号屏蔽字。

    例:

    #include "apue.h"
    #include <setjmp.h>
    #include <time.h>
    
    static void sig_usr1(int);
    static void sig_alrm(int);
    static sigjmp_buf jmpbuf;
    static volatile sig_atomic_t canjump;
    
    void pr_mask(const char *str)//打印当前被堵塞的信号
    {
            sigset_t sigset;
            int errno_save;
    
            errno_save = errno; /* we can be called by signal handlers */
            if (sigprocmask(0, NULL, &sigset) < 0)
                    perror("sigprocmask error");
    
            printf("mask: %s", str);
            if (sigismember(&sigset, SIGINT)) printf("SIGINT ");
            if (sigismember(&sigset, SIGQUIT)) printf("SIGQUIT ");
            if (sigismember(&sigset, SIGUSR1)) printf("SIGUSR1 ");
            if (sigismember(&sigset, SIGUSR2)) printf("SIGUSR2 ");
            if (sigismember(&sigset, SIGALRM)) printf("SIGALRM ");
    
            /* remaining signals can go here */
    
            printf("
    ");
            errno = errno_save;
    }
    
    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 {
    		act.sa_flags |= SA_RESTART;	
    	}
    	if(sigaction(signo,&act,&oact) < 0)
    		return (SIG_ERR);
    	return (oact.sa_handler);
    }
    
    int main(void)
    {
    	if(signal(SIGUSR1,sig_usr1) == SIG_ERR)
    		err_sys("signal(SIGUSR1) error");
    
    	if(signal(SIGALRM,sig_alrm) == SIG_ERR)
                    err_sys("signal(SIGALRM) error");
    
    	pr_mask("starting main:");
    	
    	if(sigsetjmp(jmpbuf,1)) {
    		pr_mask("ending main:");
    		exit(0);
    	}
    	canjump = 1;
    	for(;;)
    		pause();	
    }
    
    static void sig_usr1(int signo)
    {
    	time_t starttime;
    	
    	if(canjump == 0)
    		return;
    	
    	pr_mask("starting sig_usr1:");
    	
    	alarm(3);
    	starttime = time(NULL);
    	for(;;)
    		if(time(NULL) > starttime+5)
    			break;
    	pr_mask("finishing sig_usr1:");
    	canjump = 0;
    	siglongjmp(jmpbuf,1);
    }
    
    static void sig_alrm(int signo)
    {
    	pr_mask("in sig_alrm:");
    }

    3.函数sigsuspend

    #include <signal.h>

    int sigsuspend(const sigset_t * sigmask);

    进程的信号屏蔽字设置由sigmask指定。

    在捕捉到一个信号前,该进程被挂起。假设捕捉到一个信号,则sigsuspend返回,而且该进程的新高屏蔽字设置为曾经的值。

    例:

    #include "apue.h"
    
    static void sig_int(int);
    
    void pr_mask(const char *str)//打印当前被堵塞的信号
    {
            sigset_t sigset;
            int errno_save;
    
            errno_save = errno; /* we can be called by signal handlers */
            if (sigprocmask(0, NULL, &sigset) < 0)
                    perror("sigprocmask error");
    
            printf("mask: %s", str);
            if (sigismember(&sigset, SIGINT)) printf("SIGINT ");
            if (sigismember(&sigset, SIGQUIT)) printf("SIGQUIT ");
            if (sigismember(&sigset, SIGUSR1)) printf("SIGUSR1 ");
            if (sigismember(&sigset, SIGUSR2)) printf("SIGUSR2 ");
            if (sigismember(&sigset, SIGALRM)) printf("SIGALRM ");
    
            /* remaining signals can go here */
    
            printf("
    ");
            errno = errno_save;
    }
    
    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 {
    		act.sa_flags |= SA_RESTART;	
    	}
    	if(sigaction(signo,&act,&oact) < 0)
    		return (SIG_ERR);
    	return (oact.sa_handler);
    }
    
    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);
    
    	if(sigprocmask(SIG_BLOCK,&newmask,&oldmask) < 0)
    		err_sys("SIG_BLOCK error");
    
    	pr_mask("in critical region:");
    
    	if(sigsuspend(&waitmask) != -1)
    		err_sys("suspend error");
    
    	pr_mask("after return from sigsuspend:");
    
    	if(sigprocmask(SIG_SETMASK,&oldmask,NULL) < 0)
    		err_sys("SIG_SETMASK error");
    
    	pr_mask("program end:");
    }
    
    static void sig_int(int signo)
    {
    	pr_mask("in sig_int:");
    }

    4.函数sigqueue

    使用排队信号必须做一下几个操作:

    (1)使用sigaction函数安装信号处理程序时指定SA_SIGINFO标志。

    (2)在sigaction结构的sa_sigaction成员中提供信号处理程序。

    (3)使用sigqueue函数发送信号。

    #include <signal.h>

    int sigqueue(pid_t pid,int signo,const union sigval value);


    5.信号名和编号

    能够通过psignal函数可移植地打印与信号编号相应的字符串。

    #include <signal.h>

    void psignal(int signal,const char * msg);//字符串msg输入到标准错误流

    假设只需要字符信号的叙述性说明,可以用于strsignal功能。

    #include <string.h>

    char *strsignal(int signo);

  • 相关阅读:
    剑指Offer-30.连续子数组的最大和(C++/Java)
    剑指Offer-29.最小的K个数(C++/Java)
    UVA 1616 Caravan Robbers 商队抢劫者(二分)
    UVA 10570 Meeting with Aliens 外星人聚会
    UVA 11093 Just Finish it up 环形跑道 (贪心)
    UVA 12673 Erratic Expansion 奇怪的气球膨胀 (递推)
    UVA 10954 Add All 全部相加 (Huffman编码)
    UVA 714 Copying Books 抄书 (二分)
    UVALive 3523 Knights of the Round Table 圆桌骑士 (无向图点双连通分量)
    codeforecs Gym 100286B Blind Walk
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/5040933.html
Copyright © 2011-2022 走看看