【内核】02.上下文
【嵌入式八股】一、语言篇https://www.nowcoder.com/creation/manager/columnDetail/mwQPeM
【嵌入式八股】二、计算机基础篇https://www.nowcoder.com/creation/manager/columnDetail/Mg5Lym
【嵌入式八股】三、硬件篇https://www.nowcoder.com/creation/manager/columnDetail/MRVDlM
【嵌入式八股】四、嵌入式Linux篇(本专栏)https://www.nowcoder.com/creation/manager/columnDetail/MQ2bb0
上下文
11.为什么会有上下文这种概念?
在计算机系统中,上下文是指当前程序或进程执行的环境和状态,包括程序的执行位置、寄存器内容、堆栈信息、打开文件等。操作系统需要在多个进程之间进行快速的切换,这就需要在进程间保存和恢复上下文信息。
在一个计算机系统中,只有一个CPU,但是可能有多个进程或线程在同时运行。当操作系统需要将CPU从一个进程切换到另一个进程时,必须保存当前进程的上下文信息,并加载下一个进程的上下文信息,从而让它继续执行。这种切换称为上下文切换。
上下文的概念也在操作系统的其他方面得到了应用,例如在中断处理中,需要保存当前执行的进程上下文,以便中断处理程序执行完毕后能够恢复到之前的状态。在多线程编程中,线程切换也需要保存和恢复上下文信息。
内核空间和用户空间是现代操作系统的两种工作模式,内核模块运行在内核空间,而用户态应用程序运行在用户空间。它们代表不同的级别,而对系统资源具有不同的访问权限。内核模块运行在最高级别(内核态),这个级下所有的操作都受系统信任,而应用程序运行在较低级别(用户态)。在这个级别,处理器控制着对硬件的直接访问以及对内存的非授权访问。内核态和用户态有自己的内存映射,即自己的地址空间。
其中,处理器总处于以下状态中的一种:
-
内核态,运行于进程上下文,内核代表进程运行于内核空间;
-
内核态,运行于中断上下文,内核代表硬件运行于内核空间;
-
用户态,运行于用户空间。
系统的两种不同运行状态,才有了上下文的概念。用户空间的应用程序,如果想请求系统服务,比如操作某个物理设备,映射设备的地址到用户空间,必须通过系统调用来实现。通过系统调用,用户空间的应用程序就会进入内核空间,由内核代表该进程运行于内核空间,这就涉及到上下文的切换,用户空间和内核空间具有不同的地址映射,通用或专用的寄存器组,而用户空间的进程要传递很多变量、参数给内核,内核也要保存用户进程的一些寄存器、变量等,以便系统调用结束后回到用户空间继续执行。
上下文概念的引入,保证了系统的并发性和可靠性,提高了系统的性能和效率。
12.上下文有哪些?怎么理解?
上下文简单说来就是一个环境。 用户空间的应用程序,通过系统调用,进入内核空间。这个时候用户空间的进程要传递很多变量、参数的值给内核,内核态运行的时候也要保存用户进程的一些寄存器值、变量等。所谓的“进程上下文”,可以看作是用户进程传递给内核的这些参数以及内核要保存的那一整套的变量和寄存器值和当时的环境等。
进程上下文可以分为三个部分:用户级上下文、寄存器上下文以及系统级上下文。
-
用户级上下文: 正文、数据、用户堆栈以及共享存储区;
-
寄存器上下文: 通用寄存器、程序寄存器(IP)、处理器状态寄存器(EFLAGS)、栈指针(ESP);
-
系统级上下文: 进程控制块task_struct、内存管理信息(mm_struct、vm_area_struct、pgd、 pte)、内核栈。 当发生进程调度时,进行进程切换就是上下文切换(context switch).操作系统必须对上面提到的全部信息进行切换,新调度的进程才能运行。而系统调用进行的模式切换(mode switch)。模式切换与进程切换比较起来,容易很多,而且节省时间,因为模式切换最主要的任务只是切换进程寄存器上下文的切换。
硬件通过触发信号,导致内核调用中断处理程序,进入内核空间。这个过程中,硬件的一些变量和参数也要传递给内核,内核通过这些参数进行中断处理。所谓的“ 中断上下文”,其实也可以看作就是硬件传递过来的这些参数和内核需要保存的一些其他环境(主要是当前被打断执行的进程环境)。中断时,内核不代表任何进程运行,它一般只访问系统空间,而不会访问进程空间,内核在中断上下文中执行时一 般不会阻塞。
13.什么是进程上下文、中断上下文?
(1)进程上文:是指进程由用户态切换到内核态时需要保存用户态时CPU寄存器中的值,进程状态以及堆栈上的内容。即保存当前进程的状态,以便再次执行该进程时,能够恢复切换时的状态,继续执行。
(2)进程下文:是指切换到内核态后执行的程序,即进程运行在内核空间的部分。
(3)中断上文:硬件通过中断触发信号,导致内核调用中断处理程序,进入内核空间。这个过程中,硬件的一些变量和参数也要传递给内核,内核通过这些参数进行中断处理。中断上文可以看作硬件传递过来的这些参数和内核需要保存的一些其他环境(主要是当前被中断的进程环境)。
(4)中断下文:执行在内核空间的中断服务程序。
14.中断上下文代码中有哪些注意事项?
运行于进程上下文的内核代码是可抢占的,但中断上下文则会一直运行至结束,不会被抢占。所以中断处理程序代码要受到一些限制,在中断代码中不能出现实现下面功能的代码:
-
睡眠或者放弃CPU 因为内核在进入中断之前会关闭进程调度,一旦睡眠或者放弃CPU,这时内核无法调度别的进程来 执行,系统就会死掉。牢记:中断服务子程序一定不能睡眠(或者阻塞)。
-
尝试获得信号量 如果获得不到信号量,代码就会睡眠,导致(1)中的结果。
-
执行耗时的任务 中断处理应该尽可能快,因为如果一个处理程序是IRQF_DISABLED类型,他执行的时候会禁止所有 本地中断线,而内核要响应大量服务和请求,中断上下文占用CPU时间太长会严重影响系统功能。 中断处理程序的任务尽可能放在中断下半部执行。
-
访问用户空间的虚拟地址,因为中断运行在内核空间。
15.请问线程需要保存哪些上下文,SP、PC、EAX这些寄存器是干嘛用的?
线程在切换的过程中需要保存当前线程id、线程状态、堆栈、寄存器状态等信息。其中寄存器主要包括 SP、PC、EAX 等寄存器
线程需要保存的上下文通常包括以下内容:
- 线程栈指针(Stack Pointer,SP):保存线程栈的当前位置。
- 程序计数器(Program Counter,PC):保存线程当前正在执行的指令的地址。
- 通用寄存器(General-Purpose Registers,GPRs):如EAX、EBX、ECX、EDX等寄存器,保存线程执行时的数据。
- 浮点寄存器(Floating Point Registers):保存线程执行时使用的浮点数。
- 状态寄存器(Status Register):保存线程的一些状态信息,如进位标志、溢出标志等。
在线程上下文切换时,需要将这些上下文信息保存到内存中,以便在切换回该线程时能够恢复执行。这些上下文信息保存在操作系统内核的线程控制块(Thread Control Block,TCB)中,以便操作系统能够管理线程的状态。
SP、PC、EAX这些寄存器的具体作用如下:
- SP寄存器保存线程栈的当前位置,因为线程在执行时会使用栈来保存局部变量、函数调用信息和返回地址等信息,所以在切换线程时需要保存SP寄存器的值,以便下次恢复时能够正确地访问线程栈中的数据。
- PC寄存器保存线程当前正在执行的指令的地址,因为在线程执行时需要不断切换执行的指令,所以在切换线程时需要保存PC寄存器的值,以便下次恢复时能够从正确的指令地址继续执行。
- EAX累加寄存器等通用寄存器保存线程执行时的数据,因为线程执行时需要对数据进行计算和处理,所以在切换线程时需要保存这些寄存器的值,以便下次恢复时能够正确地处理数据。
16.什么是内核态和用户态?
Linux kernel和一般程序的区别是什么?
当进程运行在内核空间时就处于内核态,而进程运行在用户空间时则处于用户态。
- 从系统资源访问方面
在内核态下,进程运行在内核地址空间中,此时 CPU 可以执行任何指令,操作系统的任何资源,包括硬件。运行的代码也不受任何的限制,可以自由地访问任何有效地址,也可以直接进行端口的访问。 在用户态下,进程运行在用户地址空间中,被执行的代码要受到 CPU 的诸多检查,不能直接访,它们只能访问映射其地址空间的页表项中规定的在用户态下可访问页面的虚拟地址,且只能对任务状态段(TSS)中 I/O 许可位图(I/O Permission Bitmap)中规定的可访问端口进行直接访问。
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
查阅整理上千份嵌入式面经,将相关资料汇集于此,主要包括: 0.简历面试 1.语言篇 2.计算机基础 3.硬件篇 4.嵌入式Linux【本专栏】 (建议PC端查看)