一、系统调用几个相关的概念:
1.内核态和用户态:
内核态:实际上cpu执行内核的代码就称处于内核态
用户态:同上,cpu在执行我们用户空间的代码时就称处于用户态

2.中断:
中断分为硬件中断和软件中断,这里说的是软件中断。
什么是中断:
实际上是cpu的一条指令,有的时候我们需要暂停下来当前的事情去做一些更重要的事,这个时候需要一个中断。
(比如,小明和小红上课开小差,老师觉得学习是更加重要的事情,所以就将他俩的小差打断,去做更重要的事情,学习(我爱学习(破音~)),等到下课了,学习学完了,你俩再去聊天)

3.linux下int 0x80中断和系统调用:
linux下所有的系统调用都和0x80号中断绑定
当用户或者库函数调用系统调用,就会产生一个0x80的中断

用户空间每个系统调用API都对应着一个系统调用号
linux内核中维护着一张表,这张表叫做系统调用表
中断处理程序拿到用户传递的系统调用号,然后送到内核中,与系统调用表中编号进行对比,最后执行相应编号的函数代码。
系统调用

整个过程如上图。

二、系统调用

1.作用和意义:
是沟通用户与内核之间沟通的桥梁。
我们知道我们计算机几乎所有的硬件等资源都由我们的操作系统管理,不论是我们还是我们自己编写的软件再或者用户的应用软件对计算机硬件或者其他资源进行操作时 都需要操作系统的“同意”,这些资源由操作系统给我们统一保管和分配。
而操作系统给我们预留的这些接口就是系统调用。

2.linux下我们经常使用到的系统调用:
1.直接使用系统调用:
open write read fork 等
2.库函数间接使用系统调用:
如C库函数:printf()
一般默认将我们目标内容打印到屏幕上,实际上底层调用的是我们的write(),将目标的字符传送到我们的标准输出
系统调用
实际上,上述的write()并不是每次执行都会进行中断来满足用户,无论是中断还是系统调用,都会产生巨大的开销,无论是时间上的还是空间上的。
write()函数有自己缓冲区,一般来说,要等到缓冲区满或者用户不在写入了,write才切换到内核态执行,这样做大大加快系统的运行效率。

(计算机科学中,有一种特别重要的思想,就是通过增加中间模型,来使得系统运行更加敏捷,比如,缓存等,就像是润滑剂一样,实际上两个齿轮就可以做的事情,加上润滑剂会跑的更快~)

3.系统调用内核与用户态切换的过程:

3.1 堆栈和堆栈寄存器
cpu有一个堆栈寄存器,作用如下:
1.当cpu的堆栈寄存器指向的是用户的地址空间,说明系统现在处于用户态,正在执行用户空间的代码;
2.当cpu的堆栈寄存器指向的是内核的地址空间,说明系统正在处于内核态,正在执行内核空间的代码。

cpu的堆栈寄存器指向哪里(用户的堆栈/内核的堆栈),就是去哪里执行代码。

3.2 内核栈和用户栈
内核栈:是内核固有的一块区域,用来保护中断现场,内核中 函数 之间相互调用的参数,返回值等。
用户栈:专门用于用户执行各种各样的函数的内存,随函数调用开始结束共存亡

3.3 内核态和用户态切换:

1.用户态——>内核态:
cpu保存用户当前堆栈信息保存到内核的栈中(恢复时用到),然后将cpu指向内核堆栈,去执行内核代码。
2.内核态——>用户态:
再切换到内核堆栈前,将用户堆栈信息压入到内核栈中,内核函数执行完回退栈帧,会将用户的堆栈信息POP出栈,然后cpu堆栈寄存器就知道怎么回去了,返回的用户程序中断的地方继续执行。
系统调用

注:以上纯属个人见解,如有不恰当的地方,希望不吝赐教。

相关文章: