信号【N】-linux信号编程的buglist

信号【N】-linux信号编程的buglist,第1张

文章目录
  • 前言
  • 一、sleep无法正常休眠
  • 二、接收到信号但是配置文件没有更新
  • 总结


前言

这片文章会持续更新在信号使用中遇到的bug:


一、sleep无法正常休眠
  • 问题描述:
    再给后端的cpld发送命令,之后延时2s(sleep(2))读取cpld的特殊寄存器的数据,但总是错误的。但是使用两个sleep(2),就可以读取正确。即使第一个延时100s,不使用第二个sleep也不能正确读取。
    write()
    sleep(100)
    sleep(2)
    read()
    
  • 问题原因
    经过实验,从sleep(100)处返回时间还剩1s,也就是sleep(2)恰好不能被延时2s,提前收到信号中断返回了。再执行第二次sleep时,没有了信号,可以正常睡眠。
  • 解决办法
    为了避免这种情况,可以根据sleep的返回值,重新定义一个休眠函数,从而达到真正的睡眠时间。
    unsigned int time = 2;
    do{
    	time = sleep(time)
    }while(time > 0);
    
  • 深入理解sleep函数
    信号【3】- 理解sleep函数
二、接收到信号但是配置文件没有更新
  • 问题描述:
    在项目中遇到一个问题:在设备信号线插拔测试的时候,信号线拔下来了,但是前端网页的状态并没有更新。以下是项目中的伪代码。

    进程:1
    void handler(int num)
    {
    	flag = 1;
    }
    int main(){
    	sigset_t prevMask,intMask;
    	struct sigaction sa;
    	sigemptyset(&intMask);
    	sigaddset(&intMask,SIGINT);
    	sigemptyset(&prevMask);
    	sa.sa_flags = 0;
    	sa.sa_handler = handler;
    	sigaction(SIGMIN,&sa,NULL);
    	while(1){
    		if(flag){
    			sigprocmask(SIG_BLOCK,&intMask,&prevMask);
    			/*以下为不希望被SIGMIN打断的关键代码*/
    			flag = 0;
    			read(fd,buff,128);
    			prase(buff);
    			update(json.config)
    			/*end 关键代码*/
    			/*恢复旧的掩码解除对SIGMIN的阻塞*/
    			sigprocmask(SIG_BLOCK,&prevMask,NULL);
    		}
    		pause();/*本意是希望进程能进入暂停状态,释放CPU资源,等待信号唤醒,继续执行*/
    	}
    }
    
  • 问题原因
    经过分析是,一旦第二次调用sigprocmask之后被阻塞的未决信号立即被传递,执行了信号处理函数,发送在pause之前,那么一旦进入pause则进程被阻塞,直到第二个实例到达为止。从而不能再执行文件更新的事件。
    这段代码本意是:解除对SIGMIN的阻塞并等待其第一次出现。

  • 解决办法
    为了避免这种情况,使用了sigsuspend的函数,将阻塞和挂起封装成一个原子 *** 作。

    进程:2
    	void handler(int num)
    	{
    		flag = 1;
    	}
    	int main(){
    		sigset_t prevMask,intMask;
    		struct sigaction sa;
    		sigemptyset(&intMask);
    		sigaddset(&intMask,SIGINT);
    		sigemptyset(&prevMask);
    		sa.sa_flags = 0;
    		sa.sa_handler = handler;
    		sigaction(SIGMIN,&sa,NULL);
    		while(1){
    			if(flag){
    				sigprocmask(SIG_BLOCK,&intMask,&prevMask);
    				/*以下为不希望被SIGMIN打断的关键代码*/
    				flag = 0;
    				read(fd,buff,128);
    				prase(buff);
    				update(json.config)
    				/*end 关键代码*/
    				/*恢复旧的掩码解除对SIGMIN的阻塞*/
    				sigsuspend(NULL);/*原子 *** 作*/
    				sigprocmask(SIG_BLOCK,&prevMask,NULL);
    			}
    		}
    	}
    
  • 深入理解sigsuspend函数
    信号【5】-理解sigsuspend


总结

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/921416.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-16
下一篇 2022-05-16

发表评论

登录后才能评论

评论列表(0条)

保存