转载-Linux内核中进程上下文和中断上下文的理解

用户空间与内核空间示意图如下:

整个Linux内部结构可以分成三部分,从最底层到最上层依次是:硬件、内核空间、用户空间,如下图所示:

需要注意的细节问题:

  • 进程的内核空间存放的是内核代码和数据,用户空间中存放的是用户代码和数据,不管是内核空间还是用户空间,它们都处于虚拟空间中;
  • Linux使用两级保护机制,0级供内核使用,3级供用户程序使用。

内核态和用户态:

  • 当一个任务(进程)执行系统调用而陷入到内核代码中执行时,称此进程处于内核运行态(内核态),此时处理器处于特权级最高的(0级)内核代码中执行,当进程处于内核态时,执行的内核代码会使用当前进程的内核栈,每个进程都有自己的内核栈;
  • 当进程执行用户自己的代码时,称此进程处于用户运行态(用户态),此时处理器在特权级最低的(3级)用户代码中运行;
  • 当正在执行用户程序而突然被中断程序中断时,此时用户程序也可以象征性地称为处于进程的内核态,因为中断处理程序将使用当前进程的内核栈。

上下文context:

  • 上下文简单来说就是一个环境。

用户空间的应用程序,通过系统调用,进入到内核空间,这个时候用户空间的进程需要传递很多变量、参数的值给内核,内核态运行的时候也要保存用户进程的一些寄存器值、变量等,所谓的"进程上下文",可以看作是用户进程传递给内核的这些参数以及内核要保存的变量和寄存器的值以及当时的环境等,相对于进程而言,就是进程执行时的环境,具体来说就是各个变量和数据,包括所有的寄存器变量、进程打开的文件、内存信息等。

一个进程的上下文可以分为三部分,如下:

  • 用户级上下文:正文、数据、用户堆栈、共享存储区;
  • 寄存器上下文:通用寄存器、程序寄存器、处理器状态寄存器、栈指针;
  • 系统级上下文:进程控制块task_struct、内存管理信息(mm_struct、vm_area_struct、pgd、pte)、内核栈。

当发生进程调度时,进行进程切换就是上下文切换(context switch),操作系统必须对上面提到的全部信息进行切换,新调度的进程才能运行,系统调用进行的是模式切换(mode switch),模式切换与进程切换比较起来,模式切换容易很多,而且节省时间,因为模式切换最主要的任务只是切换进程寄存器上下文。

硬件通过触发中断信号,导致内核调用中断处理程序,进入内核空间,这个过程中,硬件的一些变量和参数也需要传递给内核,内核通过这些参数进行中断处理,所谓的"中断上下文",可以看作是硬件传递过来的这些参数和内核需要保存的一些其它环境(主要是当前被打断执行的进程环境),发生中断时,内核不代表任何进程运行,它一般只访问系统空间,而不会访问进程空间,内核在中断上下文中执行时一般不会阻塞。

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

运行在进程上下文的内核代码是可以被抢占的(Linux 2.6支持抢占),但是一个中断上下文,通常都会始终占有CPU(当然中断可以嵌套,但我们一般不这样做),不可以被打断,正因为如此,运行在中断上下文的代码就要受一些限制,不能做下面的事情:

  • 睡眠或者放弃CPU:这样做的后果是灾难性的,因为内核在进入中断之前会关闭进程调度,一旦睡眠或者放弃CPU,这时内核无法调度别的进程来执行,系统就会死掉;
  • 尝试获得信号量:如果获得不到信号量,代码就会睡眠,会产生和上面相同的情况
  • 执行耗时的任务:中断处理应该尽可能快,因为内核要响应大量服务和请求,中断上下文占用CPU时间太长会严重影响系统功能;
  • 访问用户空间的虚拟地址:因为中断上下文是和特定进程无关的,它是内核代表硬件运行在内核空间,所以在中断上下文无法访问用户空间的虚拟地址。

 

本文转载于:

https://blog.csdn.net/rendong_yang/article/details/88949950

原作者:老杨的码农生活

posted @ 2021-02-22 22:31  liangliangge  阅读(432)  评论(0编辑  收藏  举报