千家信息网

Linux中pause函数怎么用

发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,这篇文章主要为大家展示了"Linux中pause函数怎么用",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下"Linux中pause函数怎么用"这篇文章吧。##
千家信息网最后更新 2026年11月02日Linux中pause函数怎么用

这篇文章主要为大家展示了"Linux中pause函数怎么用",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下"Linux中pause函数怎么用"这篇文章吧。

##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   #include     void 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中pause函数怎么用"这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!

信号 函数 进程 处理 阻塞 时序 闹钟 动作 信号处理 情况 状态 优先级 内容 内核 参数 时候 篇文章 主动 也就是 作用 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 上海睿民互联网科技有限公司 互联网金融监管科技数据 互联网医疗科技 上海卓越科技 互联网 科技大学互联网专业好不好 广西拼得多互联网科技有限公司 老年人脱离互联网科技的作文 科技与互联网的利与弊 互联网系的金融科技公司 华服互联网科技官网 宜昌元轩互联网科技有限公司 消费医药和互联网科技 互联网在线教育科技创业 四川慕妮娅互联网科技有限公司 沐思想互联网科技有限公司 科技和互联网行业的特点 河南商务圈互联网科技有限公司 平安好医生打造互联网科技医疗 高科技和互联网的现代国家 株洲百竞科技的互联网营销顾问 河南真二互联网科技有限公司 互联网金融 科技 青岛中康互联网医疗科技有限公司 新华互联网科技2019 互联网为啥属于高科技 互联网科技革命什么开始 现代互联网科技公司 平安好医生打造互联网科技医疗 优雇互联网科技有限公司 互联网科技自媒体灵感
0