linux系统对中断的处理

1、ARM处理器程序运行的过程

在这里插入图片描述

扩展:

1)、在CPU里面,有一个很重要的单元名叫MMU,内存管理单元。
在这里插入图片描述
关于内存管理单元,有如下介绍:
在这里插入图片描述
2)、进程控制块:
PCB进程控制块(也叫做进程描述符)(位于内核空间):本质就是结构体(上百行)。
注:每个程序都是一个进程,每个进程都有一个进程控制块。进程控制块位于虚拟内存(3G-4G(对于 32位系统来说))
里面包含很多的内容,重点掌握以下部分:
(1)、存放进程ID。系统的每一个进程有唯一的id。在c语言中,用pid_t类型表示。其实就是一个非负整数。ps aux(查看进程id) ps ajx(查看进程id,父进程id…)
在这里插入图片描述

(2)、存放进程的状态:有就绪(要是说五种,就是“初始化+就绪”)、运行、挂起(暂停)(主动放弃CPU的使用权)—sleep()、停止等状态。

在这里插入图片描述

(3)、进行进程切换的时候,需要保存和恢复的一些CPU寄存器。(进程切换的时候,保存已经执行好的内容,等到下次CPU 过来执行的时候,可以接着进行(分时复用))
(4)、存放用来描述虚拟地址空间的信息。
虚拟内存通过MMU映射到物理内存。这个映射的活,是MMU干。而这个映射规则(eg:虚拟地址8000对应的物理地址是多少),是在PCB进程控制块里面存储。
(5)、存储当前工作目录:
cd … 操作,就是改变当前工作目录。通过ls,把当前工作目录下的文件显示出来。这都得益于这个功能,因为你要知道当前文件所在的目录。
(6)、存放文件描述符表,里面包含了很多指向file的结构体指针。
(7)、存放会话和进程组
(8)、存放进程可以使用的资源上限。
(9)、和信号相关的信息
(10)、用户id和组id。
3)、
内核在创建进程的时候,在创建task_struct(PCB进程控制块)的同时,会为进程创建相应的堆栈。一个内核栈,一个用户栈。内核栈和PCB进程控制块都位于内核空间,实际上是两个连续的物理页面,底部用作task_struct结构体,结构体上面的用作堆栈。
在这里插入图片描述
在这里插入图片描述

2、程序被中断时,怎么保存现场

首先,先贴出一张示意图:
在这里插入图片描述

为保证执行中断程序后,依旧可以继续执行原程序,我们需要保证下面三点:
1)、代码没有被修改
2)、数据没有被修改
注:
在有MMU的系统中,每个进程的空间是相互隔离的,进程A无法修改进程B的代码和数据。
但是在没有MMU的系统中,比如运行UCOS的单片机,将无法保证进程A不破坏进程B,只能通过尽量完善代码。
3)、CPU内部的寄存器数据不被修改。这个是关键:
在CPU执行任务的过程中,有可能发生中断。CPU在处理中断的过程中,可能就会修改寄存器中的内容。或者是对于多任务操作系统,CPU通过分时复用机制,同时处理多个进程(程序),他是如何保证CPU寄存器里面的内容不被破坏??
我们需要在程序a切换到程序b之前,保存程序a的寄存器。这些寄存器,就保存在栈中。寄存器的值,就叫做现场。

3、进程、线程的概念

引入线程的好处:
即可以互不影响的运行,又可以高效的传递数据。
因此,线程参与调度,就涉及到保存现场和恢复现场。
因此,每一个线程,都有自己的栈。
在这里插入图片描述

从 Linux 内核的角度来说,其实它并没有线程的概念。Linux 把所有线程都当做进程来实现,它将线程和进程不加区分的统一到了 task_struct 中。线程仅仅被视为一个与其他进程共享某些资源的进程,而是否共享地址空间几乎是进程(地址空间独立)和 Linux 中所谓线程(共享本进程中的数据,使用相同的地址空间)的唯一区别。

题外话:

1.进程的堆栈
内核在创建进程的时候,在创建task_struct(PCB进程控制块)的同时,会为进程创建相应的堆栈。每个进程会有两个栈,一个用户栈,存在于用户空间,一个内核栈,存在于内核空间。当进程在用户空间运行时,cpu堆栈指针寄存器里面的内容是用户堆栈地址,使用用户栈;当进程在内核空间时,cpu堆栈指针寄存器里面的内容是内核栈空间地址,使用内核栈。
2.进程用户栈和内核栈的切换
当进程因为中断或者系统调用而陷入内核态时,进程所使用的堆栈也要从用户栈转到内核栈。
进程陷入内核态后,先把用户态堆栈的地址保存在内核栈之中,然后设置堆栈指针寄存器的内容为内核栈的地址,这样就完成了用户栈向内核栈的转换;当进程从内核态恢复到用户态时,在内核态之行的最后将保存在内核栈里面的用户栈的地址恢复到堆栈指针寄存器即可。这样就实现了内核栈和用户栈的互转。
那么,我们知道从内核转到用户态时用户栈的地址是在陷入内核的时候保存在内核栈里面的,但是在陷入内核的时候,我们是如何知道内核栈的地址的呢?
关键在进程从用户态转到内核态的时候,进程的内核栈总是空的。这是因为,当进程在用户态运行时,使用的是用户栈,当进程陷入到内核态时,内核栈保存进程在内核态运行的相关信息,但是一旦进程返回到用户态后,内核栈中保存的信息无效,会全部恢复,因此每次进程从用户态陷入内核的时候得到的内核栈都是空的。所以在进程陷入内核的时候,直接把内核栈的栈顶地址给堆栈指针寄存器就可以了。
3、进程栈(属于用户栈)、进程的内核栈和线程栈的关系:
线程栈的空间开辟在所属进程的堆区,线程与其所属的进程共享进程的用户空间,所以线程栈之间可以互访。
每个进程都有自己的内核栈,所有进程之间的内核栈是不共享的。

猜你喜欢

转载自blog.csdn.net/cainiaofu/article/details/115304298