线程安全 可重入函数

FatFs 应用接口函数 大多数API函数以枚举类型FRESULT返回常见的结果代码。FR_OK(成功),FR_DISK_ERR(下层disk_read、disk_write或disk_ioctl函数报告发生了不可恢复的硬盘错误。),FR_INT_ERR(断言失败,在内部流程中检测到异常),FR_NOT_READY(下层disk_initialize函数报告存储设备无法做好工作准备。),FR_NO_FILE(目录中没找到文件),FR_NO_PATH(在路径名中找不到目录。), 阅读详情
一个可重入的函数简单来说就是可以被中断的函数,也就是说,可以在这个函数执行的任何时刻中断它,转入OS调度下去执行另外一段代码,而返回控制时不会出现什么错误。
《多线程编程指南》中定义,可以被信号控制器安全调用的函数被称为"异步信号安全"函数。
因此,我认为可重入与异步信号安全是一个概念。

有人将可重入函数与线程安全函数混为一谈,我认为是不正确的。

这里引用CSAPP中的描述来说明一下:
--------------------------------------------------
CSAPP
13.7.1 线程安全
一个函数被称为线程安全的,当且仅当被多个并发线程反复的调用时,它会一直产生正确的结果。
13.7.2 可重入性
有一类重要的线程安全函数,叫做可重入函数,其特点在于它们具有一种属性:当它们被多个线程调用时,不会引用任何共享的数据。

尽管线程安全和可重入有时会(不正确的)被用做同义词,但是它们之间还是有清晰的技术差别的。可重入函数是线程安全函数的一个真子集。
--------------------------------------------------

重入即表示重复进入,首先它意味着这个函数可以被中断,其次意味着它除了使用自己栈上的变量以外不依赖于任何环境(包括static),这样的函数就是purecode(纯代码)可重入,可以允许有该函数的多个副本在运行,由于它们使用的是分离的栈,所以不会互相干扰。
可重入函数是线程安全函数,但是反过来,线程安全函数未必是可重入函数。
实际上,可重入函数很少,APUE 10.6节中描述了Single UNIX Specification说明的可重入的函数,只有115个;APUE 12.5节中描述了POSIX.1中不能保证线程安全的函数,只有89个。

信号就像硬件中断一样,会打断正在执行的指令序列。信号处理函数无法判断捕获到信号的时候,进程在何处运行。如果信号处理函数中的操作与打断的函数的操作相同,而且这个操作中有静态数据结构等,当信号处理函数返回的时候(当然这里讨论的是信号处理函数可以返回),恢复原先的执行序列,可能会导致信号处理函数中的操作覆盖了之前正常操作中的数据。
不可重入函数的原因在于:
1> 已知它们使用静态数据结构
2> 它们调用malloc和free.
因为malloc通常会为所分配的存储区维护一个链接表,而插入执行信号处理函数的时候,进程可能正在修改此链接表。
3> 它们是标准IO函数.
因为标准IO库的很多实现都使用了全局数据结构

即使对于可重入函数,在信号处理函数中使用也需要注意一个问题就是errno。一个线程中只有一个errno变量,信号处理函数中使用的可重入函数也有可能会修改errno。例如,read函数是可重入的,但是它也有可能会修改errno。因此,正确的做法是在信号处理函数开始,先保存errno;在信号处理函数退出的时候,再恢复errno。

例如,程序正在调用printf输出,但是在调用printf时,出现了信号,对应的信号处理函数也有printf语句,就会导致两个printf的输出混杂在一起。
如果是给printf加锁的话,同样是上面的情况就会导致死锁。对于这种情况,采用的方法一般是在特定的区域屏蔽一定的信号。
屏蔽信号的方法:
1> signal(SIGPIPE, SIG_IGN); //忽略一些信号
2> sigprocmask()
sigprocmask只为单线程定义的
3> pthread_sigmask()
pthread_sigmasks可以在多线程中使用

现在看来信号异步安全和可重入的限制似乎是一样的,所以这里把它们等同看待;-)

线程安全
线程安全:如果一个函数在同一时刻可以被多个线程安全的调用,就称该函数是线程安全的。

不需要共享时,请为每个线程提供一个专用的数据副本。如果共享非常重要,则提供显式同步,以确保程序以确定的方式操作。通过将过程包含在语句中来锁定和解除锁定互斥,可以使不安全过程变成线程安全过程,而且可以进行串行化。

很多函数并不是线程安全的,因为他们返回的数据是存放在静态的内存缓冲区中的。通过修改接口,由调用者自行提供缓冲区就可以使这些函数变为线程安全的。
操作系统实现支持线程安全函数的时候,会对POSIX.1中的一些非线程安全的函数提供一些可替换的线程安全版本。
例如,gethostbyname()是线程不安全的,在Linux中提供了gethostbyname_r()的线程安全实现。
函数名字后面加上"_r",以表明这个版本是可重入的(对于线程可重入,也就是说是线程安全的,但并不是说对于信号处理函数也是可重入的,或者是异步信号安全的)。

多线程程序中常见的疏忽性问题
1> 将指针作为新线程的参数传递给调用方栈。
2> 在没有同步机制保护的情况下访问全局内存的共享可更改状态。
3> 两个线程尝试轮流获取对同一对全局资源的权限时导致死锁。其中一个线程控制第一种资源,另一个线程控制第二种资源。其中一个线程放弃之前,任何一个线程都无法继续
操作。
4> 尝试重新获取已持有的锁(递归死锁)。
5> 在同步保护中创建隐藏的间隔。如果受保护的代码段包含的函数释放了同步机制,而又在返回调用方之前重新获取了该同步机制,则将在保护中出现此间隔。结果具有误导性。对于调用方,表面上看全局数据已受到保护,而实际上未受到保护。
6> 将UNIX 信号与线程混合时,使用sigwait(2) 模型来处理异步信号。
7> 调用setjmp(3C) 和longjmp(3C),然后长时间跳跃,而不释放互斥锁。
8> 从对*_cond_wait() 或*_cond_timedwait() 的调用中返回后无法重新评估条件。


总结
判断一个函数是不是可重入函数,在于判断其能否可以被打断,打断后恢复运行能够得到正确的结果。(打断执行的指令序列并不改变函数的数据)
判断一个函数是不是线程安全的,在于判断其能否在多个线程同时执行其指令序列的时候,保证每个线程都能够得到正确的结果。

如果一个函数对多个线程来说是可重入的,则说这个函数是线程安全的,但这并不能说明对信号处理程序来说该函数也是可重入的。
如果函数对异步信号处理程序的重入是安全的,那么就可以说函数是"异步-信号安全"的。
线程安全与可重入函数的区别 线程安全简述线程安全是指在多线程环境下,同一函数或函数库被不同线程调用,不会出现数据不一致的情况。另一篇博客线程安全与线程不安全,有一个小例子对比了线程安全与线程不安全。确定一个函数不是线程安全的: 函数中访问全局变量或者静态变量。 函数中动态分配或释放堆资源。 函数中使用了其他线程不安全的函数。 值得注意的是线程安全一定是在多线程环境*=下,在单线程(即只有一个线程的进程)环境中并不存在这个说法。 阅读详情

相关推荐

数字IC设计避坑指南:为什么477条net的DRV问题无法修复?解析don‘t touch hierarchy的影响

本文深入解析了数字IC后端实现中,因“don't touch hierarchy”约束导致大量DRV违规(如477条net)无法自动修复的根本原因。文章以Cadence Innovus工具为例,详细阐述了DRV修复机制与设计保护约束的冲突原理,并提供了从日志定位、风险评估到分级解除约束的完整实战策略,帮助工程师有效解决此类设计收敛难题。

hope8的博客 290

FreeRTOS下开启fatfs文件重入功能后,“Error:..\..\FreeRTOS\src\queue.c,1248“报错问题解决

默认FF_FS_REENTRANT=1 等待时长影响软件定时器功能,消除此问题:一. FreeRTOSconfig.h文件中,关闭软件定时器configUSE_TIMERS == 0;ffconfig.h文件中_FS_TIMEOUT可以不为0 二、configUSE_TIMERS == 1开启软件定时器时,ffconfig.h文件中 设置_FS_TIMEOUT=0 ...

weixin_42634914的博客 3344

LVGL 实战:虚拟列表与对象复用机制在嵌入式GUI中的性能优化

本文深入探讨LVGL虚拟列表与对象复用机制在嵌入式GUI中的性能优化实践。通过复用机制动态管理UI对象,大幅降低内存占用,实现无限滚动列表的流畅体验。文章详细解析核心算法、内存优化策略及跨平台适配技巧,帮助开发者在资源受限设备上高效处理大量数据展示。

rice5的博客 1106

在uC-OSII多个任务中使用FATFS的重入问题

FATFS文件系统,在多个任务都存在文件处理时,可能会因为任务调度导致在f_open函数执行过程中被其他任务抢断,导致文件系统中的FATFS fs变量的值会与当前任务处理文件的初始值不匹配,导致异常发生。 f_open打开文件操作 FRESULT f_open ( FIL* fp,/* Pointer to the blank file object...

梦想启航 3547

CST毫米波雷达ADAS仿真:从直角反射器到距离多普勒(RD图)的实战解析

本文通过CST Studio Suite实战解析毫米波汽车雷达ADAS仿真,详细演示了从构建直角反射器目标、参数化定义速度、进行参数扫描到生成距离多普勒图(RD图)的全过程。文章深入探讨了雷达关键参数(如距离分辨率、速度分辨率)的设计权衡与工程逻辑,并提供了单位统一、速度范围设定等实用避坑指南,帮助工程师高效完成雷达系统性能的前期验证与优化。

weixin_29292535的博客 502

Python自动化批量识别化学分子结构——从图片到SMILES/SDF的实战指南

本文提供了使用Python自动化批量识别化学分子结构图片的实战指南。详细对比了基于Molvec API的在线快速方案与本地部署OSRA工具的两种路径,包含完整的代码示例、环境配置及优化技巧,帮助化学研究者高效地将图片批量转换为SMILES或SDF格式,显著提升数据处理效率。

apple5的专栏 942

STM32实战总结:HAL之FatFS

STM32实战总结:HAL之FatFS

qq_28576837的博客 4061

【数据集】全球湿度数据集总结

【数据集】全球湿度数据集总结

WW、forever的博客 1661

ZZ可重入与异步信号安全

可重入与异步信号安全From:http://blog.chinaunix.net/u/12592/showart_1871048.html一个可重入的函数简单来说就是可以被中断的函数,也就是说,可以在这个函数执行的任何时刻中断它,转入OS调度下去执行另外一段代码,而返回控制时不会出现什么错误。《多线程编程指南》中定义,可以被信号控制器安全调用的函数被称为"异步信号安全"函数。因此,我认为可

自由程序员 726

高效计算斐波那契数列的C++实现及源码

斐波那契数列是一个非常经典的数学问题,通常递归方式计算斐波那契数列的时候会有很大的时间复杂度问题。首先,我们需要了解斐波那契数列的定义:斐波那契数列是指前两个数都为1,从第三个开始每个数都等于它前面两个数之和。因此,斐波那契数列的前几项为:1、1、2、3、5、8、13、21……在这个代码中,我们首先判断n是否特殊情况(即n等于0、1、2),然后通过循环计算得出对应的斐波那契数列值。通过这个例子,我们可以发现使用C++语言实现高效斐波那契数列计算的代码简单、易懂,并且时间复杂度相比递归方式有了很大的提升。

TechInk的博客 547

【项目实战】YOLOV5 +实时吸烟目标检测+手把手教学+开源全部

本原创项目长期更新,旨在完成校园异常行为实时精检测,做到集成+N次开发+优化(不止局限于调包)为止,近期将不断更新以下模型+数据+标注文件+教程。关注博主,Star 一下github,一起开始美妙的目标检测之路吧~~ 文章目录本原创项目长期更新,旨在完成校园异常行为实时精检测,做到集成+N次开发+优化(不止局限于调包)为止,近期将不断更新以下模型+数据+标注文件+教程。关注博主,Star 一下github,一起开始美妙的目标检测之路吧~~一、项目展示二、项目资源共享1:训练图片:香烟图片+吸烟手势+烟雾三、

cv君的博客 13万+

线程安全与可重入函数

一,什么是线程安全?1,线程安全就是说多线程访问同一代码,不会产生不确定的结果。换句话说,线程安全就是多线程访问时,采用加锁机制,当一个线程访问该类的某个数据时,用锁对数据进行保护,其他线程不能访问该数据直到该线程读取完,其他线程才可使用,线程安全不会出现数据不一致或者数据污染。反之, 线程不安全就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据。2,举个例子: 比如说

snow_5288的博客 1682

C# 调用高德地图关键词 API

今天我们要一起探索如何使用 C# 来调用高德地图的关键词搜索 API,从而实现精准的地理位置搜索功能。高德地图的关键词搜索 API 可以帮助我们轻松地实现这一点,它能够返回一系列匹配关键词的地点坐标和其他相关信息。通过简单的几行 C# 代码,我们就实现了调用高德地图关键词搜索 API 的功能。接下来,我们将在一个 C# 控制台应用中实现调用高德地图关键词搜索 API 的功能。此外,如果要在生产环境中使用,还需要考虑安全性问题,例如不要在客户端暴露 API 密钥。🔥关注墨瑾轩,带你探索编程的奥秘!

java专栏 1105

线程安全与可重入函数的区别与联系

线程安全线程安全是多个线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取结束并且释放了锁,其他线程才可使用,保证了数据的一致性。与之对应的则是线程不安全,对数据的访问不提供保护机制,导致多个线程先后更改数据造成数据的不一致问题,这是一个非常严重的问题。从之前的二元信号量到生产者消费者模型都存在很严重的线程不安全问题,不过那只是线程安全性问题的一...

ypt 3848

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

C:可重入函数 & 线程安全函数

线程安全:简单来说线程安全就是多个线程并发同一段代码时,不会出现不同的结果,我们就可以说该线程是安全的。 线程安全产生的原因:大多是因为对全局变量和静态变量的操作。 常见的线程不安全的函数: (1)不保护共享变量的函数; (2)函数状态随着被调用,状态发生变化的函数; (3)返回指向静态变量指针的函数; (4)调用线程不安全函数的函数; 常见的线程安全的情况: (1)每个线程对全局...

鱼藏剑 1741

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

可重入函数与线程安全

重入:当不同的控制流程调用同一个函数时,有可能当一个调用还没返回时,另一个调用就进入了该函数,将其称作重入; 不可重入函数:当一个函数由于可重入出错,则将此函数称为不可重入函数; 可重入函数:当一个函数由于可重入而不影响正确结果(其只访问自己的局部变量和参数),将此函数称作可重入函数; 举例:常见情况中,当程序正在执行到某一个函数中的某一条指令时,这时其收到了一个信号,于是其暂停执行去处理信

L_XRUI的博客 952

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

可重入函数和线程安全函数的区别

可重入函数:一个函数可以在任意执行流中调用,都不会出问题。 线程安全函数:一个函数在任意线程中调用,都不会有问题。 区别: 可重入包含更高,覆盖了线程安全。 如果一个函数是可重入函数,一定是线程安全的;一个函数线程安全,不一定可重入函数。 代码示例: #include <stdio.h> #include<pthread.h> //头文件 #include...

陌上人如玉,公子世无双。 531

线程安全和可重入函数

先说结论 可重入函数未必是线程安全的;线程安全函数未必是可重入的。 可重入函数的概念 可重入的程序(函数)允许在执行的过程中被打断,并在打断所执行的代码中再次安全的调用。 若一个函数是可重入的,则该函数应当满足下述条件: 不能含有静态(全局)非常量数据。 不能返回静态(全局)非常量数据的地址。 只能处理由调用者提供的数据。 不能依赖于单实例模式资源的锁。 调用(call)的函数也必需是可重入的。 总之一句话:上述条件就是要求可重入函数使用的所有变量都通过函数的调用者提供。 举例说明,设计一个发送字符串

sinat_31039061的博客 2663

【Linux】可重入函数和线程安全的区别与联系

*****可重入函数        函数被不同的控制流程调用,有可能在第一次调用还没返回时就再次进入该函数,这称为重入。在进行链表的插入时,insert函数访问一个全局链表,有可能因为重入而造成错乱,像这样的函数称为不可重入函数,反之,如果一个函数只访问自己的局部变量或参数,则称为可重入(Reentrant) 函数。 重入:即重复调用,函数被不同的流调用,有可能会出现第一次调用还没

Scenlyf的博客 5362

可重入函数和线程安全函数

线程安全函数  • 概念:  线程安全的概念比较直观。一般说来,一个函数被称为线程安全的,当且仅当被多个并发线程反复调用时,它会一直产生正确的结果。  • 确保线程安全:  要确保函数线程安全,主要需要考虑的是线程之间的共享变量。属于同一进程的不同线程会共享进程内存空间中的全局区和堆,而私有的线程空间则主要包括栈和寄 存器。因此,对于同一进程的不同线程来说,每个线程的局部变量都是私有的,而

crazy_programmer_p的专栏 733

线程安全函数和可重入函数的区别

线程安全: 线程安全函数:在C语言中局部变量是在栈中分配的,任何未使用静态数据或其他共享资源的函数都是线程安全的。 使用全局变量的函数是非线程安全的。 使用静态数据或其他共享资源的函数,必须通过加锁的方式来使函数实现线程安全。 线程安全的(Thread-Safe): 如果一个函数在同一时刻可以被多个线程安全地调用,就称该函数是线程安全的。 ...

肖邦的夜曲的专栏 1306

【Linux】线程安全与可重入函数

【Linux学习】:在Linux的一段时间学习中,刚开始是模糊的,所以很久没有进行博客的整理,直到最近自己把Linux的学习从前往后回忆与联系清楚了,觉得是时候整理成博客,变为自己的学习笔记了,先从线程安全和可重入函数整理,一方面是趁热打铁,另一方面是在这篇博客中,其实嵌套着前面的学习!第一部分: 线程安全最直接的概念,不管是从网上查阅资料还是书上看到的,都会有这么一句:一般来说,一个函数是线程安全

John的博客 1522

可重入函数与线程安全函数

可重入函数与线程安全函数顶嵌(TOP-E)|嵌入式linux企业培训|嵌入式Linux就业实训|承接嵌入式项目开发   2009-01-23 12:02:59 作者:顶嵌开源 来源:原创 文字大小:[大][中][小]可重入函数(reentrant function)与线程安全函数(thread-safe function)有时

李亚锋老师 1282
上一篇: 可重入函数和线程安全函数
下一篇: unix 环境高级编程 文件对象互斥flockfile()与funlockfile()
crazy_programmer_p
博客等级 码龄12年 21粉丝 23原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值