什么是可重入函数

简介:

什么叫可重入:

可重入是一个并发下才有的概念。如果说,程序是串行的,自然也就不会有可重入这回事了。因为并发,所以任何个步骤都可能在运行中途被中断,然后跑另一个代码。这样就会出现一种可能,比如说两段代码都操作了一个全局变量,就会造成意想不到的错误。

可重入函数指的是,有多个线程在并发的执行一个函数。这个时候,如果两个函数会操作同一个全局的变量。这就是上面说的场景了。

什么样的函数不可重入:

  1. 函数体内使用了静态的数据结构(全局变量等)。
  2. 函数体内调用了malloc()或者free()函数
  3. 函数体内调用了标准I/O函数。

注意:malloc函数是不能并发使用的。

举个例子:

在网络开发中 经常出现需要从主机名得到ip地址的情况 这时就使用gethostbyname。很不巧的是,gethostbyname返回的是一个指向静态变量的指针,不可重入。 很可能刚要读时值就被其它线程修改。所以 新的posix中增加了另一个可重入域名解析的函数gethostbyname_r。

gethostbyname_r允许传入地址A和一个缓冲区的地址B,它会把主机信息写入到缓冲区中,然后在地址A上写入结构体,结构体中的指针指向缓冲区。这样实现了可重入,只要传入的缓冲区是独立的。

于是,这就成功引起了GHOST漏洞。关于这个漏洞,可参考《GHOST漏洞原理简单分析》。

另一个来自网上的例子:

A. 可重入函数

1 void strcpy(char *lpszDest, char *lpszSrc) {
2 while(*lpszDest++=*lpszSrc++);
3 *dest=0;
4 }

B. 不可重入函数1

1 char cTemp;//全局变量
2 void SwapChar1(char *lpcX, char *lpcY) {
3 cTemp=*lpcX;
4 *lpcX=*lpcY;
5 lpcY=cTemp;//访问了全局变量
6 }

C. 不可重入函数2

1 void SwapChar2(char *lpcX,char *lpcY) {
2 static char cTemp;//静态局部变量
3 cTemp=*lpcX;
4 *lpcX=*lpcY;
5 lpcY=cTemp;//使用了静态局部变量
6 }

 如何编写可重入的函数?

在函数体内不访问那些全局变量,不使用静态局部变量,坚持只使用局部变量,写出的函数就将是可重入的。如果必须访问全局变量,记住利用互斥信号量来保护全局变量。

  1. 不要使用全局变量。因为别的代码很可能覆盖这些变量值。
  2.  在和硬件发生交互的时候,切记执行类似disinterrupt()之类的操作,就是关闭硬件中断。完成交互记得打开中断,在有些系列上,这叫做“进入/退出核心”。
  3. 不能调用其它任何不可重入的函数
  4.  谨慎使用堆栈。最好先在使用前先OS_ENTER_KERNAL。(没用过,不懂)

总结:

其实,可重入函数和通常的并发编程遇到的问题是一样的,只是不那么容易发现。

我觉得并发编程最难的就是线程同步,就是要解决并发时引起的变量不确定性,还要尽可能高效。这就得靠程序员如何设计一个巧妙地数据结构了。

转载请注明:旅途@KryptosX » 什么是可重入函数

目录
相关文章
|
6月前
|
程序员
信号量和管程
信号量和管程
36 0
|
2月前
|
存储 Ubuntu Linux
C语言 多线程编程(1) 初识线程和条件变量
本文档详细介绍了多线程的概念、相关命令及线程的操作方法。首先解释了线程的定义及其与进程的关系,接着对比了线程与进程的区别。随后介绍了如何在 Linux 系统中使用 `pidstat`、`top` 和 `ps` 命令查看线程信息。文档还探讨了多进程和多线程模式各自的优缺点及适用场景,并详细讲解了如何使用 POSIX 线程库创建、退出、等待和取消线程。此外,还介绍了线程分离的概念和方法,并提供了多个示例代码帮助理解。最后,深入探讨了线程间的通讯机制、互斥锁和条件变量的使用,通过具体示例展示了如何实现生产者与消费者的同步模型。
|
2月前
|
Linux C语言
C语言 多进程编程(七)信号量
本文档详细介绍了进程间通信中的信号量机制。首先解释了资源竞争、临界资源和临界区的概念,并重点阐述了信号量如何解决这些问题。信号量作为一种协调共享资源访问的机制,包括互斥和同步两方面。文档还详细描述了无名信号量的初始化、等待、释放及销毁等操作,并提供了相应的 C 语言示例代码。此外,还介绍了如何创建信号量集合、初始化信号量以及信号量的操作方法。最后,通过实际示例展示了信号量在进程互斥和同步中的应用,包括如何使用信号量避免资源竞争,并实现了父子进程间的同步输出。附带的 `sem.h` 和 `sem.c` 文件提供了信号量操作的具体实现。
|
6月前
|
存储 安全 Linux
【C/C++ 可重入函数与不可重入函数】理解C/C++ 中函数的可重入性以及与线程安全性的关系
【C/C++ 可重入函数与不可重入函数】理解C/C++ 中函数的可重入性以及与线程安全性的关系
403 0
【C/C++ 可重入函数与不可重入函数】理解C/C++ 中函数的可重入性以及与线程安全性的关系
|
存储 缓存 安全
可重入函数与不可重入函数
可重入函数与不可重入函数
176 0
|
安全 Linux 调度
【Linux系统编程】可重入和不可重入函数
【Linux系统编程】可重入和不可重入函数
199 0
|
物联网 Linux 开发者
可重入函数|学习笔记
快速学习可重入函数
|
物联网 Linux 开发者
线程函数传参|学习笔记
快速学习线程函数传参
|
Linux
Linux系统编程-(pthread)线程通信(自旋锁)
自旋锁不管是内核编程,还是应用层编程都会用到;自旋锁和互斥量类似,它不是通过休眠使进程阻塞,而是在获取锁之前一直处于忙等(也就叫自旋)状态。
421 1
|
Linux
Linux系统编程-(pthread)线程通信(互斥锁)
这篇文章介绍Linux下线程同步与互斥机制--互斥锁,在多线程并发的时候,都会出现多个消费者取数据的情况,这种时候数据都需要进行保护,比如: 火车票售票系统、汽车票售票系统一样,总票数是固定的,但是购票的终端非常多。
448 0