零
文章概要
壹 前言
贰 用户态和内核态
叁 硬中断和软中断
肆 从汇编代码看中断
伍 总结
壹
前言
和往常一样,我们碰到过于复杂的知识点直接用封装代替,不过渡深究,本篇文章主要浅显地探讨下中断的大概流程,了解系统调用和中断的关系,最后只要知道频繁的系统调用将会比较耗费时间就行了。
贰
用户态和内核态
从前边写的linux内存管理文章中,我们知道每个用户进程独享一份虚拟空间,而进程的虚拟空间又被分为很多段,其中有一段为内核段,但是实际上linux的内核进程只有一个,下图所示为一个进程的虚拟内存空间,让该进程产生一种独享内存与内核的错觉。
![44e86cdc9642c6ce965e114ef8805f0f.png](https://i-blog.csdnimg.cn/blog_migrate/c9a688d19edcb2262a6107d116dd55ae.jpeg)
接下来我们只需要知道一点,当一个用户进程想要操作物理内存和外部设备时,都不是这个进程去实际操作的,都是内核进程在幕后进行操作。而这个过程就叫做从用户态转为内核态。我们从内存管理的文章中也可以知道,这么做其实是为了安全(或许有其他原因,不过我们不用care),不能让用户进程随意的操作内存,操作外设,厉害的程序员可以直接干掉整个系统。从用户态转为内核态这个操作,是由软中断来实现的,这个操作也被叫做系统调用(system call)。
叁
硬中断与软中断
当我们执行N个进程的时候,忽然有个进程急需进行某种操作,可是此时还没轮到它运行,于是它就需要发出某种信号,打断操作系统当前做的事情,转而对它的事情紧急处理,这就是中断。由计算机外部设备,比如键盘,鼠标,还有一些什么时钟触发进程切换啥的,都是硬中断,这个和我们编码无关。不讨论了。软中断就是我们刚刚提到的系统调用。每当我们的用户进程想要使用计算机物理设备时,都必须先和内核打交道,将想要干的事情告诉内核,让它去实操。这个中断有一个专门的编号 int 0x80 ,那么内核怎么知道你这次到来的是什么中断呢。不用想,肯定也是维护了那么一份数据结构(中断向量表),通过传过来的参数,内核查表就可以知道你这次要干什么。
而对于0x80中断,内核也维护了那么一份数据结构,用来记录软中断中的不同的请求,比如读请求,写请求等。例如一个java程序想要从网卡读取信息(网络IO),代码中肯定就是我们平时用到的输入流,调用read()方法,再转而调用本地C库的read()方法,进而发起系统调用,由内核程序进行sys_read()到指定内存页;
肆
从汇编代码看中断
接下来我们通过一段简单的汇编看看,一个write过程在linux中是怎么执行的。下图所示为汇编程序。我们想要往屏幕上输出一个字符串,linux中,每个进程都有一个标准输入,标准输出,报错输出,他们分别被一个文件描述符所指向。从我们之前的linux虚拟文件系统,我们知道linux把一切东西都看成是文件,屏幕等外设也不例外,而每个打开的文件都会配置一个文件描述符,当然一个文件可以被打开多次,这样就会有多个文件描述符指向这个文件。而本次我们要告诉内核进程,我们要往文件描述符为1的地方输出东西,那么内核自然就会给我们打印到屏幕上。当前进程就是我们打开的这个shell程序,也就是这个命令行界面。同时我们还需要告诉内核本次操作为write操作,用4号代表。然后代码执行到int 0x80,发起系统调用,切换到内核态,内核会去自己维护的数据结构表中查找指定代号代表的什么意思,然后进行相应的操作。
![0d6e92dc5cf6c89b207d925d5822e916.png](https://i-blog.csdnimg.cn/blog_migrate/43905422872fe2923fed17c2a26033ff.jpeg)
结果如下图所示,字符串被打印到shell屏幕中。同时我们顺便看下当前进程中的一些详细信息,使用lsof指令,$$ 指的就是当前shell进程。我们可以看到确实有个代号为1的文件描述符(以后会单独对这个文件描述符进行讲解)。
![429c1f2af7c45327168bb84fe50db088.png](https://i-blog.csdnimg.cn/blog_migrate/0fe098c248b615d5d7d27974d3737ba2.jpeg)
伍
总结
总之,在平时的java代码中,并不会涉及上述知识,本篇文章主要强调,用户态无法对真实的计算机进行操作,需要切换到内核态进行实际操作,这个切换过程是通过软中断,系统调用实现的,而既然进行了进程切换,那么肯定需要经历,保护现场,中断处理,恢复现场这个操作,频繁这么做将会是一笔不小的时间开销。有了前面这些个基础,我们将可以探讨IO模型进化历程,也就是那些BIO,NIO,多路复用器(selector,poll,epoll)。