zoukankan      html  css  js  c++  java
  • linux中断--进程上下文和中断上下文

    一、前言

    中断发生以后,CPU跳到内核设置好的中断处理代码中去,由这部分内核代码来处理中断。这个处理过程中的上下文就是中断上下文

    为什么可能导致睡眠的函数都不能在中断上下文中使用呢?

    首先睡眠的含义是将进程置于“睡眠”状态,在这个状态的进程不能被调度执行。然后,在一定的时机,这个进程可能会被重新置为“运行”状态,从而可能被调度执行。 可见,“睡眠”与“运行”是针对进程而言的,代表进程的task_struct结构记录着进程的状态。内核中的“调度器”通过task_struct对进程进行调度。
    但是,中断上下文却不是一个进程,它并不存在task_struct,所以它是不可调度的。所以,在中断上下文就不能睡眠。

    那么,中断上下文为什么不存在对应的task_struct结构呢?
    中断的产生是很频繁的(至少每毫秒(看配置,可能10毫秒或其他值)会产生一个时钟中断),并且中断处理过程会很快。如果为中断上下文维护一个对应的task_struct结构,那么这个结构频繁地分配、回收,并且影响调度器的管理,这样会对整个系统的吞吐量有所影响。

    但是在某些追求实时性的嵌入式linux中,中断也可能被赋予task_struct结构。这是为了避免:如果出现大量中断不断的嵌套的情况,导致一段时间内CPU总是运行在中断上下文,使得某些优先级非常高的进程得不到运行。这种做法能够提高系统的实时性,但是代价中吞吐量的降低。

    二、详解

    内核空间用户空间是现代操作系统的两种工作模式,内核模块运行在内核空间,而用户态应用程序运行在用户空间。它们代表不同的级别,而对系统资源具有不同的访问权限。内核模块运行在最高级别(内核态),这个级下所有的操作都受系统信任,而应用程序运行在较低级别(用户态)。在这个级别,处理器控制着对硬件的直接访问以及对内存的非授权访问。内核态和用户态有自己的内存映射,即自己的地址空间。

    处理器总处于以下状态中的一种:

    1. 内核态,运行于进程上下文,内核代表进程运行于内核空间;
    2. 内核态,运行于中断上下文,内核代表硬件运行于内核空间;
    3. 用户态,运行于用户空间。

    也就是说,用户态不能访问内核地址空间的内存,也不能直接访问硬件。要想这么做,一个通过系统调用进入内核态,也就产生了进程上下文;一个通过中断访问硬件,也就产生了中断上下文。两种状态的切换对应不同的目的(一个访问硬件,一个使用系统调用),有不同的来源(一个使用系统调用进入,一个使用硬件中断进入)。

    用户空间的应用程序,通过系统调用,进入内核空间。由内核代表该进程运行于内核空间,这就涉及到上下文的切换,用户空间和内核空间具有不同的地址映射、通用或专用的寄存器组,而用户空间的进程要传递很多变量、参数给内核,内核也要保存用户进程的一些寄存器、变量等,以便系统调用结束后回到用户空间继续执行。

    上下文context:上下文简单说来就是一个环境,相对于进程而言,就是进程执行时的环境。具体来说就是各个变量和数据,包括所有的寄存器变量、进程打开的文件、内存信息等。

    所谓“进程上下文”,就是一个进程在执行的时候,CPU的所有寄存器中的值、进程的状态以及堆栈上的内容,当内核需要切换到另一个进程时,它需要保存当前进程的所有状态,即保存当前进程的进程上下文,以便再次执行该进程时,能够恢复切换时的状态,继续执行。

    所谓“中断上下文”,就是硬件通过触发信号,导致内核调用中断处理程序,进入内核空间。这个过程中,硬件的一些变量和参数也要传递给内核,内核通过这些参数进行中断处理。中断上下文,其实也可以看作就是硬件传递过来的这些参数和内核需要保存的一些其他环境(主要是当前被中断的进程环境)。

    当一个进程在执行时,CPU的所有寄存器中的值、进程的状态以及堆栈中的内容被称为该进程的上下文。当内核需要切换到另一个进程时,它需要保存当前进程的所有状态,即保存当前进程的上下文,以便在再次执行该进程时,能够得到切换时的状态执行下去。在LINUX中,当前进程上下文均保存在进程的任务数据结构中。在发生中断时,内核就在被中断进程的上下文中,在内核态下执行中断服务例程。但同时会保留所有需要用到的资源,以便中继服务结束时能恢复被中断进程的执行。

    Linux内核工作在进程上下文或者中断上下文。提供系统调用服务的内核代码代表发起系统调用的应用程序运行在进程上下文;另一方面,中断处理程序,异步运行在中断上下文。中断上下文和特定进程无关。

    一个进程的上下文可以分为三个部分:用户级上下文、寄存器上下文以及系统级上下文。

    用户级上下文: 正文、数据、用户堆栈以及共享存储区;
    寄存器上下文: 通用寄存器、程序寄存器(IP)、处理器状态寄存器(EFLAGS)、栈指针(ESP);
    系统级上下文: 进程控制块task_struct、内存管理信息(mm_struct、vm_area_struct、pgd、pte)、内核栈。
    当发生进程调度时,进行进程切换就是上下文切换(context switch)。操作系统必须对上面提到的全部信息进行切换,新调度的进程才能运行。而系统调用进行的是模式切换(mode switch)。模式切换与进程切换比较起来,容易很多,而且节省时间,因为模式切换最主要的任务只是切换进程寄存器上下文的切换。
    进程上下文主要是异常处理程序和内核线程。内核之所以进入进程上下文是因为进程自身的一些工作需要在内核中做。例如,系统调用是为当前进程服务的,异常通常是处理进程导致的错误状态等。所以在进程上下文中引用current是有意义的。

    http://blog.csdn.net/yusiguyuan/article/details/12183743

  • 相关阅读:
    Transformation
    Yet Another Number Sequence
    Table
    K个联通块
    Acyclic Organic Compounds
    Sandy and Nuts
    tetrahedron
    BZOJ4750 密码安全
    实现商品秒杀 时间倒计时
    实现qq登录
  • 原文地址:https://www.cnblogs.com/stemon/p/5148869.html
Copyright © 2011-2022 走看看