千家信息网

linux中时序竞态是什么意思

发表于:2024-10-01 作者:千家信息网编辑
千家信息网最后更新 2024年10月01日,这篇文章主要介绍linux中时序竞态是什么意思,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!时序竞态即由于进程之间执行的顺序不同,导致同一个进程多次运行后产生了不同结果的现象。
千家信息网最后更新 2024年10月01日linux中时序竞态是什么意思

这篇文章主要介绍linux中时序竞态是什么意思,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

时序竞态即由于进程之间执行的顺序不同,导致同一个进程多次运行后产生了不同结果的现象。

pause函数

函数原型:

int pause(void);

函数作用:

进程调用pause函数时,会造成进程主动挂起(处于阻塞状态,并主动放弃CPU),并且等待信号将其唤醒。

返回值:

我们知道,信号的处理方式有三种:1. 默认动作;2. 忽略处理;3. 捕捉。进程收到一个信号后,会先处理响应信号,再唤醒pause函数。于是有下面几种情况:

  • 如果信号的默认处理动作是终止进程,则进程将被终止,也就是说一收到信号进程就终止了,pause函数根本就没有机会返回;
  • 如果信号的默认处理动作是忽略,则进程将直接忽略该信号,相当于没收到这个信号,进程继续处于挂起状态,pause函数不返回;
  • 如果信号的处理动作是捕捉,则进程调用完信号处理函数之后,pause返回-1,errno设置为EINTR,表示"被信号中断"。
  • pause收到的信号不能被屏蔽,如果被屏蔽,那么pause就不能被唤醒。
因为alarm函数可以在设定的时间之后发送SIGALRM信号,pause函数又可以将进程挂起等待信号,则二者结合可以自己写一个sleep函数,如下:#include #include #include void sig_alrm(int signo){    /* nothing to do */}unsigned int mysleep(unsigned int nsecs){   unsigned int unslept;   signal(SIGALRM, &sig_alrm);   unslept = alarm(nsecs);   pause();   return unslept;}int main(void){   while(1){       mysleep(2);       printf("Two seconds passed\n");   }   return 0;}

时序竞态前导例

在讲时序竞态具体现象之前,我们先来看一个生活中常见的场景:

想午睡10分钟,于是定了个10分钟的闹钟,希望10分钟后闹钟将自己叫醒。

正常情况:定好闹钟,午睡,10分钟后闹钟叫醒自己;

异常情况:定好闹钟,躺下睡觉2分钟,被同学叫醒去打球,打了20分钟后回来继续睡觉。但在打球期间,闹钟早就响过了,将不会再唤醒自己。

这个例子与之后要讲的时序竞态有很大的相似之处。

时序竞态问题分析

我们再回过头来看上面所写的mysleep程序。这个函数有可能是下面的时序:

  • SIGALRM默认动作是终止进程,因此我们要将其捕捉,对SIGALRM注册信号处理函数;
  • 调用alarm(1)函数定时1秒钟;
  • alarm(1)调用结束,定时器开始计时。就在这时,进程失去CPU,进入就绪态等待CPU(相当于被同学叫醒去打球)。失去CPU的方式有可能是内核调度了优先级更高的进程取代了当前进程,使得当前进程无法获得CPU;
  • 我们知道,alarm函数如果采用自然定时法的话,定时器将一直计时,与进程状态无关。于是,1秒后,闹钟定时时间到,内核向当前进程发送SIGALRM信号。高优先级进程尚未执行完毕,当前进程仍然无法获得CPU,继续处于就绪态,信号无法处理(处于未决状态);
  • 优先级高的进程执行完毕,当前进程获得CPU资源,内核调度回当前进程执行。SIGALRM信号递达,并被进程处理;
  • 信号处理完毕后,返回当前主控流程,并调用pause()函数,挂起等待alarm函数发送的SIGALRM信号将自己唤醒;
  • 但实际SIGALRM信号已经处理完毕,pause()函数永远不会等到。

解决时序竞态问题

通过以上时序分析,我们可以看出,造成时序竞态的原因就是SIGALRM信号在进程失去CPU的时候就已经发送过来。为了防止这个现象出现,我们可以先将该信号阻塞,将其"抓住",再在解除阻塞的时候立刻调用pause函数挂起等待。这样即使在调用alarm就失去CPU,也可以在进程重新获得CPU时将抓到的SIGALRM信号重新"放出来",并将之后的pause函数唤醒。

但在解除阻塞与pause等待挂起信号之间,还是有可能失去CPU,除非将这两个步骤做成一个"原子操作"。Linux系统提供的sigsuspend函数就具备这个功能。所以,在时序要求比较严格的场合下都应该使用sigsuspend函数,而非pause函数。

函数原型:

int sigsuspend(const sigset_t *mask);

函数作用:挂起等待信号;

函数参数:mask,传入参数,sigsuspend函数调用期间,进程信号屏蔽字由参数mask指定。

具体用法:可将某个信号(如SIGALRM)从临时信号屏蔽字mask中删除,也就是在调用sigsuspend函数时对该信号解除屏蔽,然后挂起等待信号。但我们此时已经改变了进程的信号屏蔽字,所以调用完sigsuspend函数之后,应将进程的信号屏蔽字恢复原样。

#include#include#includevoid sig_alrm(int signo){    /* nothing to do */}unsigned int mysleep(unsigned int nsecs){   struct sigaction newact, oldact;   sigset_t newmask, oldmask, suspmask;   unsigned int unslept;   //1.为SIGALRM设置捕捉函数,一个空函数   newact.sa_handler = sig_alrm;   sigemptyset(&newact.sa_mask);   newact.sa_flags = 0;   sigaction(SIGALRM, &newact, &oldact);   //2.设置阻塞信号集,阻塞SIGALRM信号   sigemptyset(&newmask);   sigaddset(&newmask, SIGALRM);  sigprocmask(SIG_BLOCK, &newmask, &oldmask);   //信号屏蔽字 mask   //3.定时n秒,到时后可以产生SIGALRM信号   alarm(nsecs);   /*4.构造一个调用sigsuspend临时有效的阻塞信号集,    *  在临时阻塞信号集里解除SIGALRM的阻塞*/   suspmask = oldmask;   sigdelset(&suspmask, SIGALRM);   /*5.sigsuspend调用期间,采用临时阻塞信号集suspmask替换原有阻塞信号集    *  这个信号集中不包含SIGALRM信号,同时挂起等待,    *  当sigsuspend被信号唤醒返回时,恢复原有的阻塞信号集*/   sigsuspend(&suspmask);   unslept = alarm(0);   //6.恢复SIGALRM原有的处理动作,呼应前面注释1   sigaction(SIGALRM, &oldact, NULL);   //7.解除对SIGALRM的阻塞,呼应前面注释2   sigprocmask(SIG_SETMASK, &oldmask, NULL);   return(unslept);}int main(void){   while(1){       mysleep(2);       printf("Two seconds passed\n");   }return 0;}

可重入函数/不可重入函数

一个函数在被调用执行期间尚未调用结束的时候,由于某种时序,该函数又被重复调用,这种情况称为「重入」。如果从信号处理程序返回,则继续执行进程断点处的正常指令序列,从重新恢复到断点重新执行的过程中,函数所依赖的环境没有发生改变,就说这个函数是可重入的,反之就是不可重入的。

如果要将函数做成可重入函数,则函数内不能含有全局变量及static变量,也不能使用malloc、free。

以上是"linux中时序竞态是什么意思"这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注行业资讯频道!

信号 函数 进程 处理 时序 阻塞 闹钟 动作 信号处理 情况 状态 优先级 内核 参数 时候 现象 意思 不同 主动 之间 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 access数据库别名 软件开发运营公司尽职调查 防城港市计算机网络技术招工吗 语音嵌入式软件开发 福建语音网络技术标准 南京网络服务器机柜生产厂家 万方数据库课题检测 云服务器如何做安全防护 手机查看数据库文件位置 网上祭奠软件开发教程 静安区数据库安防系统销售方法 泡泡堂服务器连接中断 网络安全健康心得体会2000字 江汉网络安全展厅 南京中兴软件开发待遇怎么样 无线传感器网络技术课后题 国家网络安全宣传周线上论坛 视频服务器远程管理 移动互联网网络安全举例说明 三原县软件开发公司 在培训机构学习网络安全 淮安手机软件开发培训 防城港市计算机网络技术招工吗 数据库远程登录设置 数据库多对多的表 小学生网络安全课件下载 评论和回复数据库表计 数据库oem 华为软件开发工程师怎么入职 银川办公软件开发哪家做的好
0