In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-15 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article mainly talks about "what are the knowledge points of Linux reentrant, asynchronous signal safety and thread safety". Interested friends may wish to take a look. The method introduced in this paper is simple, fast and practical. Let's let the editor take you to learn what are the knowledge points of Linux reentrant, asynchronous signal safety and thread safety.
Reentrant function
When a captured signal is processed by a process, the normal sequence of instructions executed by the process is temporarily interrupted by a signal processor. It first executes the instructions in the signal processor. If you return from a signal handler (for example, without calling exit or longjmp), continue to execute the normal sequence of instructions that the process was executing when the signal was captured (similar to what happens when a hardware interrupt occurs). But in the signal processor, we don't know where the process is executing when the signal is captured.
What happens if the process is using malloc to allocate extra memory on its heap and inserts and executes the signal handler because the signal is caught and malloc is called? Or what happens if the process is calling halfway through a function that stores the results in a static area, such as getpwnam, and we call the same function in the signal handler? In the case of malloc, the process can be severely damaged because malloc usually maintains a linked list of all its assigned areas, and the process may be changing the linked list when the insert executes the signal handler.
In the case of getpwnam, the information returned to the ordinary caller may be overwritten by the information returned to the signal processor.
SUS specifies that it must be guaranteed to be a reentrant function. The following table lists these reentry functions:
A reentrant function is simply a function that can be interrupted, that is, it can be interrupted at any time when the function is executed, and it can be transferred to OS to execute another piece of code without any error when returning to control. Reentrant functions can be used concurrently by more than one task without worrying about data errors. In contrast, non-reentrant (non-reentrant) functions cannot be shared by more than one task unless they are mutually exclusive (either using semaphores or disabling interrupts in critical parts of the code).
The reentrant function can be interrupted at any time and continue to run later without losing data. Reentrant functions either use local variables or protect their data when using global variables.
Signal security, in fact, that is, asynchronous signal security, that is, the thread in the signal processing function, no matter in any way to call your function if you do not deadlock does not modify the data, it is signal safety. Therefore, I think reentrant and asynchronous signal security is a concept.
Thread safety
Thread safety: a function is called thread safe, and it always produces correct results when and only when it is called repeatedly by multiple concurrent threads.
There is an important class of thread-safe functions called reentrant functions, which are characterized by the property that when they are called by multiple threads, they do not reference any shared data.
Although thread safety and reentrant are sometimes (incorrectly) used as synonyms, there are clear technical differences between them. A reentrant function is a true subset of thread-safe functions.
The difference and relationship between reentrant and thread safety
Reentrant function: reentry means repeated entry, first of all, it means that this function can be interrupted, and secondly, it means that it does not rely on any environment (including static) in addition to using variables on its own stack, such a function is purecode (pure code) reentrant, which allows multiple copies of the function to run, because they use separate stacks, so they will not interfere with each other.
Reentrant functions are thread-safe functions, but vice versa, thread-safe functions are not necessarily reentrant functions.
In fact, there are very few reentrant functions. There are only 115 reentrant functions described by Single UNIX Specification in Section 10.6 of APUE, and only 89 functions that cannot guarantee thread safety in POSIX.1 are described in Section 12.5 of APUE.
Signals, like hardware interrupts, interrupt the sequence of instructions that are being executed. The signal processing function cannot tell where the process runs when the signal is captured. If the operation in the signal processing function is the same as that of the interrupted function, and there is a static data structure in this operation, when the signal processing function returns (of course, what is discussed here is that the signal processing function can be returned), restoring the original execution sequence may cause the operation in the signal processing function to overwrite the data in the previous normal operation.
Several cases of non-reentrant
Use static data structures, such as getpwnam,getpwuid: if getpwnam is being executed when the signal occurs, the execution of getpwnam in the signal processor may overwrite the old value obtained by the original getpwnam
Call malloc or free: if the signal is malloc (modifying the linked table of storage space on the heap) when the signal occurs, the signal processor calls malloc, which destroys the data structure of the kernel
Use standard IO functions because many standard IO implementations use global data structures, such as printf (file offset is global)
Call longjmp or siglongjmp in the function: the program is modifying one data structure when the signal occurs, and the processor returns to another place, causing the data to be partially updated.
Even for reentrant functions, one problem to pay attention to when using in signal processing functions is errno. There is only one errno variable in a thread, and the reentrant function used in the signal processing function may also modify the errno. For example, the read function is reentrant, but it may also modify the errno. Therefore, the correct thing to do is to save the errno at the beginning of the signal processing function and restore the errno when the signal processing function exits.
For example, the program is calling printf output, but when calling printf, a signal appears, and the corresponding signal processing function also has a printf statement, which will cause the output of the two printf to be mixed together.
If the printf is locked, the same situation will lead to a deadlock. In this case, the method is generally used to block a certain signal in a specific area.
The method of blocking the signal:
Signal (SIGPIPE, SIG_IGN); / / ignore some signals sigprocmask (); / / sigprocmask is only pthread_sigmask () defined for single thread; / / pthread_sigmasks can be used in multithreading
Now it seems that the restrictions of signal asynchronous security and reentrant are the same, so they are treated as the same here.
Thread safety: a function is said to be thread-safe if it can be called safely by multiple threads at the same time. The Malloc function is thread safe.
When sharing is not needed, provide a dedicated copy of the data for each thread. If sharing is important, explicit synchronization is provided to ensure that the program operates in a determined manner. By including procedures in statements to lock and unlock mutexes, unsafe procedures can be turned into thread-safe procedures and can be serialized.
Many functions are not thread-safe because the data they return is stored in static memory buffers. By modifying the interface, the caller can provide a buffer to make these functions thread-safe.
When the operating system implements thread-safe functions, it will provide some replaceable thread-safe versions of some non-thread-safe functions in POSIX.1.
For example, gethostbyname () is thread-unsafe, and a thread-safe implementation of gethostbyname_r () is provided in Linux.
Add _ r after the function name to indicate that this version is reentrant (thread-safe for threads, but not for signal-handling functions, or asynchronous signal-safe).
Common negligence problems in multithreaded programs:
Pass the pointer to the caller stack as a parameter to the new thread.
A shared changeable state that accesses global memory without the protection of a synchronization mechanism.
A deadlock occurs when two threads try to take turns to gain permissions on the same pair of global resources. One thread controls the first resource, and the other thread controls the second resource. None of the threads can continue to operate until one of the threads abandons.
Attempt to reacquire the lock already held (recursive deadlock).
Create hidden intervals in synchronization protection. This interval occurs in protection if the protected code snippet contains a function that releases the synchronization mechanism and reacquires the synchronization mechanism before returning to the caller. The results are misleading. For the caller, the global data appears to be protected, but in fact it is not.
When mixing UNIX signals with threads, the sigwait (2) model is used to handle asynchronous signals.
Call setjmp (3C) and longjmp (3C), and then jump for a long time without releasing the mutex.
The condition cannot be reevaluated after it is returned from a call to _ cond_wait () or _ cond_timedwait ().
Summary
To judge whether a function is a reentrant function is to judge whether it can be interrupted or not, and the correct result can be obtained by resuming operation after interruption. (interrupting the sequence of executed instructions does not change the data of the function)
To judge whether a function is thread-safe or not is to determine whether it can ensure that each thread can get the correct result when multiple threads execute its instruction sequence at the same time.
If a function is reentrant for multiple threads, the function is thread-safe, but that does not mean that the function is also reentrant for signal handlers.
If the reentrant of the function to the asynchronous signal processor is safe, then the function can be said to be "asynchronous-signal safe".
Reentrant and thread-safe are two separate concepts, both related to the way the function handles resources.
First of all, reentrant and thread-safe are two different concepts. A function can be reentrant or thread-safe, can satisfy both, or neither (strictly speaking, there is a loophole in this description. See Article 2).
Secondly, from a set and logic point of view, reentrant is a subset of thread safety, and reentrant is a sufficient and necessary condition for thread safety. A reentrant function must be thread-safe, but it is not true.
Third, the definitions of reentrant and thread-safe concepts in POSIX:
Reentrant Function: A function whose effect, when called by two or more threads,is guaranteed to be as ifthe threads each executed thefunction one after another in an undefined order, even ifthe actual execution is interleaved.
Thread-Safe Function: A function that may be safely invoked concurrently by multiple threads.
Async-Signal-Safe Function: A function that may be invoked, without restriction fromsignal-catching functions. No function is async-signal-safe unless explicitly described as such
The relationship among the above three is: the reentrant function must be the thread safety function and the asynchronous signal safety function; the thread safety function is not necessarily the reentrant function.
The difference between reentrant and thread safety is reflected in whether it can be called in the signal handler. The reentrant function can be safely called in the signal handler, so it is also Async-Signal-Safe Function. The thread safety function does not guarantee that it can be safely called in the signal processing function. If you set the signal blocking set and other methods to ensure that a non-reentrant function will not be interrupted by the signal, then it is also Async-Signal-Safe Function.
It is worth mentioning that System Interface for POSIX 1003.1 is Thread-Safe by default, but not Async-Signal-Safe. The need for Async-Signal-Safe is clearly stated, such as fork () and signal ().
A non-reentrant function is usually (though not in all cases) judged by its external interface and usage. For example: strtok () is non-reentrant because it internally stores the string split by the tag; the ctime () function is also non-reentrant and returns a pointer to static data that is overwritten and rewritten in each call.
A thread-safe function implements multi-thread secure access to shared data by locking. The concept of thread safety is only related to the internal implementation of the function and does not affect the external interface of the function. In C, local variables are assigned on the stack. Therefore, any function that does not use static data or other shared resources is thread-safe.
In the current version of AIX, the following libraries are thread-safe:
C standard function library
BSD compatible function libraries
Using global variables is not thread-safe. Such information should be stored on a thread-by-thread basis so that access to data can be serialized. One thread may read the error code generated by another thread. In AIX, each thread has its own errno variable.
Finally, let's imagine a thread-safe but non-reentrant function:
Suppose the function func () needs to access a shared resource during execution, so in order to achieve thread safety, lock the resource before using it and unlock the resource without the need for it.
Suppose that during a certain execution of the function, after the resource lock has been obtained, an asynchronous signal occurs, and the execution flow of the program is transferred to the corresponding signal processing function. Assuming that the function func () also needs to be called in the signal processing function, then func () will still try to acquire the resource lock before accessing the shared resource in this execution, but we know that the previous func () instance has already acquired the lock, so the signal processing function is blocked-- on the other hand, the thread interrupted by the signal before the end of the signal processing function cannot resume execution, and of course there is no chance to release the resources. This creates a deadlock between the thread and the signal processing function.
Therefore, although func () can guarantee thread safety by locking, it is non-reentrant because of the function body's access to shared resources.
At this point, I believe you have a deeper understanding of "what are the knowledge points of Linux reentrant, asynchronous signal safety and thread safety". You might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.