Linux信号透彻分析理解与各种实例讲解( 三 )


sa_handler是一个函数指针 , 主要是表示接收到信号时所要采取的行动 。 此字段的值可以是SIG_DFL,SIG_IGN.分别代表默认操作与内核将忽略进程的信号 。 这个函数只传递一个参数那就是信号代码 。
当SA_SIGINFO被设定在sa_flags中 , 那么则会使用sa_sigaction来指示信号处理函数 , 而非sa_handler.
sa_mask设置了掩码集 , 在程序执行期间会阻挡掩码集中的信号 。
sa_flags设置了一些标志 ,SA_RESETHAND当该函数处理完成之后 , 设定为为系统默认的处理模式 。 SA_NODEFER 在处理函数中 , 如果再次到达此信号时 , 将不会阻塞 。 默认情况下 , 同一信号两次到达时 , 如果此时处于信号处理程序中 , 那么此信号将会阻塞 。
SA_SIGINFO表示用sa_sigaction指示的函数 。
sa_restorer已经被废弃 。
sa_sigaction所指向的函数原型:
void my_handler(int signo,siginfo_t *si,void *ucontext);
第一个参数: 信号编号
第二个参数:指向一个siginfo_t结构 。
第三个参数是一个ucontext_t结构 。
其中siginfo_t结构体中包含了大量的信号携带信息 , 可以看出 , 这个函数比sa_handler要强大 , 因为前者只能传递一个信号代码 , 而后者可以传递siginfo_t信息 。
typedef struct siginfo_t{int si_signo;//信号编号int si_errno;//如果为非零值则错误代码与之关联int si_code;//说明进程如何接收信号以及从何处收到pid_t si_pid;//适用于SIGCHLD , 代表被终止进程的PIDpid_t si_uid;//适用于SIGCHLD,代表被终止进程所拥有进程的UIDint si_status;//适用于SIGCHLD , 代表被终止进程的状态clock_t si_utime;//适用于SIGCHLD , 代表被终止进程所消耗的用户时间clock_t si_stime;//适用于SIGCHLD , 代表被终止进程所消耗系统的时间sigval_t si_value;int si_int;void * si_ptr;void* si_addr;int si_band;int si_fd;}; sigqueue(pid_t pid,int signo,const union sigval value)union sigval{int sival_int, void*sival_ptr}; sigqueue函数类似于kill,也是一个进程向另外一个进程发送信号的 。
但它比kill函数强大 。
第一个参数指定目标进程的pid.
第二个参数是一个信号代码 。
第三个参数是一个共用体 , 每次只能使用一个 , 用来进程发送信号传递的数据 。
或者传递整形数据 , 或者是传递指针 。
发送的数据被sa_sigaction所指示的函数的siginfo_t结构体中的si_ptr或者是si_int所接收 。
sigpending的用法
sigpending(sigset_t set);
这个函数的作用是返回未决的信号到信号集set中 。 即未决信号集 , 未决信号集不仅包括被阻塞的信号 , 也可能包括已经到达但没有被处理的信号 。
示例1: sigaction函数的用法
struct sigaction {void (*sa_handler)(int);void (*sa_sigaction)(int,siginfo_t*,void*);sigset_t sa_mask;int sa_flags;void (*sa_restorer)(void);} 运行结果:[root@localhost C]# ./s2signal 1 handler is : using default handersignal 2 handler is : 8048437signal 3 handler is : using default handersignal 4 handler is : using default handersignal 5 handler is : using default handersignal 6 handler is : using default handersignal 7 handler is : using default handersignal 8 handler is : using default handersignal 9 handler is : using default handersignal 10 handler is : using default handersignal 11 handler is : using default handerxxxxx解释:
sigaction(i,NULL,
signal_set(
由于act为NULL,那么oldact保存的是当前信号的行为 , 当前的第二个信号的行为是执行自定义的处理程序 。
当按下CTRL+C时会执行信号处理程序 , 输出xxxxxx , 再按一下CTRL+C会停止,是由于SA_RESETHAND恢复成默认的处理模式 , 即终止程序 。
如果没有设置SA_NODEFER,那么在处理函数执行过程中按一下CTRL+C将会被阻塞 , 那么程序会停在那里 。
示例2: sigqueue向本进程发送数据的信号
#include#include#include#include#includevoid myhandler(int signo,siginfo_t *si,void *ucontext);int main(){union sigval val;//定义一个携带数据的共用体struct sigaction oldact,act;act.sa_sigaction=myhandler;act.sa_flags=SA_SIGINFO;//表示使用sa_sigaction指示的函数 , 处理完恢复默认 , 不阻塞处理过程中到达下在被处理的信号//注册信号处理函数sigaction(SIGUSR1,char data[100];int num=0;while(num<10){sleep(2);printf("等待SIGUSR1信号的到来/n");sprintf(data,"%d",num++);val.sival_ptr=data;sigqueue(getpid(),SIGUSR1,val);//向本进程发送一个信号}}void myhandler(int signo,siginfo_t *si,void *ucontext){printf("已经收到SIGUSR1信号/n");printf("%s/n",(char*)(si->si_ptr));}程序执行的结果是:
等待SIGUSR1信号的到来已经收到SIGUSR1信号0等待SIGUSR1信号的到来已经收到SIGUSR1信号1等待SIGUSR1信号的到来已经收到SIGUSR1信号2等待SIGUSR1信号的到来已经收到SIGUSR1信号3等待SIGUSR1信号的到来已经收到SIGUSR1信号4等待SIGUSR1信号的到来已经收到SIGUSR1信号5等待SIGUSR1信号的到来已经收到SIGUSR1信号6等待SIGUSR1信号的到来已经收到SIGUSR1信号7等待SIGUSR1信号的到来已经收到SIGUSR1信号8等待SIGUSR1信号的到来已经收到SIGUSR1信号9