c – 为什么这个代码被认为是re​​etrant以及当操作系统中断线程时到底发生了什么?

前端之家收集整理的这篇文章主要介绍了c – 为什么这个代码被认为是re​​etrant以及当操作系统中断线程时到底发生了什么?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
以下是IBM称为可重入的代码片段:
/* reentrant function (a better solution) */
char *strtoupper_r(char *in_str,char *out_str)
{
  int index;

  for (index = 0; in_str[index]; index++)
    out_str[index] = toupper(in_str[index]);

  out_str[index] = 0

  return out_str;
}

对我来说,这段代码不可重入,因为循环计数器的索引是在本地定义的.如果操作系统在循环中中断此线程,并且另一个线程调用函数,则索引将丢失.我错过了什么?为什么这段代码被认为是可重入的?

操作系统在中断线程时是否将类似索引的局部变量的副本保存到线程的堆栈中,然后在处理继续时重新建立变量?

它似乎使这个函数可重入索引必须是接口的一部分作为调用者提供的存储.

解决方法

not reentrant because index for the loop counter is being defined locally. Should the OS interrupt this thread inside the loop,and another thread call this function,index would be lost. What am I missing? Why is this code considered reentrant?

当发生中断时,cpu本身将至少保存当前指令指针(可能是标志寄存器和一些段和堆栈寄存器,但它依赖于cpu),例如,(对于x86)基于特定内存地址处的函数指针表调用代码.可以期望这些中断处理程序保存(例如,推送到堆栈)他们想要使用的其他寄存器,然后在返回之前恢复它们.

每个线程都有自己的堆栈,所以这一切都挂起来了.

Does the OS save a copy of local variables like index on to a thread’s stack when it interrupts the thread and then reestablishes the variables when processing continues?

通常……要么保存到堆栈,要么某些cpu(例如Sparc)有注册窗口 – 相同的cpu操作码在中断处理程序运行时寻址不同的寄存器,然后上下文切换回程序正在使用的寄存器.

使用非堆栈数据可以阻止函数重入,例如函数体内的静态变量或某个全局变量/缓冲区.

猜你在找的C&C++相关文章