当前位置: 首页 > news >正文

Linux C库函数的可重入与不可重入版本说明

在多线程编程中,线程安全(Thread-Safety)是一个非常重要的概念,而可重入性(Reentrancy)是确保线程安全的一个关键因素。

C 标准库中的很多函数都存在可重入(Reentrant)和不可重入版本。在这些函数的命名上,不可重入的函数名称通常是简单的函数名,而可重入版本的函数名称后面通常带有 _r,表示该函数是设计为可重入的版本。

  • 不可重入函数:不可重入的函数通常依赖于共享的全局状态,或使用静态变量来存储中间结果。这使得当多个线程并发调用这些函数时,可能会发生数据竞争或资源争用,导致不安全的行为。

  • 可重入函数:可重入函数在设计上避免了共享状态的问题,它们通常只使用局部变量,或者通过传递上下文指针来存储状态,这样每个线程都拥有自己的副本,避免了竞争条件。

我们在 C 库中经常会遇到一些不可重入的函数,这些函数在多线程环境中可能会出现问题。例如:

  • asctime()asctime_r()
  • ctime()ctime_r()
  • localtime()localtime_r()

这些函数的 _r 版本是可重入的,并且能够在多线程环境下安全使用。

通过 man 手册,我们可以查询每个库函数的详细信息,其中包括其线程安全性标注。例如,执行 man 3 ctime 可以查看 ctime()ctime_r() 函数的详细信息。在这个手册页面的 "ATTRIBUTES" 部分,会显示每个函数是否是线程安全的。

函数的线程安全性通常会以 MT-SafeMT-Unsafe 标记:

  • MT-Safe(线程安全):表示该函数是多线程安全的,在多线程环境中可以同时被多个线程调用,而不会产生竞态条件或数据竞争。

  • MT-Unsafe(线程不安全):表示该函数不是线程安全的,如果多个线程同时调用该函数,可能会导致数据不一致或其他不安全行为。

值得注意的是,即使某些函数被标记为 MT-Safe,它们可能还带有一些附加条件(如 envlocale 标签)。这些条件表示在某些情况下,即使是可重入版本的函数,也可能会失去线程安全性。这种情况经常出现在依赖环境变量或区域设置(locale)的函数中。

例如,asctime_r()ctime_r()localtime_r() 等函数通常被标记为 MT-Safe env locale,这意味着这些函数在满足环境变量和区域设置相关条件时是线程安全的,但如果这些条件不满足(例如环境变量发生变化),它们可能仍然会出现线程不安全的情况。】

man 手册的 ATTRIBUTES 部分,经常可以看到 envlocale 等标签。通过 man 7 attributes 可以进一步查询这些标签的含义。虽然这个手册可能内容较为抽象,但通过理解这些标签,可以更好地判断函数的线程安全性。

  • env 标签表示该函数依赖于进程的环境变量。环境变量是全局的,多个线程共享同一个进程的环境变量,因此如果一个线程修改了环境变量,其他线程的读取行为可能会产生不可预知的结果。

    举例getenv() 函数会读取环境变量,由于环境变量是全局的,多个线程同时调用 getenv() 并不会产生冲突,但如果其中一个线程修改了环境变量(如调用 setenv()putenv()),其他线程的 getenv() 结果就可能变得不确定,因此这类函数是条件性线程安全的。

  • locale 标签表示该函数依赖于区域设置。区域设置(Locale)是一个进程级别的设置,控制着程序如何处理与语言和文化相关的信息,比如日期格式、货币符号、字符编码等。如果多个线程同时更改进程的区域设置,这些更改会影响所有线程。因此依赖区域设置的函数,虽然在某些条件下是线程安全的,但如果区域设置发生变化,可能会导致不安全的情况。

    举例setlocale() 函数用于设置或查询程序的当前区域设置。如果某个线程更改了区域设置,其他依赖区域设置的函数(如 strcoll())可能会受到影响,导致线程不安全。

有些函数是绝对线程安全的,意味着它们不依赖于任何共享资源,或者完全不会受到环境变量和区域设置的影响。例如数学库中的 sqrt() 函数。我们可以通过 man 手册查询到:

这里没有任何附加标签,比如 envlocale,表示该函数在任何情况下都是线程安全的。

需要强调的是,可重入函数并不一定就是线程安全的,虽然它们之间有很大的重叠。例如,函数如果只使用局部变量而不依赖全局状态,它通常是可重入的,但并不一定是线程安全的,特别是在函数内部涉及到系统调用时。

  • 可重入函数:可重入函数在每次调用时不会依赖外部状态(如全局变量、静态变量),即便是在中断上下文中或多个线程并发执行时,它也能安全执行。

  • 线程安全函数:线程安全函数意味着多个线程可以同时调用该函数而不会发生数据竞争或冲突,线程安全函数通常通过使用同步机制(如锁)来确保多个线程的正确执行。

让我们通过 ctime()ctime_r() 函数来具体说明不可重入函数和可重入函数的区别。

ctime():不可重入,它返回的字符串是存储在静态缓冲区中的,所有线程共享同一个缓冲区。如果多个线程同时调用 ctime(),会导致缓冲区数据被覆盖,结果不可靠。

#include <stdio.h>
#include <time.h>void* unsafe_function(void* arg) {time_t now = time(NULL);printf("ctime: %s\n", ctime(&now));  // 使用静态缓冲区,线程不安全return NULL;
}

ctime_r():可重入版本,允许用户传递一个缓冲区,线程之间不共享任何状态,因此是线程安全的。

#include <stdio.h>
#include <time.h>void* safe_function(void* arg) {time_t now = time(NULL);char buffer[26];  // 用户传入的缓冲区printf("ctime_r: %s\n", ctime_r(&now, buffer));  // 线程安全return NULL;
}

C 标准库中的很多函数都有可重入与不可重入版本。在多线程编程中,使用可重入函数是确保线程安全的关键之一,但可重入并不总是等同于线程安全。通过了解 man 手册中的 MT-SafeMT-Unsafe 标记,以及带有 envlocale 等条件性标签的含义,开发者可以更好地选择合适的函数来避免多线程环境中的潜在问题。


文章转载自:

http://ScNhZend.tkmLb.cn
http://r2jVzvmp.tkmLb.cn
http://jCu12DST.tkmLb.cn
http://caUN7SH5.tkmLb.cn
http://qXiIMsWF.tkmLb.cn
http://233tlmSX.tkmLb.cn
http://7TROyL72.tkmLb.cn
http://aBXuahOo.tkmLb.cn
http://MmeUBcbH.tkmLb.cn
http://aXQD6qOj.tkmLb.cn
http://FmsSUej5.tkmLb.cn
http://4n9NPPq5.tkmLb.cn
http://38ZYXD85.tkmLb.cn
http://CfkxeIgo.tkmLb.cn
http://NC3WDQKC.tkmLb.cn
http://fL5erpxh.tkmLb.cn
http://t2md8nwZ.tkmLb.cn
http://KOlfBvEA.tkmLb.cn
http://4IGYTCCo.tkmLb.cn
http://YpFLG7hX.tkmLb.cn
http://9C23vFXo.tkmLb.cn
http://mFRGKYbp.tkmLb.cn
http://881DnWZp.tkmLb.cn
http://0JWu219P.tkmLb.cn
http://fCv9ip5M.tkmLb.cn
http://4FXHwCYG.tkmLb.cn
http://nttXKG0L.tkmLb.cn
http://J284ELHd.tkmLb.cn
http://Qh0isrzy.tkmLb.cn
http://oFOlivNc.tkmLb.cn
http://www.dtcms.com/a/385303.html

相关文章:

  • ZooKeeper核心知识点总结:分布式系统的“协调者”
  • Unreal故障艺术之RGB颜色分离故障
  • 金融数据---东方财富人气榜-A股
  • 设计模式详解——创建型
  • Java 泛型与通配符全解析
  • Python变量与数据类型全解析:从命名规则到类型转换
  • 了解篇 | StarRocks 是个什么数据库?
  • 风险控制规则引擎:从敏捷开发工具到管理逻辑的承载者
  • 基于Matlab深度学习的植物叶片智能识别系统及其应用
  • AI编程从0-1开发一个小程序
  • Android原生的TextToSpeech,文字合成语音并播放
  • 【03】AI辅助编程完整的安卓二次商业实战-本地构建运行并且调试-二次开发改注册登陆按钮颜色以及整体资源结构熟悉-优雅草伊凡
  • 高德api使用
  • 工程造价指数指标分析:从数据采集到决策支撑的工程经济实践
  • 中控平台数据监控大屏
  • Vue 与 React 的区别?
  • 元图CAD:智能工程图纸解决方案的商业模型创新
  • MySQL 全量备份迁移步骤指南
  • 有关gitlab14.x版本在内网环境下无法添加webhooks的解决方法
  • O3.4 opencv摄像头跟踪
  • 数智管理学(五十二)
  • 121、【OS】【Nuttx】【周边】效果呈现方案解析:find 命令格式(上)
  • Python 3入门指南
  • I.MX6UL:EPIT
  • 企业数字化转型的 4A 架构指南:从概念解读到 TOGAF 阶段对应
  • Linux基础之部署mysql数据库
  • 【文献分享】空间互近邻关系在空间转录组学数据中的应用
  • 高精度、高带宽的磁角度传感器——MA600A
  • HarmonyOS服务卡片开发:动态卡片与数据绑定实战指南
  • HarmonyOS迷宫游戏鸿蒙应用开发实战:从零构建随机迷宫游戏(初版)