c语言 重新输入,C语言函数重新输入

C语言函数重新输入

由于使用了不受保护的系统资源(例如全局变量区,中断向量表),因此除非确保相互排斥(使用信号灯/代码的关键部分禁止中断),否则无法在多任务环境中运行等

重入函数:

没有静态数据结构不会返回指向静态数据的指针. 所有函数数据均由函数调用者提供. 使用自动变量,或通过复制全局变量来保护全局变量. 如果必须访问全局变量,请使用互斥信号来保护它们. 调用非可重入函数

不可重入函数为:

如果函数在重入条件下使用不受保护的共享资源,则该函数是不可重入的.

函数中使用静态变量,无论它是全局静态变量还是局部静态变量. 该函数返回一个静态变量. 在函数中调用非可重入函数. 函数中使用静态数据结构. 在函数中调用malloc()或free()函数. 该函数调用其他标准I / O函数. 该函数是单例中的成员函数. 并使用不使用线程独立存储的成员变量

将非可重入函数重写为可重入函数:

1. 不要使用全局变量

2. 当与硬件交互时可能发生中断时ccriticalsection对应c语言,请先关闭该中断(某些系列称为“进入/退出内核”或使用OS_ENTER_KERNAL / OS_EXIT_KERNAL来描述,这是关键部分的保护)

3. 不要调用非可重入函数

4. 小心使用堆栈,最好在使用前使用OS_ENTER_KERNAL

中断是嵌入式系统的重要组成部分,这导致许多编译器开发人员提供了扩展,该扩展允许标准C支持中断. ISR:

错误:

1,ISR没有返回值

如果它具有返回值,并返回给谁,则某种中断源将生成一个中断,并且系统将使用ISR进行处理. ISR链接到某个中断源,并且中断源的生成是随机的. 因此,ISR没有固定的调用方和固定的返回地址,因此返回值没有用.

2,ISR无法传递参数

3. 在许多编译器/处理器中,浮点数不是可重入的. 有些不允许在ISR中进行浮点运算.

4. ISR应该简短有效. 进行浮点数运算是不明智的.

5,printf是不可重入函数.

说明:

1. 浮点数: 通常,浮点操作由专用硬件执行. 例如,假设有一个名为FLOAT的硬件寄存器,用于计算和存储浮点数的中间运算结果.

假设有这样的功能

如果是第一次执行,则浮点运算的结果会暂时存储在FLOAT寄存器中,并在此时被中断,并且中断函数或其他进程也将调用fun函数,这是第二次调用的fun函数将在执行过程中破坏第一个FLOAT寄存器中的结果,因此,当返回第一个fun函数时,结果将不正确.

2,printf功能

引用全局变量stdout,它是标准输入和输出流的对象

malloc --------全局内存分配表

免费--------全局内存分配表

Unix通常具有可重入的函数版本,其名称后缀_r

这种情况发生在多任务系统中. 当在任务执行期间捕获并处理信号时,信号处理程序会暂时中断该过程正在执行的指令序列. 如果从信号处理程序返回,它将继续在过程断点处执行正常的指令序列. 从恢复到断点重新执行,函数所依赖的环境没有改变,可以说该函数是可重入的. 否则它不是可重入的.

众所周知,在进程中断期间,系统会保存并恢复进程的上下文,但是恢复的上下文仅限于少数上下文,例如返回地址,cpu寄存器等,以及内部诸如全局或静态变量,缓冲区等函数. 它不受保护,因此如果在函数中断期间这些值发生变化,则当函数返回到断点以继续执行时结果将不可预测. 例如,对于malloc,例如,某个进程当前正在执行malloc以分配堆空间. 此时,程序捕获信号中断. 信号处理程序中还有一个malloc. 这将对流程环境造成损害,因为Malloc通常会为其分配的存储区维护一个链接表. 在插入和执行信号处理功能时,该进程可能正在此表上运行,并且信号处理功能的调用仅覆盖了该过程的操作,从而导致错误.

以下大多数条件是不可重入函数:

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

(2)称为malloc或free;

(3)调用标准I / O函数;标准io库的许多实现都以不可重入的方式使用全局数据结构.

(4)进行了浮点运算. 在许多处理器/编译器中,浮点运算通常是不可重入的(浮点运算通常使用协处理器或软件仿真来实现.

1)信号处理程序A在内部和外部调用相同的不可重入函数B; B在执行过程中被信号中断并进入A(在A中调用B),并在完成后返回到B的中断点以继续执行. 这时,B函数的环境可能会更改,结果是不可预测的

2)多个线程在进程内部共享资源. 如果两个线程A和B调用相同的不可重入函数F,则程A进入F之后,该线程被调度为切换到B,并且B也执行F. 再次切换到线程A时,调用F的结果也是意外的

请注意,即使在信号处理程序中调用可重入函数也存在问题. 通常,在信号处理程序中调用可重入函数时,应先保存errno,然后再保存errno. (因为每个线程只有一个errno变量,所以信号处理函数可以修改其值. 要了解经常捕获的信号是SIGCHLD,它的信号处理程序通常调用wait函数,并且可以更改所有wait函数. errno. ) / p>

可重入功能列表:

_exit(),access(),警报(),cfgetispeed(),cfgetospeed(),cfsetispeed(),cfsetospeed(),chdir(),chmod(),chown(),close(),creat() ,Dup(),dup2(),execle(),execve(),fcntl(),fork(),fpathconf(),fstat(),fsync(),getegid(),geteuid(),getgid(),getgroups) (),Getpgrp(),getpid(),getppid(),getuid(),kill(),link(),lseek(),mkdir(),mkfifo(),open(),pathconf(),pause()) ,Pipe(),raise(),read(),重命名(),rmdir(),setgid(),setpgid(),setsid()ccriticalsection对应c语言,setuid(),sigaction(),sigaddset(),sigdelset(),sigemptyset) (),Sigfillset(),sigismember(),signal(),sigpending(),sigprocmask(),sigsuspend(),sleep(),stat(),sysconf(),tcdrain(),tcflow(),tcflush() ,Tcgetattr(),t cgetpgrp(),tcsendbreak(),tcsetattr(),tcsetpgrp(),time(),times(),umask(),uname(),unlink(),utime(),wait(), waitpid(),写().

在本书的信号处理程序中调用非重入函数的示例:

#include

#include

#include

静态无效函数(int signo)

{

struct passwd * rootptr;

if(((rootptr = getpwnam(“ root”))== NULL)

{

err_sys(“ getpwnam错误”);

}

信号(SIGALRM,函数);

警报(1);

}

int main(int argc,char ** argv)

{

信号(SIGALRM,函数);

警报(1);

对于(;;)

{

if(((ptr = getpwnam(“ sar”))== NULL)

{

err_sys(“ getpwnam错误”);

}

}

返回0;

}

给SIGALRM信号,然后设置一个计时器. 在for函数的执行过程中的某个时刻,也许相应的信号在getpwnam函数的运行过程中被中断,进入信号处理函数func,并在运行期间再次接收. 很容易遇到意想不到的问题.

================================================ ==== ==================================

不可重入函数在返回之前不能再次调用. 例如,printf,malloc,free等是不可重入的函数. 因为中断可能随时发生,例如在执行printf期间,您不能在中断处理程序中调用printf,否则将重新输入printf.

大多数函数都不是可重入的,因为在函数中引用了全局变量. 例如,printf将引用全局变量stdout,malloc,并自由引用全局内存分配表.

个人理解: 如果发生中断,则在运行至printf时,假定发生了中断嵌套,并且此时已占用stdout资源,因此第二个中断printf等待第一个中断stdout资源的释放. 中断正在等待第二个中断返回,从而导致死锁. 我不知道这是否正确.

非重入函数表示如果在调用函数之前再次调用该函数,则可能会产生错误. 可重入函数不存在此问题.

非重入函数通常在实现时使用全局资源. 在多线程环境中,如果不能很好地处理数据保护和互斥访问,则会发生错误.

常见的不可重入功能为:

printf --------参考全局变量stdout

malloc --------全局内存分配表

免费--------全局内存分配表

在Unix中,通常存在带有_r后缀的同名重入函数版本. 如果没有,请尝试在可预见的地方添加保护锁同步机制等.

本文来自电脑杂谈,转载请注明本文网址:

http://www.pc-fly.com/a/jisuanjixue/article-150757-1.html

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值