处理器总处于以下状态中的一种:
1、内核态,运行于进程上下文,内核代表进程运行于内核空间;
2、内核态,运行于中断上下文,内核代表硬件运行于内核空间;
3、用户态,运行于用户空间。
LINUX完全注释中的一段话:
Interrupt Context
-------------------------------------------
the kernel is in while it is executing on behalf of aprocess -- for example, executing a system call or running a kernelthread. In process context, the current macro points to theassociated task. Furthermore, because a process is coupled to thekernel in process
context(因为进程是以进程上文的形式连接到内核中的), process contextcan sleep or otherwise invoke the scheduler.
(although it points to theinterrupted process). Without a backing process(由于没有进程的背景),interrupt context cannot sleep -- how would it everreschedule?(否则怎么再对它重新调度?) Therefore, you cannot call certainfunctions from interrupt context. If a function sleeps, you
cannotuse it from your interrupt handler -- this limits the functionsthat one can call from an interrupthandler.(这是对什么样的函数可以在中断处理程序中使用的限制)
be quick and simple. Busy looping isdiscouraged. This is a very important point; always keep in mindthat your interrupt handler has interrupted other code (possiblyeven another interrupt handler on a different line!). Because ofthis asynchronous nature, it
is imperative(必须) that all interrupthandlers be as quick and as simple as possible. As much aspossible, work should be pushed out from the interrupt handler andperformed in a bottom half, which runs at a more convenienttime.
did not receive(拥有) their ownstacks. Instead, they would share the stack of the process thatthey interrupted[1]. The kernel stack is two pages in size;typically, that is 8KB on 32-bit architectures and 16KB on 64-bitarchitectures. Because in this setup interrupt
handlers share thestack, they must be exceptionally frugal(必须非常节省) with what datathey allocate there. Of course, the kernel stack is limited tobegin with, so all kernel code should be cautious.
one, providing only a 4KB stack on32-bit systems. This reduced memory pressure because every processon the system previously needed two pages of nonswappable kernelmemory. To cope with(应对) the reduced stack size, interrupt handlerswere given their own stack,
one stack per processor, one page insize. This stack is referred to as the interrupt stack(这个栈就程为中断栈).Although the total size of the interrupt stack is half that of theoriginal shared stack, the average stack space available is greaterbecause interrupt handlers
get the full page of memory tothemselves.
is. Always use an absoluteminimum amount of stack space.
Process Context
-------------------------------------------
withinthe program's address space. Normal program execution occurs inuser-space. When a program executes a system call or triggers anexception, it enters kernel-space. At this point, the kernel issaid to be "executing on behalf of the process" and is in processcontext.
When in process context, the current macro is valid[7].Upon exiting the kernel, the process resumes execution inuser-space, unless a higher-priority process has become runnable inthe interim(过渡期), in which case the scheduler is invoked to selectthe higher
priority process.
on behalf of a process, but isexecuting an interrupt handler. There is no process tied tointerrupt handlers and consequently no process context.
executing in kernel-space only throughone of these interfaces -- all access to the kernel is throughthese interfaces.
-------------------------------------------
转自:
1.http://hi.baidu.com/jiangguiqing/blog/item/a77f1dec6d40fad52e2e2179
2.http://hi.baidu.com/zengzhaonong/blog/item/aba2504a67345e2108f7ef77
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/zhiyu520/archive/2008/07/27/2719827.aspx
进程上下文和中断上下文的区别
内核空间和用户空间是现代操作系统的两种工作模式,内核模块运行在内核空间,而用户态应用程序运行在用户空间。它们代表不同的级别,而对系统资源具有不同的访问权限。内核模块运行在最高级别(内核态),这个级下所有的操作都受系统信任,而应用程序运行在较低级别(用户态)。在这个级别,处理器控制着对硬件的直接访问以及对内存的非授权访问。内核态和用户态有自己的内存映射,即自己的地址空间。
系统的两种不同于行状态,才有了上下文的概念。用户空间的应用程序,如果想请求系统服务,比如操作某个物理设备,映射设备的地址到用户空间,必须通过系统调用来实现。(系统调用是操作系统提供给用户空间的接口函数)。如下图所示:
通过系统调用,用户空间的应用程序就会进入内核空间,由内核代表该进程运行于内核空间,这就涉及到上下文的切换,用户空间和内核空间具有不同的地址映射,通用或专用的寄存器组,而用户空间的进程要传递很多变量、参数给内核,内核也要保存用户进程的一些寄存器、变量等,以便系统调用结束后回到用户空间继续执行,所谓的进程上下文,就是一个进程在执行的时候,CPU的所有寄存器中的值、进程的状态以及堆栈上的内容,当内核需要切换到另一个进程时,它需要保存当前进程的所有状态,即保存当前进程的进程上下文,以便再次执行该进程时,能够恢复切换时的状态,继续执行。
同理,硬件通过触发信号,向CPU发送中断信号,导致内核调用中断处理程序,进入内核空间。这个过程中,硬件的一些变量和参数也要传递给内核,内核通过这些参数进行中断处理,中断上下文就可以理解为硬件传递过来的这些参数和内核需要保存的一些环境,主要是被中断的进程的环境。
Linux内核工作在进程上下文或者中断上下文。提供系统调用服务的内核代码代表发起系统调用的应用程序运行在进程上下文;另一方面,中断处理程序,异步运行在中断上下文。中断上下文和特定进程无关。
运行在进程上下文的内核代码是可以被抢占的(Linux2.6支持抢占)。但是一个中断上下文,通常都会始终占有CPU(当然中断可以嵌套,但我们一般不这样做),不可以被打断。正因为如此,运行在中断上下文的代码就要受一些限制,不能做下面的事情:
1. 睡眠或者放弃CPU。
由于中断上下文不属于任何进程,它与current没有任何关系(尽管此时current指向被中断的进程),所以中断上下文一旦睡眠或者放弃CPU,将无法被唤醒。所以也叫原子上下文(atomic context)。
2. 尝试获得信号量
为了保护中断句柄临界区资源,不能使用mutexes。如果获得不到信号量,代码就会睡眠,会产生和上面相同的情况,如果必须使用锁,则使用spinlock。
3. 执行耗时的任务
中断处理应该尽可能快,因为内核要响应大量服务和请求,中断上下文占用CPU时间太长会严重影响系统功能。在中断处理例程中执行耗时任务时,应该交由中断处理例程底半部来处理。
4. 访问用户空间的虚拟地址
因为中断上下文是和特定进程无关的,它是内核代表硬件运行在内核空间,所以在终端上下文无法访问用户空间的虚拟地址
5. 中断处理例程不应该设置成reentrant(可被并行或递归调用的例程)。因为中断发生时,preempt和irq都被disable,直到中断返回。所以中断上下文和进程上下文不一样,中断处理例程的不同实例,是不允许在SMP上并发运行的。
6. 中断处理例程可以被更高级别的IRQ中断。如果想禁止这种中断,可以将中断处理例程定义成快速处理例程,相当于告诉CPU,该例程运行时,禁止本地CPU上所有中断请求。这直接导致的结果是,由于其他中断被延迟响应,系统性能下降。