内核控制路径就是内核里面的代码,即位于0xc000 0000以上的函数代码,包括中断处理函数,异常处理函数(比如驱动里的实现read的函数),内核线程函数
那么怎么才能让cpu去执行这个代码呢?
中断处理函数:硬件通知cpu,cpu调到对应地址执行之
异常处理函数:比如应用层执行的系统调用,触发cpu执行这个函数
内核线程:和其他用户线程一样,参与cpu的优先级调度。
******************************************************************************************************************************************************
.......
Unix kernels do much more than handle system calls; in fact, kernel routines can be activated in several ways:
-
A process invokes a system call.
-
The CPU executing the process signals anexception, which is an unusual condition such as an invalid instruction. The kernel handles the exception on behalf of the process that caused it.
-
A peripheral device issues an interrupt signal to the CPU to notify it of an event such as a request for attention, a status change, or the completion of an I/O operation. Each interrupt signal is dealt by a kernel program called aninterrupt handler. Because peripheral devices operate asynchronously with respect to the CPU, interrupts occur at unpredictable times.
-
A kernel thread is executed. Because it runs in Kernel Mode, the corresponding program must be considered part of the kernel.
内核控制路径内核例程包括
系统调用代码(一种异常处理程序)
异常处理程代码
中断处理程序代码
内核线程代码
内核例程不属于任何进程,没有进程标示符(内核线程有),如果不开启内核抢占,内核例程将一直执行直到完成任务自动让出cpu
只要进入了内核空间,便是处于以上四种内核例程的某一个
( 内核例程 = 内核控制路径 + 内核线程 )
******************************************************************************************************************************************************
中断发生以后,CPU跳到内核设置好的中断处理代码中去,由这部分内核代码来处理中断。这个处理过程中的上下文就是中断上下文。
为什么可能导致睡眠的函数都不能在中断上下文中使用呢? 首先睡眠的含义是将进程置于“睡眠”状态,在这个状态的进程不能被调度执行。然后,在一定的时机,这个进程可能会被重新置为“运行”状态,从而可能被调度执行。 可见,“睡眠”与“运行”是针对进程而言的,代表进程的task_struct结构记录着进程的状态。内核中的“调度器”通过task_struct对进程进行调度。
但是,中断上下文却不是一个进程,它并不存在task_struct,所以它是不可调度的。所以,在中断上下文就不能睡眠。
那么,中断上下文为什么不存在对应的task_struct结构呢?
中断的产生是很频繁的(至少每毫秒(看配置,可能10毫秒或其他值)会产生一个时钟中断),并且中断处理过程会很快。如果为中断上下文维护一个对应的task_struct结构,那么这个结构频繁地分配、回收、并且影响调度器的管理,这样会对整个系统的吞吐量有所影响。
但是在某些追求实时性的嵌入式linux中,中断也可能被赋予task_struct结构。这是为了避免大量中断不断的嵌套,导致一段时间内CPU总是运行在中断上下文,使得某些优先级非常高的进程得不到运行。这种做法能够提高系统的实时性,但是代价中吞吐量的降低。
refer to
http://bbs.chinaunix.net/thread-1969752-1-1.html
******************************************************************************************************************************************************
All Unix kernels are reentrant. This means that several processes may be executing in Kernel Mode at the same time. Of course, on uniprocessor systems, only one process can progress, but many can be blocked in Kernel Mode when waiting for the CPU or the completion of some I/O operation. For instance, after issuing a read to a disk on behalf of a process, the kernel lets the disk controller handle it and resumes executing other processes. An interrupt notifies the kernel when the device has satisfied the read, so the former process can resume the execution.
One way to provide reentrancy is to write functions so that they modify only local variables and do not alter global data structures. Such functions are calledreentrant functions . But a reentrant kernel is not limited only to such reentrant functions (although that is how some real-time kernels are implemented). Instead, the kernel can include nonreentrant functions and use locking mechanisms to ensure that only one process can execute a nonreentrant function at a time.
If a hardware interrupt occurs, a reentrant kernel is able to suspend the current running process even if that process is in Kernel Mode. This capability is very important, because it improves the throughput of the device controllers that issue interrupts. Once a device has issued an interrupt, it waits until the CPU acknowledges it. If the kernel is able to answer quickly, the device controller will be able to perform other tasks while the CPU handles the interrupt.
Now let's look at kernel reentrancy and its impact on the organization of the kernel.A kernel control path denotes the sequence of instructions executed by the kernel to handle a system call, an exception, or an interrupt.
In the simplest case, the CPU executes a kernel control path sequentially from the first instruction to the last. When one of the following events occurs, however, the CPU interleaves the kernel control paths :
-
A process executing in User Mode invokes a system call, and the corresponding kernel control path verifies that the request cannot be satisfied immediately; it then invokes the scheduler to select a new process to run. As a result, a process switch occurs. The first kernel control path is left unfinished, and the CPU resumes the execution of some other kernel control path. In this case, the two control paths are executed on behalf of two different processes.
-
The CPU detects an exceptionfor example, access to a page not present in RAM while running a kernel control path. The first control path is suspended, and the CPU starts the execution of a suitable procedure. In our example, this type of procedure can allocate a new page for the process and read its contents from disk. When the procedure terminates, the first control path can be resumed. In this case, the two control paths are executed on behalf of the same process.
-
A hardware interrupt occurs while the CPU is running a kernel control path with the interrupts enabled. The first kernel control path is left unfinished, and the CPU starts processing another kernel control path to handle the interrupt. The first kernel control path resumes when the interrupt handler terminates. In this case, the two kernel control paths run in the execution context of the same process, and the total system CPU time is accounted to it. However, the interrupt handler doesn't necessarily operate on behalf of the process.
-
An interrupt occurs while the CPU is running with kernel preemption enabled, and a higher priority process is runnable. In this case, the first kernel control path is left unfinished, and the CPU resumes executing another kernel control path on behalf of the higher priority process. This occurs only if the kernel has been compiled with kernel preemption support.
A kernel control path denotes the sequence of instructions executed by the kernel to handle a system call, an exception, or an interrupt.
内核控制路径是指被内核执行的用于处理系统调用异常中断的指令序列
kernel preemption
内核抢占
******************************************************************************************************************************************
(2)内核控制路径
内核在允许中断信号到来之前,必须先准备好对它们的处理,也就是适当地初始化中断描述符表(Interrupt Descriptor Table, IDT)。中断信号一来,CPU控制单元就自动把当前的程序计数器(eip、cs)和eflags保存到内核stack,然后把事先与发生的中断信号类型关联好的处理程序的地址(保存在IDT中)放进程序计数器。这时,内核控制路径(kernel control path)横空出世。
什么是内核控制路径?它是不是一个进程?不是。内核进程?也不是。它虽然也需要切换上下文,需要保存那些它可能使用的寄存器的并在返回时恢复,但这是一个非常轻的上下文切换(终端上下文)。 它诞生的时候并没有发生进程切换,处理中断的主语仍然是中断发生时正在执行的那个进程,它仍然在使用分配给它的那段时间片。
有趣的是,如果一个进程还在处理一个异常的时候,分配给它的时间片到期了,会发生什么事情呢? 这取决于有没有启用内核抢占(Kernel Preemption),如果没有启用,进程就继续处理异常,如果启用了,进程可能会立即被抢占,异常的处理也就暂停了,直到schedule()再度选择原先那个进程(注意:内核处理中断的时候,必然会禁用内核抢占,所以这里才说是异常)。
refer to
http://blog.csdn.net/zhandoushi1982/article/details/5608609
******************************************************************************************************************************************************
4.1. The Role of Interrupt Signals
the code executed by an interrupt or by an exception handler is not a process. Rather, it is a kernel control path that runs at the expense of the same process that was running******************************************************************************************************************************************************
可以看出
进程通过调用系统调用(叫编程异常 Programmed exceptions或软件中断 software interrupts,ulk3,4.2)而陷入内核执行 异常处理程序(一种内核控制路径,此处即系统调用代码),当前进程的时间片仍然在消耗,当消耗完时
在内核抢占允许的情况下,当前进程会被调度程序用其他进程替换掉,而刚才的内核控制路径(系统调用)被打断,断点入该进程的内核栈,
在内核抢占禁止的情况下,此内核控制路径(系统调用)一直执行,尽管对应进程的时间片已消耗完
可参考ulk3 -5.1.1内核抢占一节
进程在执行过程中,如果发生硬件中断,则cpu陷入内核执行 中断处理程序(一种内核控制路径)执行,在此期间,此进程的时间片同上面一样仍然在消耗,当消耗完时,不允许发生进程切换,见下
*****************************************************************************************************************************************************
5.1.1. Kernel Preemption
Making the Linux 2.6 kernel preemptive did not require a drastic change in the kernel design with respect to the older nonpreemptive kernel versions. As described in the section "Returning from Interrupts and Exceptions" in Chapter 4, kernel preemption is disabled when thepreempt_countfield in the tHRead_info descriptor referenced by the current_thread_info( ) macro is greater than zero.The field encodes three different counters, as shown inTable 4-10 in Chapter 4, so it is greater than zero when any of the following cases occurs:
-
The kernel is executing an interrupt service routine.
-
The deferrable functions are disabled (always true when the kernel is executing a softirq or tasklet).
-
The kernel preemption has been explicitly disabled by setting the preemption counter to a positive value.
The above rules tell us that the kernel can be preempted only when it is executing an exception handler (in particular a system call) and the kernel preemption has not been explicitly disabled. Furthermore, as described in the section "Returning from Interrupts and Exceptions" in Chapter 4, the local CPU must have local interrupts enabled, otherwise kernel preemption is not performed.
只有在执行异常处理例程(内核控制路径)时才会发生内核抢占,尤其是执行系统调用时
但内核线程应该也能被抢占------?先记下
2.2 内核控制路径的交叉执行
Linux允许内核代码路径的交错执行,也就是说,在当前内核控制路径尚未执行完的时候,允许另外一条控制路径来中断(也可以称为抢占)它。但这种交错执行不是任意的,需要满足如下严格的规则:
.内核进程代码路径不能够中断任何其它内核控制路径,包括别的内核进程代码路径(这保证了Linux进程在内核中是非抢占的---- 这应该是2.4,2.6 抢占内核可以中断)。
异常处理代码可以中断内核进程代码路径,但不能够抢*断处理路径的执行。实际上后一个特点是对中断处理程序的限制,由于异常处理总是由于当前正在运行的代码所引起的,只有中断处理程序中不允许执行可能引起"缺页操作"的代码,才能够保证不激活异常成立程序。
中断处理程序可以中断任何一个内核进程代码路径,也可以中断异常处理路径,以及与其它的中断处理程序交错执行。
refer to
http://www.lslnet.com/linux/dosc1/31/linux-242522.htm
可参考ulk3 chapter5 内核同步
******************************************************************************************************************************************************
4.2. Interrupts and ExceptionsThe Intel documentation classifies interrupts and exceptions as follows:
Each interrupt or exception is identified by a number ranging from 0 to 255; Intel calls this 8-bit unsigned number avector. The vectorsof nonmaskable interrupts and exceptions are fixed, while those of maskable interrupts can be altered by programming the Interrupt Controller (see the next section). |
几种软中断的实例
********************************************************************
arm linux refer to 嵌入式linux应用开发完全手册注册 ch20
在中断里面睡眠
http://blog.csdn.net/unbutun/article/details/5730153#comments