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


第五部分: 信号的继承与执行
当使用fork()函数时 , 子进程会继承父进程完全相同的信号语义 , 这也是有道理的 , 因为父子进程共享一个地址空间 , 所以父进程的信号处理程序也存在于子进程中 。
示例: 子进程继承父进程的信号处理函数
#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);} 输出的结果为:
子进程信号处理10父进程信号处理20
可以看出来 , 子进程继承了父进程的信号处理函数 。
第六部分: 实时信号中锁的研究
1. 信号处理函数与主函数之间的死锁
当主函数访问临界资源时 , 通常需要加锁 , 如果主函数在访问临界区时 , 给临界资源上锁 , 此时发生了一个信号 , 那么转入信号处理函数 , 如果此时信号处理函数也对临界资源进行访问 , 那么信号处理函数也会加锁 , 由于主程序持有锁 , 信号处理程序等待主程序释放锁 。 又因为信号处理函数已经抢占了主函数 , 因此 , 主函数在信号处理函数结束之前不能运行 。 因此 , 必然造成死锁 。
示例1: 主函数与信号处理函数之间的死锁
#include#include#include#include#include#includeint value=http://kandian.youth.cn/index/0;sem_t sem_lock;//定义信号量void myhandler(int signo,siginfo_t *si,void *vcontext);//进程处理函数声明int main(){union sigval val;val.sival_int=1;struct sigaction oldact,newact;int res;res=sem_init(if(res!=0){perror("信号量初始化失败");}newact.sa_sigaction=myhandler;newact.sa_flags=SA_SIGINFO;sigaction(SIGUSR1,sem_wait(printf("xxxx/n");value=http://kandian.youth.cn/index/1;sleep(10);sigqueue(getpid(),SIGUSR1,val);//sigqueue发送带参数的信号sem_post(sleep(10);exit(0);}void myhandler(int signo,siginfo_t *si,void *vcontext){sem_wait(value=0;sem_post(}此程序将一直阻塞在信号处理函数的sem_wait函数处 。
2. 利用测试锁解决死锁
sem_trywait(是非阻塞的sem_wait,如果加锁失败或者是超时 , 则返回-1 。
示例2: 用sem_trywait来解决死锁
#include#include#include#include#include#includeint value=http://kandian.youth.cn/index/0;sem_t sem_lock;//定义信号量void myhandler(int signo,siginfo_t *si,void *vcontext);//进程处理函数声明int main(){union sigval val;val.sival_int=1;struct sigaction oldact,newact;int res;res=sem_init(if(res!=0){perror("信号量初始化失败");}newact.sa_sigaction=myhandler;newact.sa_flags=SA_SIGINFO;sigaction(SIGUSR1,sem_wait(printf("xxxx/n");value=http://kandian.youth.cn/index/1;sleep(10);sigqueue(getpid(),SIGUSR1,val);//sigqueue发送带参数的信号sem_post(sleep(10);sigqueue(getpid(),SIGUSR1,val);exit(0);}void myhandler(int signo,siginfo_t *si,void *vcontext){if(sem_trywait(sem_post(}}