Linux系统结构一般分为四部分:
Linux 内核由如下几部分组成:内存管理、进程管理、设备驱动程序、文件系统和网络管理等。如图:
为了使用户有良好的运行环境,当用户需要调用系统内核函数时,操作系统就会将系统调用接口提供给用户使用。
而系统调用的作用就是将应用程序的请求给系统内核,调用相应的系统内核函数。Linux系统调用,包含了大部分常用的系统调用和由系统调用派生出的函数。
这里的在linux-x86上的系统调用是通过int 0x80实现,通过系统调用号区分函数入口:
API(Application Programming Interface)又称为应用程序接口。通过该接口用户程序员可以间接的访问到系统硬件和操作系统资源。操作系统的主要作用之一就是把系统硬件和操作系统资源进行封装并对上层用户进行屏蔽,防止用户有意无意的对系统造成破坏。操作系统就像一个保护壳一样保护系统资源不被外界破坏。因此,当用户需要对系统资源进行访问的时候,就必须通过操作系统向用户提供的接口才能实现用户对系统资源的访问,取得内核的服务。
API一般以函数定义的形式出现,如read()、malloc()、abs()等。但API并不需要和系统调用一一对应,它们之间的关系可以是一对一、一对多、多对一或者无关系。例如read()接口就和read系统调用对应,而abs()作用是求绝对值,不需要任何系统调用。而且一般API主要是通过C函数库来实现。
而ret2syscall中int 0x80 是一种用于在 Linux 系统中进行系统调用的方式,它通过向处理器发出中断信号,使得程序从用户态切换到内核态,以请求内核提供相应的服务。而 System Call Interface (SCI)
是操作系统提供的 API,用于执行从用户空间到内核空间的函数调用,从而实现用户程序对内核中功能的调用。
int 0x80 的实现需要依赖于 SCI 接口,在早期的 Linux 版本中,其中的一些系统调用就是通过 int 0x80 来实现的。在这个过程中,int 0x80 这条指令会触发中断,进而执行 SCI的相关代码,将程序从用户态切换到内核态,完成系统调用的过程。
因此,int 0x80 和 SCI 之间存在着密切的关系,可以说是两种不同层面上的实现方式。在较新版本的 Linux 中,int 0x80 已经逐渐被其他更加高效的实现方式所替代,但 SCI 接口作为操作系统提供的核心接口之一,一直扮演着非常重要的角色。
(系统调用 - 维基百科,自由的百科全书 (wikipedia.org))
((1条消息) 系统调用接口_xiaobaiyuan_bk的博客-CSDN博客)
(2.4. 系统调用接口 — 计算机系统基础 (jmu.edu))
因为物理空间中计算机内存是极为有限的,而实际使用中对计算机的各种操作都会占用计算机的内存。以下是主要问题:
引入一个中间层(即虚拟内存)对进程地址和物理地址进行隔离。
Linux系统对内存结点进行分区:
text`DMA`:0~16MB内存页框,可由老式基于ISA设备通过DMA使用,直接映射到内核的地址空间。是一种计算机系统中常用的数据传输方式,它可以让设备在不占用CPU时间的情况下,直接访问内存,实现高速数据传输。 在数据传输量大、速度要求高的场景中, DMA传输过程中,通常需要使用一个特殊的硬件设备——DMA控制器。(这里指不通过CPU来实现外设与数据交换的控制器,硬件)
(关于DMA(Direct memory access)比较通俗浅白的理解 - 腾讯云开发者社区-腾讯云 (tencent.com))
低于869MB界限为:low memory,反之,高于869MB则称为high memory。
如图:
三者关系:
页面大小:4kb。页表项大小:4B。32位虚拟地址可以表示的进程大小2^32为4GB。
页面面数为:2^20页,所以页表就需要4MB空间
用户空间被划分为5个不同的内存空间:text,data,BSS,heap,stack,
直接映射区 Direct Memory Region
:从内核空间起始地址开始,最大896M
的内核空间地址区间,为直接内存映射区。
直接映射区的896MB的「线性地址」直接与「物理地址」的前896MB
进行映射,也就是说线性地址和分配的物理地址都是连续的。内核地址空间的线性地址0xC0000001
所对应的物理地址为0x00000001
,它们之间相差一个偏移量PAGE_OFFSET = 0xC0000000
该区域的线性地址和物理地址存在线性转换关系「线性地址 = PAGE_OFFSET
+ 物理地址」也可以用 virt_to_phys()
函数将内核虚拟空间中的线性地址转化为物理地址。
内核空间中896MB到1GB空间被称为高端内存线性地址空间。前面提到0-896MB是直接映射,也就是和物理空间是一样连续的,但是实际上目前pc里的内存肯定都大于1GB,所以我们总不能后面的也都直接映射吧,这时候这后面的高端内存线性空间就得发挥作用了。他被划分为三块区域(这里只适用于32bit):
vmalloc Region
该区域由内核函数vmalloc
来分配,特点是:线性空间连续,但是对应的物理地址空间不一定连续。vmalloc
分配的线性地址所对应的物理页可能处于低端内存,也可能处于高端内存。
Persistent Kernel Mapping Region
该区域可访问高端内存。访问方法是使用 alloc_page (_GFP_HIGHMEM)
分配高端内存页或者使用kmap
函数将分配到的高端内存映射到该区域。
Fixing kernel Mapping Region
该区域和 4G 的顶端只有 4k 的隔离带,其每个地址项都服务于特定的用途,如 ACPI_BASE
等。
(手画好累)
虚拟文件系统(Virtual File system)是linux内核的文件子系统之一,它为用户程序提供文件和文件系统操作的统一接口,屏蔽不同文件系统的差异和操作细节。借助VFS可以直接使用open()
、read()
、write()
这样的系统调用操作文件,而无须考虑具体的文件系统和实际的存储介质。
VFS之所以能够衔接各种各样的文件系统,是因为它抽象了一个通用的文件系统模型,定义了通用文件系统都支持的、概念上的接口。新的文件系统只要支持并实现这些接口,并注册到Linux内核中,即可安装和使用。
举个例子,比如Linux写一个文件:
textint ret = write(fd, buf, len);
调用了write()
系统调用,它的过程简要如下:
sys_write()
处理。sys_write()
根据fd
找到所在的文件系统提供的写操作函数,比如op_write()
。op_write()
实际的把数据写入到文件中。Linux CFS 调度器:原理、设计与内核实现(2023) (arthurchiao.art)
shell的中文意思就是‘壳’,从第一张图中可以看出shell是建立在kernel之上的,shell就相当于kernel的一个接口,用于连接用户与内核空间。
本文作者:Hyrink
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!