• 《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);

  • 相关阅读:
    linux awk 文本分析实例 [视频]
    如何实现 Python 中 selnium 模块的换行
    Python 中当前位置以及目录文件遍历操作
    Python中执行变量而非字符串
    如何使用 sort 命令来找到几个版本库之间的共同文件
    Setup "EQGRP_Lost_in_Translation" Of NAS
    SQL server 2008 安装问题解决
    windows共享文件的方法
    linux command
    knowlege experience
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/5040933.html
Copyright © 2020-2023  润新知