英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论