竞态条件和sigsupend函数

2023-12-03 15:32
文章标签 条件 函数 竞态 sigsupend

本文主要是介绍竞态条件和sigsupend函数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

竞态条件(race condition)是一个在设备或者系统试图同时执行两个操作的时候出现的不希望的状况,但是由于设备和系统的自然特性,为了正确地执行,操作必须按照合适顺序进行。 

好比我们在模拟实现sleep()函数时

#include <stdio.h>
#include <signal.h>
#include <unistd.h>void handler(int s)
{}int mysleep(int sec)
{signal(SIGALRM,handler);alarm(sec);pause();int r=alarm(0);return r;
}
int main()
{mysleep(3);printf("3 sec \n");return 0;
}

这样实现基本可以完成sleep的功能,但在极端情况下,cpu负载很高,当程序刚刚执行完alarm(sec);这行代码时,时间片切给了另外一个进程,等回来时,alarm的时间已经到了,这时直接处理SIGALRM信号,执行信号处理函数,这些都进行完毕,才来继续执行pause()这句代码,因为信号已经在pause之前被处理过了,所以会一直阻塞在pause这里,而我们想要的是在pause()挂起时经过若干秒被SIGALRM信号打断然后pause返回,显然这与我们想要的结果相悖。

首先我们想到的是使用信号屏蔽来解决,在执行pause()之前一直屏蔽SIGALRM信号,等到即将执行pause时再解除屏蔽,但是这种做法似乎没效果,因为时间片也有可能在解除屏蔽与pause执行的间隙被切换出去,和上边做法没区别。。。

系统为我们提供了这么一个函数sigsuspend
int sigsuspend(const sigset_t* mask);
它相当于pause+信号屏蔽,是pause的加强版,可以用来解决竞态问题。
它的功能是在该函数执行期间用参数中传递 的信号屏蔽集覆盖原来的信号屏蔽集,函数执行完毕后又恢复为原来的信号屏蔽集。

小试一把先:

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
void handler(int s)
{printf("recv %d\n",s);sleep(3);printf("finish\n");
}
int main()
{signal(SIGINT,handler);signal(SIGQUIT,handler);sigset_t set;sigemptyset(&set);sigaddset(&set,SIGINT);sigprocmask(SIG_BLOCK,&set,NULL);sigset_t pset;sigemptyset(&pset);sigaddset(&pset,SIGQUIT);sigsuspend(&pset);sigprocmask(SIG_UNBLOCK,&set,NULL);
}

这里写图片描述

这时我们使用这个函数来处理mysleep中的竞态问题,在执行sigsupend之前屏蔽SIGALRM信号,在sigsupend的参数中传一个空的信号屏蔽集,即取消SIGALRM的屏蔽,这样就能使SIGALRM信号一定能够在sigsupend期间被处理。

#include <stdio.h>
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void handler(int s)
{}int mysleep(int sec)
{signal(SIGALRM,handler);sigset_t set;sigemptyset(&set);sigaddset(&set,SIGALRM);sigprocmask(SIG_BLOCK,&set,NULL);alarm(sec);sigset_t pset;sigemptyset(&pset);sigsuspend(&pset);sigprocmask(SIG_UNBLOCK,&pset,NULL);int r=alarm(0);return r;
}
int main()
{mysleep(3);printf("3 sec\n");
}

这篇关于竞态条件和sigsupend函数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/449941

相关文章

Pandas中统计汇总可视化函数plot()的使用

《Pandas中统计汇总可视化函数plot()的使用》Pandas提供了许多强大的数据处理和分析功能,其中plot()函数就是其可视化功能的一个重要组成部分,本文主要介绍了Pandas中统计汇总可视化... 目录一、plot()函数简介二、plot()函数的基本用法三、plot()函数的参数详解四、使用pl

Python的time模块一些常用功能(各种与时间相关的函数)

《Python的time模块一些常用功能(各种与时间相关的函数)》Python的time模块提供了各种与时间相关的函数,包括获取当前时间、处理时间间隔、执行时间测量等,:本文主要介绍Python的... 目录1. 获取当前时间2. 时间格式化3. 延时执行4. 时间戳运算5. 计算代码执行时间6. 转换为指

Python正则表达式语法及re模块中的常用函数详解

《Python正则表达式语法及re模块中的常用函数详解》这篇文章主要给大家介绍了关于Python正则表达式语法及re模块中常用函数的相关资料,正则表达式是一种强大的字符串处理工具,可以用于匹配、切分、... 目录概念、作用和步骤语法re模块中的常用函数总结 概念、作用和步骤概念: 本身也是一个字符串,其中

Java中Switch Case多个条件处理方法举例

《Java中SwitchCase多个条件处理方法举例》Java中switch语句用于根据变量值执行不同代码块,适用于多个条件的处理,:本文主要介绍Java中SwitchCase多个条件处理的相... 目录前言基本语法处理多个条件示例1:合并相同代码的多个case示例2:通过字符串合并多个case进阶用法使用

shell编程之函数与数组的使用详解

《shell编程之函数与数组的使用详解》:本文主要介绍shell编程之函数与数组的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录shell函数函数的用法俩个数求和系统资源监控并报警函数函数变量的作用范围函数的参数递归函数shell数组获取数组的长度读取某下的

SpringBoot条件注解核心作用与使用场景详解

《SpringBoot条件注解核心作用与使用场景详解》SpringBoot的条件注解为开发者提供了强大的动态配置能力,理解其原理和适用场景是构建灵活、可扩展应用的关键,本文将系统梳理所有常用的条件注... 目录引言一、条件注解的核心机制二、SpringBoot内置条件注解详解1、@ConditionalOn

MySQL高级查询之JOIN、子查询、窗口函数实际案例

《MySQL高级查询之JOIN、子查询、窗口函数实际案例》:本文主要介绍MySQL高级查询之JOIN、子查询、窗口函数实际案例的相关资料,JOIN用于多表关联查询,子查询用于数据筛选和过滤,窗口函... 目录前言1. JOIN(连接查询)1.1 内连接(INNER JOIN)1.2 左连接(LEFT JOI

MySQL中FIND_IN_SET函数与INSTR函数用法解析

《MySQL中FIND_IN_SET函数与INSTR函数用法解析》:本文主要介绍MySQL中FIND_IN_SET函数与INSTR函数用法解析,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友一... 目录一、功能定义与语法1、FIND_IN_SET函数2、INSTR函数二、本质区别对比三、实际场景案例分

C++ Sort函数使用场景分析

《C++Sort函数使用场景分析》sort函数是algorithm库下的一个函数,sort函数是不稳定的,即大小相同的元素在排序后相对顺序可能发生改变,如果某些场景需要保持相同元素间的相对顺序,可使... 目录C++ Sort函数详解一、sort函数调用的两种方式二、sort函数使用场景三、sort函数排序

C语言函数递归实际应用举例详解

《C语言函数递归实际应用举例详解》程序调用自身的编程技巧称为递归,递归做为一种算法在程序设计语言中广泛应用,:本文主要介绍C语言函数递归实际应用举例的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录前言一、递归的概念与思想二、递归的限制条件 三、递归的实际应用举例(一)求 n 的阶乘(二)顺序打印