Before talking about the process context, the interrupt context, and the atomic context, it is necessary to discuss the following two concepts:
A--context
The context is translated from English ContexT, which refers to an environment . in relation to the process, it is the environment when the process executes;
In particular, variables and data, including all register variables, process open files, memory information, and so on.
B--Atomic
Atom (Atom) is intended to be "the smallest particle that cannot be further divided", while atomic manipulation (atomic operation) means "one or a series of operations that cannot be interrupted";
First, why there is the concept of context
Kernel space and user space are two working modes of modern operating system, kernel modules run in kernel space, while user-state applications run in user space. They represent different levels and have different access rights to system resources. Kernel modules run at the highest level (kernel state), and all operations under this level are trusted by the system, and the application runs at a lower level (user state). At this level, the processor controls direct access to the hardware and non-authorized access to the memory. The kernel state and the user state have their own memory map, which is their own address space.
Where the processor is always in one of the following states:
kernel state , running in the process context , the kernel represents the process running in the kernel space;
kernel state , running in the interrupt context , the kernel represents the hardware running in the kernel space;
User state , running in user space.
Context switching, user space and kernel space with different address mappings, universal or dedicated register group, and user space process to pass a lot of variables, parameters to the kernel, the kernel also to save the user process of some registers, variables, etc., so that the system call back to the user space to continue to execute,
Second, process context
The so-called process context is the value of all registers of the CPU, the state of the process, and the contents on the stack when a process executes, and when the kernel needs to switch to another process, it needs to save all the state of the current process, that is, to save the process context of the current process so that it can execute the process again. Ability to resume the state of the switchover and continue execution.
The context of a process can be divided into three parts: a user-level context , a register context , and a system-level context .
User-level context: body, data, user stack, and shared storage;
Register Context: Universal Register, Program Register (IP), processor status register (eflags), stack pointer (ESP);
System-Level context: Process Control block task_struct, memory management information (mm_struct, Vm_area_struct, PGD, Pte), kernel stacks.
When process scheduling occurs, process switching is context switch.
The operating system must switch all the information mentioned above before the newly scheduled process can run. The system call is a mode switch. Mode switching is much easier compared to process switching, and saves time because the main task of mode switching is to switch the process register context .
The process context is primarily exception handlers and kernel threads. The kernel enters the process context because some of the work of the process itself needs to be done in the kernel. For example, a system call is serviced for the current process, and the exception is usually the error state caused by the processing process, and so on. Therefore, it makes sense to refer to current in the context of a process.
Third, interrupt context
The hardware sends the interrupt signal to the CPU by triggering the signal, causing the kernel to call the interrupt handler and enter the kernel space. In this process, some variables and parameters of the hardware are also passed to the kernel, and the kernel is interrupted by these parameters.
Therefore,the "interrupt context" can be understood as the hardware passed over these parameters and the kernel needs to save some environment, mainly the environment of the interrupted process.
The kernel enters the interrupt context because of interrupt processing or soft interrupts caused by the interruption of the signal. It is possible to refer to current in the context of an interrupt if the interrupt signal is random, the interrupt handler and the soft interrupt do not anticipate which process is currently running at the time the interrupt occurred, but it is meaningless.
In fact, the interrupt signal that a process wants to wait for may occur during the execution of the B process. For example, a process initiates a write disk operation, a process sleeps after the B process is running, and when the disk is finished, the disk interrupt signal interrupts the B process, which wakes up the a process when it interrupts processing.
Iv. Process Context VS Interrupt context
the kernel can be in two contexts: the process context and the interrupt context.
After the system call, the user application enters the kernel space, after which the kernel space is run on the process context for the representative of the corresponding process for the user space.
An asynchronous interrupt causes the interrupt handler to be called, and the interrupt handler runs in the interrupt context.
The kernel restricts the operation of the interrupt context and does not allow it to do the following:
A--go to sleep or actively abandon the CPU
Since the interrupt context does not belong to any process, it has nothing to do with current (although at this point the current points to the interrupted process), the interrupt context cannot be awakened once it sleeps or discards the CPU. Therefore also called Atomic context (atomic context).
B--Occupy the mutex
in order to protect the interrupt handle critical section resource, you cannot use mutexes. If the semaphore is not available, the code will sleep, producing the same situation as above and using spinlock if the lock must be used.
C-Perform time-consuming tasks
Interrupt processing should be as fast as possible, because the kernel responds to a large number of services and requests, and the interrupt context takes too long CPU time to severely affect system functionality. When performing time-consuming tasks in an interrupt-handling routine, it should be referred to the bottom half of the interrupt handling routine.
D--access to user space virtual memory
because the interrupt context is independent of a particular process, it is the kernel that is running in kernel space on behalf of the hardware, so the virtual address of the user space cannot be accessed in the interrupt context
E--Interrupt processing routines should not be set to reentrant (routines that can be called in parallel or recursively)
Because the interrupt occurs, both the preempt and the IRQ are disable until the interrupt is returned. So the interrupt context is not the same as the process context, and the different instances of the interrupt processing routines are not allowed to run concurrently on the SMP.
F--Interrupt handling routines can be interrupted by a higher level of IRQ
If you want to prohibit this interruption, you can define the interrupt processing routine as a fast-processing routine, which is equivalent to telling the CPU that the routine is running and that all interrupt requests on the local CPU are blocked. As a direct result, the performance of the system degrades due to the delayed response of other interrupts.
V. Atomic context
One of the basic tenets of the kernel is that in the context of interrupts or atoms, the kernel cannot access user space and the kernel cannot sleep. That is, in this case, the kernel cannot invoke any function that could cause sleep.
- #define IN_SOFTIRQ () (Softirq_count ())//in handling soft interrupts
- #define IN_INTERRUPT () (Irq_count ())//In the processing of a hard interrupt or soft interrupt
- #define IN_ATOMIC () ((Preempt_count () & ~preempt_active)! = 0)//include all of the above
The count that these four macros access is thread_info->preempt_count. This variable is actually a bitmask. The minimum 8 bits represents a preemption count, usually modified by Spin_lock/spin_unlock, or the programmer enforces the modification, indicating that the maximum preemption depth allowed by the kernel is 256.
The 8-15-bit is a soft interrupt count, usually modified by local_bh_disable/local_bh_enable, and indicates that the maximum allowable soft interrupt depth for the kernel is 256.
The 16-27-bit is a hard interrupt count, usually modified by ENTER_IRQ/EXIT_IRQ, and indicates that the maximum allowable hard interrupt depth for the kernel is 4096.
The 28th place is the preempt_active flag. The code representation is:
Preempt_mask:0x000000ff
Softirq_mask:0x0000ff00
hardirq_mask:0x0fff0000
all the above 4 macros return 1 to get the place is atomic context, is not allowed to access the kernel user space, not allow the kernel sleep, do not allow the call any function that may cause sleep. and on behalf of Thread_info->preempt_count not 0, this tells the kernel that the preemption is disabled here.
However, for in_atomic (), it works well when preemption is enabled, telling the kernel whether it currently holds a spin lock, whether preemption is disabled, and so on. However, if preemption is not enabled, Spin_lock does not modify preempt_count at all, so even if the kernel calls Spin_lock and holds the spin lock, In_atomic () will still return 0, and the error tells the kernel that it is currently in a non-atomic context. So it is problematic to rely on in_atomic () to determine whether the code in the atomic context is in the case of a forbidden preemption.
Process context, interrupt context, and atomic context