[Repost] CPU context switch

CPU context switch

https://www.jianshu.com/p/87b8ec445c9c

 

Linux is a multitasking operating system that supports tasks that are much larger than the number of CPUs to run at the same time. Of course, these tasks are not actually running at the same time, but because the system assigns CPUs to them in a short time, causing the illusion that multiple tasks are running simultaneously.

Before each task runs, the CPU needs to know where the task is loaded and where to start running, that is, the system needs to help it set the CPU register and program counter (Program Counter, PC) in advance.

The CPU register is a small-capacity but extremely fast memory built into the CPU. The program counter is used to store the position of the instruction being executed by the CPU or the position of the next instruction to be executed. They are all the CPU must depend on the environment before running any task, so it is also called CPU context.

 

Knowing what a CPU context is, I think you can easily understand CPU context switching. CPU context switching is to save the CPU context (that is, CPU registers and program counters) of the previous task, then load the new task context into these registers and program counters, and finally jump to the new location pointed by the program counter To run a new task.

These saved contexts will be stored in the system kernel and loaded again when the task is rescheduled for execution. This will ensure that the original state of the task is not affected, making the task appear to run continuously.

I guess someone will say that CPU context switching is nothing more than updating the values ​​of CPU registers, but these registers are designed for fast running tasks. Why does it affect the CPU performance of the system?

Before answering this question, I wonder if you ever thought about what these "tasks" managed by the operating system are?

You might say that tasks are processes, or tasks are threads. Yes, processes and threads are the most common tasks. But beyond that, are there any other tasks?

Don't forget that the hardware trigger signal will cause the interrupt handler to be called, which is also a common task.

Therefore, depending on the task, CPU context switching can be divided into several different scenarios, namely process context switching, thread context switching, and interrupt context switching.

In this lesson, I will show you how to understand these different context switches and why they cause CPU performance related problems.

Process context switch

According to the privilege level, Linux divides the running space of the process into kernel space and user space, which correspond to Ring 0 and Ring 3 of the CPU privilege level in the figure below.

  • The kernel space (Ring 0) has the highest authority and can directly access all resources;
  • User space (Ring 3) can only access restricted resources, and cannot directly access hardware devices such as memory. It must be caught in the kernel through system calls to access these privileged resources.
 

From another perspective, that is to say, the process can run in both user space and kernel space. When a process runs in user space, it is called the user state of the process, and when it falls into kernel space, it is called the kernel state of the process.

The transition from user mode to kernel mode needs to be completed through system calls. For example, when we view the contents of a file, we need multiple system calls to complete: first call open () to open the file, then call read () to read the file content, and call write () to write the content to standard output, and finally Call close () to close the file.

So, has the CPU context switched during the system call? The answer is naturally yes.

The original user mode instruction position in the CPU register needs to be saved first. Then, in order to execute the kernel state code, the CPU register needs to be updated to the new location of the kernel state instruction. Finally, jump to the kernel mode to run the kernel task.

After the system call is completed, the CPU register needs to restore the original saved user state, and then switch to user space to continue the process. Therefore, in the process of one system call, two CPU context switches actually occurred.

However, it should be noted that during the system call, there will be no user-mode resources such as virtual memory, nor will it switch processes. This is different from what we usually call process context switching:

  • Process context switching refers to switching from one process to another.
  • The same process is always running during the system call.

Therefore, the system call process is usually called privilege mode switching, rather than context switching. But in fact, during the system call, the context switch of the CPU is still inevitable.

So, what is the difference between a process context switch and a system call?

First of all, you need to know that processes are managed and scheduled by the kernel, and process switching can only happen in kernel mode. Therefore, the context of the process includes not only user space resources such as virtual memory, stack, and global variables, but also the state of the kernel space such as the kernel stack and registers.

Therefore, the context switching of the process is one step more than when the system is called: before saving the kernel state and CPU register of the current process, the virtual memory and stack of the process need to be saved first; and the kernel of the next process is loaded After the state, you also need to refresh the virtual memory and user stack of the process.

As shown in the figure below, the process of saving and restoring context is not "free" and requires the kernel to run on the CPU to complete.

 

According to Tsuna's test report, each context switch requires tens of nanoseconds to microseconds of CPU time. This time is quite considerable, especially in the case of a large number of process context switches, it is easy to cause the CPU to spend a lot of time on the storage and restoration of resources such as registers, kernel stacks and virtual memory, which greatly shortens the real operation The time of the process. This is exactly what we talked about in the previous section, which is an important factor leading to an increase in average load.

In addition, we know that Linux uses TLB (Translation Lookaside Buffer) to manage the mapping relationship between virtual memory and physical memory. After the virtual memory is updated, the TLB also needs to be refreshed, and the memory access will also slow down accordingly. Especially on a multiprocessor system, the cache is shared by multiple processors. Refreshing the cache will not only affect the current processor process, but also affect the processes of other processors sharing the cache.

After knowing the potential performance problems of process context switching, let's look at when to switch process context. Obviously, the context needs to be switched when the process is switched. In other words, the context needs to be switched only when the process is scheduled. Linux maintains a ready queue for each CPU, sorts the active processes (that is, the processes that are running and waiting for the CPU) according to priority and the time to wait for the CPU, and then selects the process that needs the most CPU, that is, the highest priority and Wait for the process with the longest CPU time to run.

So, when will the process be scheduled to run on the CPU?

One of the easiest times to think of is when the process finishes execution and terminates. The CPU it used before will be released. At this time, it will take a new process from the ready queue and run it. In fact, there are many other scenarios that will also trigger process scheduling. Here I will sort out each one for you.

  • First, in order to ensure that all processes can be scheduled fairly, CPU time is divided into segments of time segments, and these time segments are allocated to each process in turn. In this way, when the time slice of a process is exhausted, it will be suspended by the system and switched to other processes that are waiting for the CPU to run.

  • Second, when the system has insufficient system resources (such as insufficient memory), the process cannot be run until the resources are satisfied. At this time, the process will also be suspended and the system schedules other processes to run.

  • Third, when the process actively suspends itself through the sleep function sleep, it will naturally be rescheduled.
  • Fourth, when a process with a higher priority is running, in order to ensure the operation of the high-priority process, the current process will be suspended and run by the high-priority process.

  • Finally, when a hardware interrupt occurs, the process on the CPU will be suspended by the interrupt, and the interrupt service routine in the kernel will be executed instead.

It is very necessary to understand these few scenarios, because once the performance problem of context switching occurs, they are the murderers behind the scenes.

Thread context switch

After talking about the context switching of the process, let's take a look at the thread-related issues.

The biggest difference between threads and processes is that threads are the basic unit of scheduling, while processes are the basic unit of resource ownership. To put it bluntly, the so-called task scheduling in the kernel, the actual scheduling object is a thread; and the process only provides resources such as virtual memory and global variables to the thread. So, for threads and processes, we can understand this:

  • When the process has only one thread, the process can be considered equal to the thread.

  • When a process has multiple threads, these threads will share the same virtual memory and global variables and other resources. These resources do not need to be modified during context switching.

  • In addition, threads also have their own private data, such as stacks and registers, which also need to be saved during context switching.

In this way, the context switching of the thread can actually be divided into two situations:

  • First, the two threads before and after belong to different processes. At this time, because the resources are not shared, the switching process is the same as the process context switching.
  • Second, the two threads before and after belong to the same process. At this time, because the virtual memory is shared, when switching, the resources of the virtual memory remain unchanged, and only the non-shared data such as the private data and registers of the thread need to be switched.

Here you should also find that although the same context switching, thread switching in the same process consumes less resources than switching between multiple processes, and this is also an advantage of multithreading instead of multiprocesses.

Interrupt context switch

In addition to the previous two context switches, there is also a scenario that also switches the CPU context, that is, interrupts.

In order to quickly respond to hardware events, interrupt processing interrupts the normal scheduling and execution of the process, and instead calls an interrupt handler to respond to device events. When interrupting other processes, you need to save the current state of the process, so that after the interruption, the process can still resume running from the original state.

Unlike process context, interrupt context switching does not involve the user state of the process. Therefore, even if the interruption process interrupts a process that is currently in user mode, there is no need to save and restore user process resources such as virtual memory and global variables of the process. The interrupt context actually includes only the states necessary for the execution of the kernel-mode interrupt service program, including CPU registers, kernel stack, and hardware interrupt parameters.

For the same CPU, interrupt processing has a higher priority than processes, so interrupt context switching does not occur simultaneously with process context switching. . In the same way, because interrupts interrupt the scheduling and execution of normal processes, most interrupt handlers are short and succinct, so that execution can end as soon as possible.

In addition, like process context switching, interrupt context switching also consumes CPU. Too many switching times will consume a large amount of CPU, and even seriously reduce the overall performance of the system. Therefore, when you find that there are too many interrupts, you need to pay attention to check whether it will bring serious performance problems to your system.

summary

To sum up, no matter what kind of scenario causes the context switch, you should know:

  1. CPU context switching is one of the core functions to ensure the normal operation of the Linux system, and generally does not require our special attention.

2. However, too many context switches will consume CPU time in the storage and restoration of data such as registers, kernel stacks, and virtual memory, thereby shortening the real running time of the process and causing the overall performance of the system to decrease significantly.

original

https://time.geekbang.org/column/article/69859

Guess you like

Origin www.cnblogs.com/jinanxiaolaohu/p/12687849.html