【Linux 系统】理解Linux下一切皆文件

文章目录

前言

在C语言中,我们都知道一个进程会默认为我们打开三个文件:一个是标准输入流、一个是标准输出流、一个是标准错误流。他们分别指向是:键盘、显示器。这个时候就有疑问了?为什么我们能通过对FILE*的操作转化为对硬件设备操作呢?

学习 Linux 文件系统的时候,听过很多的一句话就是Linux 下一切皆文件。很多初学者对于这句话很难理解:硬件设备是如何被操作系统管理起来的呢?

接下来,小编会和大家浅浅谈谈这个话题:Linux 下一切皆文件。我们将从硬件出发来理解这句话。

理解

小编的理解思路是:从下层向上层去找。

第一层

首先硬件设备都是外设 ,操作系统(这里指 Linux)是软硬件的管理者。而操作系统管理的方式就是:"先描述,再组织 "。所以在 Linux 内核中一定会为硬件设备创建对应的 struct device 这样的结构体来描述一个硬件设备。

c 复制代码
struct device
{
	//硬件设备的属性
};

对于每一个硬件设备,都具有不同的读写方法 。例如:键盘设备只有读方法没有写方法、显示器设备只有写方法没有读方法......每一种硬件设备的方法都是大相径庭的。在描述硬件设备中的 struct device 中或许就有使用硬件设备的方法。指向方法的代码。

第二层

关键 :虽然每种方法的实现是不一致的,但是我们不可否定的是:每种设备的方法属性可是一致的 。所以,上层我们就可以提供函数指针 来封装下层的各种调用方法了。在 Linux 内核中会有许多的方法 (来自硬件、网络......),Linux 的做法是将这些方法都描述起来:struct operation_func 其中封装了各种的函数指针。用于指向各种设备的方法。

c 复制代码
struct operation_func
{
//泛型(不一定是这样实现了)
//  对应方法还是要看源码
	int (*write)(void);
	int (*read)(void);
	// ......其它属性的读方法
};

这样的函数指针指向下层的各种设备的方法。问题是上层如何区分应该调用哪个方法呢?判断属性即可,我们可以设置属性字段......方式让上层正确调用。

第三层

再往上层就是我们的文件管理 了。内核中,为每一个打开的文件都创建了一个 struct file 结构体来描述打开的文件。所以,为了得到对应写文件的方法,必然:struct file 必须有一个字段,能够找到对应的方法。这个字段就是:struct operation_func *op 一个指针,就能执行对应的方法描述结构体了。

c 复制代码
stuct file
{
	struct operation_func* op;
}

最后,就是同层的调用 了。进程 struct task_struct中的一个字段指向struct file_struct。其中的struct file* arr[]指向描述的文件 struct file。

总结

从上层来看,我们只需要使用系统调用read/write类似的方法就可以向键盘读取/显示器写入。或许read函数是像类似下面的样子进行封装的:

c 复制代码
ssize_t read(int fd/*...*/)
{
	task->files->arr[fd]->op->read();
}

实际上的设计不可能像小编说的这样简单,只会更加复杂。各种判断......这里小编只是帮助大家理解!!!

于是:上层对于同一种方法的调用形成了不同的效果 。这就是C语言实现的多态!!!

如下图:

上面C语言实现多态的前提就是:不同的方法属性是相同的。那么我们就可以用同一类型的指针进行调用。对上层来看就是:调用同一种方法调用执行了不同的结果。

我们再来看开始的那一个问题:键盘和显示器是如何做到的呢?实际上也是这样的逻辑。FILE 中封装了文件描述符 fd(Linux下)(C语言的使用者是0感知的)。下层通过第二层,实现了各种同属性方法的统一封装 ,上层在调用的时候就忽略了这种方法实现的差异。read/write方法就可以对键盘和显示器使用了。

Linux 内核扮演了一个"万能翻译官"的角色。它向上(对应用程序)提供了一套统一的文件操作 API。当应用程序调用 read(fd, ...) 时,内核会根据文件描述符 fd 所代表的实际资源(是硬盘?是键盘?还是网络套接字?),去调用相应的底层驱动程序(硬盘驱动、键盘驱动、网络协议栈)来完成真正的读操作,然后将结果返回给应用程序。

最后在这里提醒各位:这些理解都是小编个人理解。如果有不正确欢迎大家指出。小编会谦虚学习!!!

相关推荐
Lsetea6 小时前
curl指定CA目录仍报证书不受信任:--capath与OpenSSL rehash排查
运维·https·ssl·openssl·curl
夜听莺儿鸣6 小时前
502-002_Linux驱动开发模块化编程
linux·驱动开发·模块化编程
wuminyu7 小时前
C++协程实现接收端的零拷贝Buffer管理原理剖析
java·linux·c语言·jvm·c++
优化Henry7 小时前
LTE 载波频率与频点配置详解
运维·网络·学习·5g·信息与通信
代码方舟7 小时前
数据科学风控实战:基于天远全能消金报告构建自动化信用评估网关
运维·人工智能·自动化
科力锐品牌君7 小时前
应用级灾备 | 海量非结构化数据如何实现高效数据保护
linux·运维·网络·安全·系统安全·数据安全·灾备
KaiwuDB8 小时前
KaiwuDB 运维实战04:DRBD + KaiwuDB——物联网场景下的低成本数据库高可用方案
运维·数据库·物联网·时序数据库·kaiwudb·aiot·多模数据库
zhangrelay8 小时前
ROS项目设计案例智能大模型正经乱答案例
linux·笔记·学习·ubuntu·机器人
福建佰胜张工8 小时前
A5E00839230西门子工业核心配件详解:参数、安装调试与故障运维全攻略
运维·网络·安全·自动化
流浪0018 小时前
Linux系统篇39——线程(四) pthread库的由来和线程的创建与等待
linux·操作系统·线程·pthread库