澄清GNU C库如何定义不可重入函数。

huangapple go评论69阅读模式
英文:

Clarifying how GNU C Library defines nonreentrant functions

问题

我不明白上面的情况为什么是不可重入的。在我看来,gethostbyname 是一个(只读)获取函数,仅仅从内存中读取数据(而不是修改内存)。为什么 gethostbyname 是不可重入的呢?

英文:

Taken from: https://www.gnu.org/software/libc/manual/html_node/Nonreentrancy.html

> For example, suppose that the signal handler uses gethostbyname. This function returns its value in a static object, reusing the same object each time. If the signal happens to arrive during a call to gethostbyname, or even after one (while the program is still using the value), it will clobber the value that the program asked for.

I fail to see how the above scenario is non-reentrant. It seems to me that gethostbyname is a (read-only) getter function that merely reads from memory (as opposed to modifying memory). Why is gethostbyname non-reentrant?

答案1

得分: 1

根据这个词的含义,"reentrancy(可重入性)"指的是一个函数在被另一个线程调用的同时仍然可以被再次调用的能力。您提出的情景正是可重入性被实践的确切场合。假设这个函数有一些static或全局变量(就像gethostbyname(3)函数一样),由一个调用写入的结构的返回缓冲区,在被另一个调用时可能会被覆盖,从而完全破坏了第一个写入。当函数的正在执行实例(被中断的实例,而不是中断的实例)再次获得控制权时,它的所有数据都已被中断的实例覆盖并销毁。

解决这个中断问题的常见方法是在函数执行时禁用中断。这样它就不会被自身的新调用中断。

如果两个线程调用相同的代码片段,并且所有参数和局部变量都存储在堆栈中,那么每个线程都有自己数据的副本,因此同时调用两者不会有问题,因为它们触及的数据位于不同的堆栈中。这将不会发生在static变量上,不管是局部范围、编译单元范围还是全局范围(考虑问题是在调用相同的代码片段时出现的,因此无论一个调用有访问权限的地方,另一个也有)。

静态数据,比如缓冲区(查看stdio缓冲包装器等)等,一般意味着例程不可重入。

英文:

As the word says, reentrancy is the capability of a function to be able to be called again while it is being called in anothe thread. The scenario you propose is the exact place in which reentrancy is exercised. asume the function has some static or global variable (as the gethostbyname(3) function does) As the return buffer for the structure is being written by one, the other call can be overwriting it to completely destroy the first writing. When the in execution instance of the function (the interrupted one, not the interrumpting one) gets control again, all it's data has been overwritten by the interrupting one, and destroyed it.

A common solution to solve this problem with interruptions is to disable interrupts while the function is executing. This way it doesn't get interrupted by a new call to itself.

If two threads call the same piece of code, and all the parameters and local variables are stored in the stack, each thread has a copy of its own data, so there's no problem in calling both at the same time, as the data they touch is in different stacks. This will not happen with static variables, being those local scope, compilation unit scope or global scope (think that the problem comes when calling the same piece of code, so everywhere one call has access to, the other has also)

Static data, like buffers (look at stdio buffered packages) etc. means in general, the routines will not be reentrant.

huangapple
  • 本文由 发表于 2020年1月6日 15:34:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/59608267.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定