c 可重入函数,c++ 可重入函数

c 可重入函数,c++ 可重入函数,一篇文章带你了解C语言函数的可重入性

本文主要详细介绍了C语言函数的可重入性,非常详细,有一定的参考价值。感兴趣的朋友可以参考一下。

目录

I .不可重入函数。第二,可重入函数。三。如何编写可重入函数?可重入函数与线程安全的关系五、malloc和printf为什么不能重入?

一、不可重入函数。

如果我们在一个函数中使用了一个静态变量,这个函数可能在调用另一个函数的过程中被调用,导致中断,那么原来的静态变量在这里被改变,然后返回到主函数,使用的静态变量被改变,导致错误。这种函数称为不可重入函数。

在嵌入式系统的设计中,经常会出现多个任务调用同一个函数的情况。如果这个函数不幸被设计成不可重入的,那么当不同的任务调用这个函数时,调用这个函数的其他任务的数据可能会被修改,导致不可预知的后果。

在实时系统设计中,不可重入函数被认为是不安全的函数。

满足下列条件的函数多数是不可重入的:

(1)函数体使用静态数据结构;

(2)在函数体中调用malloc()或free()函数;

(3)在函数体中调用标准的I/O函数。

(4)不能中断的硬件寄存器在函数体中调用,比如串口收发寄存器。

二、可重入函数。

可重入函数可以被多个任务调用,而不用担心数据损坏。可重入函数可以随时中断,一段时间后可以重新运行,不会丢失相应的数据。

重新进入函数或只使用局部变量,即保存在CPU寄存器或堆栈中;或者如果使用了全局变量,应该保护全局变量。

如果函数是可重入的,它必须满足以下必要条件:

1.它不能包含静态(全局)非常数数据。

2.不能返回静态(全局)非常数数据的地址。

3.只能处理调用者提供的数据。作为可重入函数的输入参数,只能由调用者提供,提供的输入数据必须满足以上两个要求。

4.不能依赖单实例模式资源的锁。

5.不能调用不可重入的函数。在函数内部,尽量不要使用malloc和free方法来分配和释放内存。如果使用,通常会导致函数不可重入。

三、如何写出可重入的函数

1.写函数时尽量使用局部变量(比如寄存器和栈中的变量)。不要访问那些全局变量,也不要使用静态局部变量。

2.如果真的需要访问全局变量(包括静态),一定要注意实现互斥。可重入函数在并行运行环境中非常重要,但是访问全局变量通常会牺牲一些性能。在编写可重入函数时,如果使用了全局变量,应该通过关闭中断和信号量(即P和V操作)的方式对其进行保护。

四、函数的可重入性和线程安全的关系

重入和线程安全都与函数处理资源的方式有关。然而,它们之间也有一些不同之处。重入概念会影响函数的外部接口,而线程安全只关心函数的实现。

在大多数情况下,要将一个不可重入的函数变成可重入的函数,必须修改函数接口,以便所有数据都由函数的调用者提供。要把非线程安全的函数改成线程安全的,只需要修改函数的实现部分。通常,添加同步机制是为了防止共享资源被几个线程同时访问。

线程安全和可重入是两个不同的概念。

重入是指在单线程操作系统背景下,重入函数或子程序按照后进先出的线性顺序执行。对于多线程函数或子例程,每个线程的执行时间由操作系统调度,这是不可预测的。但是这个函数的每个线程都会时不时的获取CPU时间片,不断的推进执行进度。

可重入函数不一定是线程安全的;线程安全函数不一定是可重入的。例如,一个函数打开一个文件并读入数据。这个函数是可重入的,因为同时执行它的多个实例不会引起冲突;但是,它不是线程安全的,因为当文件被读入时,其他线程可能正在修改文件,所以为了线程安全,有必要给文件添加“同步锁”。

该函数使用锁定和解锁操作来访问其函数体内的共享资源,因此它是线程安全的,但不能被重入。如果此功能的一个实例在已执行锁定但未执行解锁时停止,并且系统启动此功能的另一个实例,则新实例将在锁定位置等待。如果这个函数是一个中断处理服务,中断处理期间的新中断将导致资源死锁。

五、malloc和printf为什么不可重入

Malloc和printf通常在内部使用全局结构和基于锁的同步。这就是为什么他们不能重新进入。

Malloc函数可以是线程安全的也可以是线程不安全的。两者都不能重新输入:

Malloc在全局堆上操作,两个并发的malloc调用可能返回同一个内存块。(第二个malloc调用应该在获取块的地址之前发生,但是该块没有被标记为不可用)。这违反了malloc的后置条件,所以这个实现不会重入。

printf函数也对全局数据进行操作。任何输出流通常使用一个附加到资源数据的全局缓冲区(终端或文件的缓冲区)。打印过程通常将数据复制到缓冲区,然后刷新缓冲区的序列。

总结

本文到此为止。希望能帮到你,也希望你能多关注我们的更多内容!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

相关文章阅读

  • vs2015打包安装程序,vs2015程序打包,VS2022实现VC++打包生成安装文件图文详细历程
  • vc++6.0的快捷键,vc 快捷键
  • vc++6.0的快捷键,vc 快捷键,VC6.0常用快捷键大全
  • 绘制圆角矩形的方法,c++ 画矩形,C#画圆角矩形的方法
  • 懒汉式和饿汉式代码,单列模式懒汉和饿汉,C++单例模式的懒汉模式和饿汉模式详解
  • 好用的C++编译器,c++编译软件哪个好
  • semaphore c#,c++ semaphore
  • semaphore c#,c++ semaphore,C++中Semaphore内核对象用法实例
  • dev-c++使用教程,dev c++安装教程
  • dev-c++使用教程,dev c++安装教程,Dev C++ 安装及使用方法(图文教程)
  • C里面指针常量和常量指针的区别,c++指针常量和常量指针
  • C里面指针常量和常量指针的区别,c++指针常量和常量指针,简单总结C++中指针常量与常量指针的区别
  • com组件初始化失败,c#开发com组件,C++中COM组件初始化方法实例分析
  • c++静态成员变量使用,c++静态成员函数和静态成员变量
  • c++静态成员变量使用,c++静态成员函数和静态成员变量,详解c++ 静态成员变量
  • 留言与评论(共有 条评论)
       
    验证码: