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


发送端:
#include#include#include#include#includeint main(){union sigval value;value.sival_int=10;if(sigqueue(4403,SIGUSR1,value)==-1){//4403是目标进程pidperror("信号发送失败/n");}sleep(2);} 接收端:
#include#include#include#include#includevoid myhandler(int signo,siginfo_t*si,void *ucontext);int main(){struct sigaction oldact,act;act.sa_sigaction=myhandler;act.sa_flags=SA_SIGINFO|SA_NODEFER;//表示执行后恢复 , 用sa_sigaction指示的处理函数 , 在执行期间仍然可以接收信号sigaction(SIGUSR1,while(1){sleep(2);printf("等待信号的到来/n");}}void myhandler(int signo,siginfo_t *si,void *ucontext){ printf("the value is %d/n",si->si_int);}示例4: sigpending的用法
sigpending(sigset_t *set)将未决信号放到指定的set信号集中去 , 未决信号包括被阻塞的信号和信号到达时但还没来得及处理的信号
#include#include#include#include#includevoid myhandler(int signo,siginfo_t *si,void *ucontext);int main(){struct sigaction oldact,act;sigset_t oldmask,newmask,pendingmask;act.sa_sigaction=myhandler;act.sa_flags=SA_SIGINFO;sigemptyset(//首先将阻塞集合设置为空 , 即不阻塞任何信号//注册信号处理函数sigaction(SIGRTMIN+10,//开始阻塞sigemptyset(sigaddset(printf("SIGRTMIN+10 blocked/n");sigprocmask(SIG_BLOCK,sleep(20);//为了发出信号printf("now begin to get pending mask/n");if(sigpending(}if(sigismember(}sigprocmask(SIG_UNBLOCK,printf("SIGRTMIN+10 unblocked/n");}//信号处理函数void myhandler(int signo,siginfo_t *si,void *ucontext){printf("receive signal %d/n",si->si_signo);} 程序执行:
在另一个shell发送信号:
kill -44 4579
SIGRTMIN+10 blockednow begin to get pending maskSIGRTMIN+10 is in the pending maskreceive signal 44SIGRTMIN+10 unblocked
可以看到SIGRTMIN由于被阻塞所以处于未决信号集中 。
关于基本的信号处理函数就介绍到这了 。
第四部分: 保护临界区不被中断
1. 函数的可重入性
函数的可重入性是指可以多于一个任务并发使用函数 , 而不必担心数据错误 。 相反 , 不可重入性是指不能多于一个任务共享函数 , 除非能保持函数互斥(或者使用信号量 , 或者在代码的关键部分禁用中断) 。 可重入函数可以在任意时刻被中断 , 稍后继续执行 , 而不会丢失数据 。
可重入函数:* 不为连续的调用持有静态数据 。 * 不返回指向静态数据的指针;所有数据都由函数的调用者提供 。 * 使用本地数据 , 或者通过制作全局数据的本地拷贝来保护全局数据 。 * 绝不调用任何不可重入函数 。
不可重入函数可能导致混乱现象 , 如果当前进程的操作与信号处理程序同时对一个文件进行写操作或者是调用malloc() , 那么就可能出现混乱 , 当从信号处理程序返回时 , 造成了状态不一致 。 从而引发错误 。
因此 , 信号的处理必须是可重入函数 。
简单的说 , 可重入函数是指在一个程序中调用了此函数 , 在信号处理程序中又调用了此函数 , 但仍然能够得到正确的结果 。
printf , malloc函数都是不可重入函数 。 printf函数如果打印缓冲区一半时 , 又有一个printf函数 , 那么此时会造成混乱 。 而malloc函数使用了系统全局内存分配表 。
2. 保护临界区不被中断
由于临界区的代码是关键代码 , 是非常重要的部分 , 因此 , 有必要对临界区进行保护 , 不希望信号来中断临界区操作 。 这里通过信号屏蔽字来阻塞信号的发生 。
下面介绍两个与保护临界区不被信号中断的相关函数 。