linux thread switching and process switching methods

  • 2020-05-15 03:24:27
  • OfStack

Process switching is divided into two steps:

1. Switch page directories to use the new address space

2. Switch kernel stack and hardware context

For linux, the biggest difference between thread and process is the address space. For thread switching, step 1 is unnecessary, and step 2 is both process and thread switching.

Switching performance consumption:

One of the main differences between thread context switching and process up-down switching is that the virtual memory space for thread switching is still the same, but the process switching is different. Both of these context switches are handled through the operating system kernel. The most significant performance loss associated with this switching of the kernel is switching out the contents of the registers.

2. Another hidden loss is that context switching can disrupt the processor's caching mechanism. Simply put, once a context switch is made, all cached memory address 1 in the processor is instantly invalidated. Another significant difference is that when you change the virtual memory space, the processed page table buffer (processor's Translation Lookaside Buffer (TLB)) or something similar will be completely refreshed, which will cause memory access to be quite inefficient for a period of time. But in thread switching, this problem does not occur.

System call: in process context

System calls are in the context of a process and do not have delays such as tasklet. The system calls themselves can sleep, as you can see in the kernel code

While system calls are actually similar to other interrupt implementations, looking up entry handlers through the IDT table, the biggest difference between system calls and other interrupts is that the system call is executed on behalf of the current process, so the current macro /task_struct is meaningful, and the sleep can be awakened

System calls, exceptions, interrupts (where interrupts are asynchronous clocks, while exceptions are synchronous clocks), can also make system calls exceptions

Interrupt context: the environment on which execution in an interrupt depends, i.e. the interrupt context (not including system calls, but hardware interrupts)

Process context: when a process is executing, the values in all registers of CPU, the state of the process, and the contents of the stack are called the context of the process

1. First, both contexts are in the kernel space.

2. Second, the difference between the two is that the process context is closely related to the currently executing process, while the interrupt context is not logically related to the process.

The process context is primarily the exception handler and kernel threads. The kernel enters the process context because some of the process's own work needs to be done in the kernel. For example, system calls are for the current process, exceptions are usually handling the error state caused by the process, and so on. So it makes sense to reference current in a process context.

The kernel enters the interrupt context for interrupt processing or soft interrupts caused by interrupt signals. The occurrence of interrupt signal is random, and the interrupt handler and soft interrupt cannot predict which process is currently running when the interrupt occurs in advance, so it is ok to refer to current in the interrupt context, but it is meaningless. In fact, the interrupt signal that the A process wants to wait for may occur during the execution of the B process. For example, the A process starts the write disk operation, A process is running now after sleep, when the disk interrupt signal interrupts the B process after the disk is written, A process will wake up when the interrupt process is processed.

The word context brings to mind the CPU register state of a process, but it doesn't seem to make much difference what the kernel does when entering the process context (exception handling system call) and when entering the interrupt context (interrupt handling). So the main difference between the two contexts, I think, is process-related.

The kernel code running in the process context is preemptible, but the interrupt context runs straight to the end and is not preempted. Therefore, the kernel restricts the work of the interrupt context by not allowing it to do the following:

(1) go to sleep or give up CPU;

Because the interrupt context does not belong to any process, it has nothing to do with current (although at this point current is pointing to the interrupted process), it will not wake up when the interrupt context falls asleep or CPU is abandoned. So it's also called atomic context (atomic context).

(2) occupy the mutex;

To protect interrupt handle critical section resources, mutexes cannot be used. If no semaphores are obtained, the code will sleep, producing the same situation as above, and if locks must be used, spinlock will be used.

(3) perform time-consuming tasks;

Interrupt handling should be as fast as possible, because the kernel responds to a large number of services and requests, and an interrupt context that takes CPU too long can seriously affect system functionality. When time-consuming tasks are performed in an interrupt processing routine, they should be handled by the bottom half of the interrupt processing routine.

(4) access user space virtual memory.

Because the interrupt context is process-independent, it is the kernel running in kernel space on behalf of the hardware, so the virtual address in user space cannot be accessed in the interrupt context

(5) interrupt handling routines should not be set to reentrant (routines that can be called in parallel or recursively).

Because when an interrupt occurs, both preempt and irq are disable until the interrupt returns. So the interrupt context is not the same as the process context, and different instances of the interrupt handler routine are not allowed to run concurrently on SMP.

(6) interrupt handling routines can be interrupted by IRQ at a higher level. (can't nest interrupts) use soft interrupts, the upper part of the close interrupt, which means no nesting, and the lower part of the soft interrupt

If you want to disable such interrupts, you can define an interrupt handler routine as a quick-processing routine, which tells CPU that all interrupt requests on local CPU are disabled when the routine is run. As a direct result, system performance degrades as other interrupts are delayed in response.

Soft interrupts are a delay mechanism in which the code execution priority is higher than the process and lower than the hard interrupts. Compared to a hardware interrupt, soft in the middle is open in the environment of execution (long guan interrupt spends too much on the system), the code is executed in the interrupt/thread context, can't sleep, although each cpu has a corresponding ksoftirqd/n thread to perform the soft interrupt, but do_softirq this function will also exit in interrupt getting used, so you can't sleep (interrupt context can't sleep because is a scheduling system was based on the process of the basic unit, When scheduling the task_struct this data structure found in the current process of bump up and down, when the process was dispatched to perform when they find the execution breakpoints, but there is no specific task_struct structure interrupt context, there are, of course, the so-called thread interrupt, can satisfy the interrupt processing function performs blocking operation, but real time there may be a problem. There is also the concept of interrupt representing the execution of the current process, which I feel is a bit of a bullshit, after all, the entire kernel space is Shared by all processes, and there is no concept of representation.)

The above delayable function runs in the interrupt context (one checkpoint for soft interrupts is when do_IRQ exits), which leads to some problems: soft interrupts can't sleep and can't block. Because the interrupt context is in kernel state, there is no process switching, so if the soft interrupt is asleep or blocked, there is no way to exit this state, causing the entire kernel to die. However, blocking functions cannot be implemented in an interrupt context, but must be run in a process context, such as a function that accesses a block of disk data. Therefore, blocking functions cannot be implemented with soft interrupts. But they often have the property of being deferrable.


Related articles: