Linux 设计哲学系列(一) —— 分层架构思想

在探索linux的某些完全不相关的module时,笔者意识到了一些共性的内容,我不认为这是一种巧合,而是一种设计的哲学,比如本文讨论的分层架构。本文深入剖析了Linux系统的分层架构思想。以read调用读取1字节、面包供应链为例,拆解了从应用层到硬件层的层级逻辑。从「What」「Why」「How」三个维度,帮助读者以最快速度、最简易方式理解Linux的分层设计哲学。

一、What:分层架构是什么?

我们首先来看一个生活实例,假如说你现在想吃面包,你会怎么办?

        第一种方式:很简单,找一家卖面包的店,购买即可,对吧。

        第二种方式:自己种小麦、收割、磨成面粉、加工、送入烤箱得到成品,但没人会这样做

        OK这就是分层和不分层的区别啊

那么如何精准描述Linux的分层架构呢:

       Linux 分层架构设计是按功能拆分的多层结构,各层独立各司其职,层间通过固定接口交互,互不干涉,便于维护和扩展。

 结合例子来理解一下Linux的分层架构:

        先别问为啥要这样做,在第二节会讨论。回到我们获得面包的案例,正常人都会选择去面包房买面包,那么你就是分层架构里面的一层,其他层有:面包店、各种材料生产商、农民,etc.

        你去买面包,那你就是其中的消费者层,消费者里不止你一个人,但你们很多人目的都一样:进店买东西,所以你们所有人可以归为一层,其他层同理。很像抽象出一个类对吧,可以这么理解。此时你作为消费者层的一个实例:

        你不会和种小麦的农民产生任何交流,但你获得了农民生产的小麦制品。

        你会和面包店产生交互,但你并不关心面包店的其他信息,你只要获取面包而已。

        面包店上新了,消费者也是只需购买就ok了,不必关心面包店是不是换了原料供应商。

这就是:各层独立各司其职,层间通过固定接口交互,互不干涉,便于维护和扩展。

接下来我们来看一个Linux系统里的实例:

        Linux 分层架构在文件 IO 场景中体现得最为直观,我们要通过库函数read读取磁盘中的1byte数据,大致都要经过:应用层→C 函数库→系统调用→VFS→PageCache→文件系统→通用块层→IO 调度层→硬件驱动→硬件。

        现在你不必理解下图中这么多层分别干了什么,你只需要知道当你调用read时,并不是该函数直接去磁盘找了数据并交给你,而是经过了下图很多层的调用。

 下图表格说明了当你调用read函数读取磁盘文件数据时linux里发生了什么:

Linux IO 调用层

核心职责

1. 应用层(App)

发起文件读取请求(如代码中read(f,&c,1)读 1 字节)

2. C 函数库层

封装 IO 引擎(如read属于 sync 引擎),转发请求到系统调用

3. 系统调用层(Syscall)

接收库层请求,转换为内核可识别指令(如sys_read)

4. VFS

抽象文件系统模型,调用vfs_read,屏蔽 Ext4/XFS 等具体实现差异

5. PageCache

内存中的文件数据缓存,命中则直接返回数据,未命中则触发缺页中断

6. 文件系统层

实现 VFS 的具体操作,按 “块” 管理数据

7. 通用块层

抽象硬件差异,用bio结构描述 IO 请求,转发到 IO 调度层

8. IO 调度层

优化 IO 请求顺序

9. 硬件驱动层

适配具体硬件,将 IO 请求转为硬件指令

10. 硬件层(磁盘)

按 “扇区” 读取数据,返回给上层

        看完之后,可能有读者想说:怎么TM这么麻烦,我直接让read函数从硬盘里掏出来1Byte给我看不就完了?

        确实啊!对于任何一个实例来说,直接去做实现的话,流程确实会简化很多。但是系统中有这样千千万万个实例啊,如果每个实例我们都直接这样实现的话,那就不叫一个操作系统了,就会和菜市场一样混乱无序,这显然不是大家想要的。

本节我们找到了分层架构的核心特点:

        对于每一层,我们分对上层和对下层两方面来看

        与其下层的联系:依赖下一层的API,但不关心下一层的实现细节。

        与其上层的联系:给上层提供API。

二、Why:为什么要搞分层?

好的,下面请你回答问题

你买一块面包,关注什么,不关注什么?

你肯定关注:价格,品相,味道

你不太关注:原材料产地,做法,服务员的工资,etc.

那么原材料产地,做法,服务员的工资这些到底有没有人关注呢

肯定有的,但不是你啊!比如烘焙师关注面包做法,服务员关注自己的工资等等

那谁和你关注的要素一样呢?

答案当然是和你一样的消费者呗,所以你们消费者可以归为一类,因为你们关心同样的东西,你们的目的也是一样的。

我不知道我是否说清楚了......

问题答案如果让我来总结的话,就八个大字:

解耦、复用、拓展、可控

这也是要设计一个好的操作系统,必须要考虑的问题。

这四个词汇分别什么意思呢?

解耦:职责隔离,仅靠标准接口交互,改动独立无牵连;

复用:核心能力抽为公共服务,多场景直接调用不重复开发;

拓展:新增功能无需改动原有架构,灵活兼容适配;

可控:权限校验、风险拦截、问题可追溯,流程与风险均在掌控。

三、How:分层的优缺点

如果还用我们之前的例子,那就是你无需自己种小麦、收割、磨成面粉、加工、送入烤箱得到成品,只用通过从面包店购买,就可以达到和复杂方法一样的效果:获得了面包。

1. 分层的核心优点:

优点

IO 场景实例

性能优化(缓存)

PageCache 命中时,读 1 字节无需磁盘 IO,直接从内存返回

兼容性(屏蔽差异)

应用读 1 字节,不用关心磁盘是机械盘还是 SSD盘

效率(批量处理)

磁盘按扇区(512 字节)读,文件系统按块(4KB)存,PageCache 按页(4KB)缓存,一次 IO 能供多次读 1 字节的请求

安全(权限控制)

应用要读 1 字节,必须经过 VFS 权限校验,不能直接访问磁盘

2. 分层的缺点:

缺点

IO 场景实例(参考链接博客)

Linux 的优化手段

性能开销(额外 IO)

读 1 字节却最少要读 4KB(PageCache 页大小),造成 冗余 IO

1. 预读取策略:提前读更多数据,供后续请求使用;

2. 零拷贝技术,减少数据在层间拷贝的开销

调试复杂(问题定位难)

读 1 字节失败,可能是 PageCache 未命中、VFS 权限错、磁盘驱动故障

1. 日志工具:dmesg 看内核日志,strace 跟踪系统调用;

2. 性能工具:perf 分析 IO 耗时

架构冗余(流程长)

读 1 字节要经过好多层,流程比 直接读磁盘复杂得多

1. 动态模块:不用的层不加载;

2. 精简路径:高频请求跳过底层

本文参考:read 文件一个字节实际会发生多大的磁盘IO?_打开一个文件 会产生多少个io-优快云博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值