首页 > 学院 > 开发设计 > 正文

Linux--信号时序竞态

2019-11-06 06:18:21
字体:
来源:转载
供稿:网友

1. 有问题的mysleep函数,主要注释部分的解释

#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <signal.h>void sig_handle(int signo){	}unsigned int mysleep(unsigned int nsec){	//int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);	struct sigaction newaction, oldaction;		newaction.sa_handler = sig_handle;	sigemptyset(&newaction.sa_mask);	newaction.sa_flags = 0;		if (sigaction(SIGALRM, &newaction, &oldaction) < 0)	{		PRintf("sigaction error/n");		return -1;	}		//假如CPU太忙了,nsec之后内核还在处理别的进程的事,当处理完成后,内核执行这个进程的事,	//由于这时候已经到时间了,按照内核的处理方式,先检查该进程有没有未处理的信号,结果发现	//存在alarm信号没有处理,从而调用信号处理函数。这时候信号到达不了用户空间了。导致pause	//无限制等待	alarm(nsec);	pause();		unsigned int leaveSec = alarm(0);	sigaction(SIGALRM, &oldaction, NULL);		return leaveSec;}int main(int argc, char *argv[]){	while(1)	{		unsigned int leaveSec = mysleep(2);		printf("2 seconds after, leave %u!/n", leaveSec);	}	return 0;}

2. 改进后的mysleep函数,使用信号屏蔽和挂起的原子操作
#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <signal.h>void sig_handle(int signo){	}unsigned int mysleep(unsigned int nsec){	sigset_t newset, oldset, emptyset;	sigemptyset(&newset);	sigemptyset(&emptyset);		sigaddset(&newset, SIGALRM);		if (sigprocmask(SIG_BLOCK, &newset, &oldset) < 0)	{		printf("sigprocmask error/n");		return -1;	}		struct sigaction newact, oldact;	newact.sa_handler = sig_handle;	sigemptyset(&newact.sa_mask);	newact.sa_flags = 0;		if (sigaction(SIGALRM, &newact, &oldact) < 0)	{		printf("sigaction error/n");		return -1;	}		alarm(nsec);	sigsuspend(&emptyset);		unsigned int nleave = alarm(0);	sigaction(SIGALRM, &oldact, NULL);		sigprocmask(SIG_SETMASK, &oldset, NULL); 		return nleave;}int main(int argc, char *argv[]){	while(1)	{		unsigned int leave = mysleep(1);				printf("1s passed, time leave %u/n", leave);	}	return 0;}
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表