In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-03-26 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/01 Report--
Today, the editor will share with you the relevant knowledge points of the semaphore basic knowledge points of the FreeRTOS real-time operating system, which are detailed in content and clear in logic. I believe most people still know too much about this knowledge, so share this article for your reference. I hope you can get something after reading this article. Let's take a look at it.
1. Brief introduction of semaphore
The semaphore of FreeRTOS includes binary semaphore, counting semaphore, mutex semaphore (hereafter referred to as mutex) and recursive mutex semaphore (hereafter referred to as recursive mutex).
We can regard mutexes and recursive mutexes as special semaphores. Mutexes and semaphores differ in usage:
Semaphores are used for synchronization, between tasks or between tasks and interrupts; mutexes are used for interlocking to protect resources that can only be accessed by one task at a time, and to put a lock on resources.
When semaphores are used for synchronization, usually one task (or interrupt) gives the signal and another task acquires the signal; the mutex must get the signal in the same task and give the signal in the same task.
Mutexes have priority inheritance, semaphores do not.
Mutexes cannot be used in interrupt service programs, semaphores can.
The API function for creating a mutex is different from that for creating a semaphore, but it is common to get and give the signal API function.
two。 Binary semaphore
Binary semaphores can be used for both mutex and synchronization functions.
Binary semaphores and mutexes are very similar, but there are some subtle differences: mutexes contain a priority inheritance mechanism, while binary semaphores do not. This makes binary semaphores better used for synchronization (between tasks or between tasks and interrupts) and mutexes for simple mutexes. This section describes only the binary semaphores used for synchronization.
The semaphore API function allows you to specify a blocking time. When the task attempts to obtain an invalid semaphore, the task enters the blocking state, and the blocking time is used to determine the maximum time for the task to enter the blocking, and the blocking time is the system beat cycle time. If multiple tasks are blocked on the same semaphore, the task with the highest priority is the first to unblock when the semaphore is valid.
You can think of a binary semaphore as a queue with only one item (item), so the queue can only be empty or full (so it's called binary). Tasks and interrupts use queues without paying attention to who controls the queue-just need to know whether the queue is empty or full. Using this mechanism, you can synchronize tasks and interrupts.
Consider a situation where a task is used to maintain peripherals. Using polling can waste CPU resources and hinder the execution of other tasks. It is better to spend most of the time blocking (allowing other tasks to execute) and not executing the task until some event occurs. Binary semaphores can be used to implement this application: when a task takes a semaphore, because a specific event has not occurred and the semaphore is empty, the task will enter a blocking state; when the peripheral needs to be maintained, an interrupt service routine is triggered. The interrupt service only gives the semaphore (writing data to the queue). The task is only to take the signal, and does not need to be returned, the interruption of service is just to give the signal.
The priority of the task can be used to ensure that the peripheral is maintained in a timely manner. Queues can also be used instead of binary semaphores. Interrupt routines can capture data related to peripheral events and send it to the queue of tasks. The task unblocks when it finds that the queue data is valid, and if necessary, performs data processing. The second scheme makes the interrupt execution as short as possible, and other processes can be implemented in the task.
Note: the API function without the end of "FromISR" should never be used in interrupt programs.
Note: in most applications, task notifications can replace binary semaphores and are faster and generate less code.
Figure 1-1: synchronization between interrupts and tasks-using semaphores
As shown in figure 1-1, when the program starts running, the semaphore is invalid, so the task is blocked under this semaphore. After a period of time, an interrupt occurs and the API function xSemaphoreGiveFromISR () is used in the interrupt service program to give a signal, and the semaphore becomes valid. After exiting the interrupt service program, the context switch is performed, the task is unblocked, and the semaphore is taken away and the task is executed using the API function xSemaphoreTake (). Then the semaphore becomes invalid and the task enters blocking again.
3. Counting semaphore
Binary semaphores can be thought of as queues of length 1, while counting semaphores can be thought of as queues of length greater than 1. In addition, semaphore users do not have to care about the data stored in the queue, just whether the queue is empty or not.
Count semaphores are usually used for the following two events:
Count event: in this case, whenever an event occurs, the event handler will give a signal (the semaphore count value increases by 1), and when the event is processed, the handler will take the semaphore (the semaphore count value minus 1). Therefore, the count value is the difference between the number of events occurring and the number of events handled. In this case, the count semaphore has a value of 0 when it is created.
Resource management: in this usage, the count value represents the valid number of resources. The task must obtain the semaphore before it can gain control of the resource. When the count value is reduced to 00:00, there are no resources. When the task is completed, it returns the semaphore-the semaphore count increases. In this case, when the semaphore is created, the count value is equal to the maximum number of resources.
Note: the API function without the end of "FromISR" should never be used in interrupt programs.
Note: in most applications, task notifications can replace counting semaphores, and they are faster and generate less code.
4. Mutually exclusive quantity
A mutex is a binary semaphore that contains a priority inheritance mechanism. For synchronization (between tasks or between tasks and interrupts), binary semaphores are a better choice, and mutexes are used for simple interlocks.
Mutexes used for interlocking can act as tokens to protect resources. When a task wants to access a resource, it must first obtain a token. When the task has finished using the resource, it must return the token so that other tasks can access the same resource.
Mutexes and semaphores use the same API function, so mutexes also allow you to specify a blocking time. The blocking time unit is the system beat cycle time, and the number represents the maximum number of system beat cycles in the blocking state when the mutual exclusion is invalid.
The biggest difference between mutexes and binary semaphores is that mutexes have priority inheritance mechanism. In other words, if a mutex (token) is being used by a low-priority task, and a high priority tries to obtain the mutex, the high-priority task will enter the blocking state because it cannot get the mutex. The low-priority task that is using the mutex will temporarily raise its priority to the same priority as the high-priority task that enters the blocking state. This process of priority promotion is called priority inheritance. This mechanism is used to ensure that high-priority tasks enter the blocking state for as short as possible and to minimize the impact of "priority flipping" that has already occurred.
In many cases, there is only one hardware resource, and when the low-priority task occupies the resource, even the high-priority task can only obediently wait for the low-priority task to release the resources. Here, the phenomenon that high-priority tasks cannot run while low-priority tasks can run is called "priority flipping".
Why can priority inheritance reduce the impact of priority flipping? For example, there are now Task A, Task B, and Task C. the priority order of the three tasks is Task C > Task B > Task A. Both Task An and Task C use a hardware resource, and current task An occupies that resource.
First, look at the situation where there is no priority inheritance: task C also uses this resource, but task An is using this resource at this time, so task C enters blocking, and the priority order of the three tasks remains unchanged. After task C enters blocking, some hardware produces an interrupt that wakes up an event that unblocks task B. At the end of the interruption, task B preempts the CPU permissions of task A because task B has a higher priority than task A. Then the blocking time of task C is at least: interrupt processing time + running time of task B + running time of task A.
Let's look at the case of priority inheritance: task C also uses this resource, but task An is using this resource at this time, so task C enters blocking, and because priority An inherits the priority of task C. the priority order of the three tasks has changed, and the new priority order is: task C = task A > task B. After task C enters blocking, some hardware produces an interrupt that wakes up an event that unblocks task B. After the end of the interruption, task A continues to receive CPU privileges because the priority of task An is temporarily raised, which is greater than that of task B. When task A completes, task C, which is a high priority, takes over the CPU. So the blocking time of task C is: interrupt processing time + running time of task A. Look, task C has less blocking time, which is the advantage of priority inheritance.
Priority inheritance does not solve priority inversion and can only minimize the impact of this situation. Hard real-time systems should avoid priority reversal at the beginning of the design.
Figure 4-1 Mutex is used to protect resources
As shown in figure 4-1, mutexes are used to protect resources. In order to access resources, the task must first obtain mutexes. Task A wants to obtain resources. First, it uses the API function xSemaphoreTake () to obtain semaphores. After successfully obtaining semaphores, task A holds mutexes and can safely access resources. During this period, task B starts to execute, it also wants to access resources, task B also needs to get the semaphore first, but the semaphore is invalid at this time, and task B enters the blocking state. When task An is finished, use the API function xSemaphoreGive () to release the semaphore. Task B then unblocks, task B uses the API function xSemaphoreTake () to obtain and get the semaphore, and task B can access resources.
5. Recursive mutex
A task that has already obtained a recursive mutex can repeatedly get the recursive mutex. If you use the xSemaphoreTakeRecursive () function to successfully get a recursive mutex several times, you need to return it several times using the xSemaphoreGiveRecursive () function. Until then, the recursive mutex is in an invalid state. For example, if a task successfully gets a recursive mutex five times, the mutex is not valid for other tasks until it returns the recursive mutex five times.
Recursive mutexes can be regarded as semaphores with priority inheritance mechanism, and the task of obtaining recursive mutexes must be returned after use.
Mutexes cannot be used in interrupt service programs because:
Mutexes have a priority inheritance mechanism, which makes sense only when mutexes are obtained or given in the task.
Interrupts cannot be blocked by waiting for mutexes.
These are all the contents of this article entitled "what are the basic semaphore knowledge points of FreeRTOS real-time operating system?" Thank you for reading! I believe you will gain a lot after reading this article. The editor will update different knowledge for you every day. If you want to learn more knowledge, please pay attention to the industry information channel.
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: 240
*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.