首先,在windows中是文件的东西,它们在linux中也是文件;其次一些在windows中不是文件的东西,比如进程、磁盘、显示器、键盘这样硬件设备也被抽象成了文件,你可以使用访问文件的方法访问它们获得信息;甚至管道,也是文件;网络编程中的socket(套接字)这样的东西,使用的接口跟文件接口也是⼀致的。
这样做最明显的好处是,开发者仅需要使用一套 API 和开发⼯具,即可调取 Linux 系统中绝大部分的资源。举个简单的例子,Linux 中几乎所有读(读文件,读系统状态,读PIPE)的操作都可以用read 函数来进行;几乎所有更改(更改文件,更改系统参数,写 PIPE)的操作都可以用write函数来进行。
当打开一个文件时,操作系统为了管理所打开的文件,都会为这个文件创建一个file结构体。
struct file 中的 f_op 指针指向了一个 file_operations 结构体,这个结构体中的成员除了struct module* owner 其余都是函数指针。
file_operation 就是把系统调用和驱动程序关联起来的关键数据结构,这个结构的每⼀个成员都对应着⼀个系统调用。读取 file_operation 中相应的函数指针,接着把控制权转交给函数,从而完成了Linux设备驱动程序的工作。

上图中的外设,每个设备都可以有自己的read、write,但一定是对应着不同的操作方法!!但通过struct file 下 file_operation 中的各种函数回调,让我们开发者只用file便可调取 Linux 系统中绝⼤部分的资源!!这便是“linux下一切皆文件”的核心理解。
缓冲区是内存空间的⼀部分。也就是说,在内存空间中预留了⼀定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区。缓冲区根据其对应的是输入设备还是输出设备,分为输入缓冲区和输出缓冲区。
标准I/O提供了3种类型的缓冲区。
除了上述列举的默认刷新方式,下列特殊情况也会引发缓冲区的刷新:


核心机械组件 :
数据存储的物理结构:

如何定位一个扇区:
柱面(cylinder),磁头(head),扇区(sector),显然可以定位数据了,这就是数据定位(寻址)方式之一,CHS寻址方式。

磁带上面可以存储数据,我们可以把磁带“拉直”,形成线性结构。

那么磁盘本质上虽然是硬质的,但是逻辑上我们可以把磁盘想象成为卷在一起的磁带,那么磁盘的逻辑存储结构我们也可以类似于:

这样每一个扇区,就有了一个线性地址(其实就是数组下标),这种地址叫做 LBA。
所以,磁盘的真实情况是:
磁道:
某一盘面的某一个磁道展开,即:一维数组

柱面:
整个磁盘所有盘面的同一个磁道,即柱面展开,一个二维数组。

柱面展开类似于下面的过程:

整盘展开:即一个三维数组

所以,寻址一个扇区:先找到哪⼀个柱面(Cylinder) ,在确定柱⾯内哪一个磁道(其实就是磁头位置,Head),在确定扇区(Sector),所以就有了CHS 。
其实这个三位数组,我们可以看成是一个一维数组。

所以,每一个扇区都有一个下标,我们叫做 LBA(Logical Block Address) 地址,其实就是线性地址。所以怎么计算得到这个LBA地址呢?

OS只需要使用LBA就可以了!!LBA地址转成CHS地址,CHS如何转换成为LBA地址。谁做啊??磁盘自己来做!
CHS转成LBA:
LBA转成CHS:
所以:从此往后,在磁盘使用者看来,根本就不关心CHS地址,而是直接使用LBA地址,磁盘内部自己转换。所以:从现在开始,磁盘就是一个元素为扇区 的一维数组,数组的下标就是每一个扇区的LBA地址。OS使用磁盘,就可以用一个数字访问磁盘扇区了。
其实硬盘是典型的“块”设备,操作系统读取硬盘数据的时候,其实是不会一个个扇区地读取,这样效率太低,而是一次性连续读取多个扇区,即一次性读取一个”块”(block)。
硬盘的每个分区是被划分为一个个的”块”。一个”块”的大小是由格式化的时候确定的,并且不可以更改,最常见的是4KB,即连续八个扇区组成⼀个 ”块”。”块”是文件存取的最小单位。
注意:

其实磁盘是可以被分成多个分区(partition)的,以Windows观点来看,你可能会有⼀块磁盘并且将它分区成C,D,E盘。那个C,D,E就是分区。分区从实质上说就是对硬盘的一种格式化。

文件=数据+属性。
我们使用ls -l 的时候看到的除了看到文件名,还能看到文件元数据(属性)。
所以,文件在磁盘上存储的狮虎,不仅要存储文件的内容数据,还要存储属性,这个属性就是文件的inode信息。
本质上这是一个结构体,包含文件的各种属性,比如文件类型,文件所有者,大小,最后修改时间......等。
还有一个inode_number整型数字,inode_number和文件是一一对应的。
这个结构体的大小一般是128字节。(这个结构题不包含文件名,因为文件名长度是变化的,如果保存在该结构中,那么结构体的长度也就大小不一了)。
我们想要在硬盘上储文件,必须先把硬盘格式化为某种格式的文件系统,才能存储文件。文件系统的目的就是组织和管理硬盘中的文件。
ext2文件系统将整个分区划分成若干个同样大小的块组 (Block Group),如下图所示。只要能管理⼀个分区就能管理所有分区,也就能管理所有磁盘文件。
ext2文件系统会根据分区的大小划分为数个Block Group。

上图中启动块(Boot Block/Sector)的大小是确定的,为1KB,由PC标准规定,用来存储磁盘分区信息和启动信息,任何文件系统都不能修改启动块。启动块之后才是ext2文件系统的开始。
存放文件属性 如文件大小,所有者,最近修改时间等
数据区:存放文件内容,也就是一个一个的Block。根据不同的⽂件类型有以下几种情况:
Block Bitmap中记录着Data Block中哪个数据块已经被占用,哪个数据块没有被占用。
每个bit表示一个inode是否空闲可用。
块组描述符表,描述块组属性信息,整个分区分成多个块组就对应有多少个块组描述符。每个块组描述符存储一个块组的描述信息,如在这个块组中从哪里开始是inode Table,从哪里开始是DataBlocks,空闲的inode和数据块还有多少个等等。块组描述符在每个块组的开头都有一份拷贝。
存放文件系统本身的结构信息,描述整个分区的文件系统信息。记录的信息主要有:bolck 和 inode的总量,未使用的block和inode的数量,一个block和inode的大小,最近一次挂载的时间,最近一次写入数据的时间,最近一次检验磁盘的时间等其他文件系统的相关信息。Super Block的信息被破坏,可以说整个文件系统结构就被破坏了。
超级块在每个块组的开头都有⼀份拷贝(第⼀个块组必须有,后面的块组可以没有)。 为了保证文件系统在磁盘部分扇区出现物理问题的情况下还能正常工作,就必须保证文件系统的super block信息在这种情况下也能正常访问。所以⼀个文件系统的super block会在多个block group中进行备份,这些super block区域的数据保持一致。
知道inode号的情况下,在指定分区,请解释:对文件进行增、删、查、改是在做什么?
目录也是文件,但是磁盘上没有目录的概念,只有文件属性+文件内容的概念。
目录的属性不⽤多说,内容保存的是:文件名和Inode号的映射关系。
问题:打开当前工作目录文件 ,查看当前工作目录文件的内容?当前工作目录不也是文件吗?我们访问当前工作目录不也是只知道当前工作目录的文件名吗?要访问它,不也得知道当前工作目录的inode吗?
答案1:所以也要打开:当前工作目录的上级目录,额....,上级目录不也有目录吗??不还是上面的问题吗?
答案2:所以类似"递归",需要把路径中所有的目录全部解析,出口是"/"根目录。
最终答案3:实际上,任何文件,都有路径,访问目标,比如:/home/xg/code/test/test/test.c
都要从根目录开始,依次打开每一个目录,根据目录名,依次访问每个目录下指定的目录,直到访问到test.c。这个过程叫做Linux路径解析。
可是路径谁提供?
问题1:Linux磁盘中,存在真正的目录吗?
答案:不存在,只有文件。只保存文件属性+文件内容
问题2:访问任何⽂件,都要从/目录开始进⾏路径解析?
答案:原则上是,但是这样太慢,所以Linux会缓存历史路径结构
问题2:Linux目录的概念,怎么产生 的?
答案:打开的文件是目录的话,由OS自己在内存中进行路径维护。
Linux中,在内核中维护树状路径结构的内核结构体叫做: struct dentry,这个结构体中就包含了文件的inode信息。
真正找到磁盘上文件的并不是文件名,而是inode。其实在linux中可以让多个文件名对应于同一个inode。
[root@localhost linux]# touch abc
[root@localhost linux]# ln abc def
[root@localhost linux]# ls -li abc def
263466 abc
263466 defabc和def的链接状态完全相同,他们被称为指向⽂件的硬链接。内核记录了这个连接数,inode 263466 的硬连接数为2。
我们在删除文件时干了两件事情:1.在目录中将对应的记录删除,2.将硬连接数-1,如果为0,则将对应的磁盘释放。
用途:
硬链接是通过inode引用另外一个文件,软链接是通过名字引用另外⼀个文件,但实际上,新的文件和被引用的文件的inode不同,应用常见上可以想象成一个快捷方式。
[root@localhost linux]# ln -s abc.s abc
1
[root@localhost linux]# ls -li
263563 -rw-r--r--. 2 root root 0 9⽉ 15 17:45 abc
261678 lrwxrwxrwx. 1 root root 3 9⽉ 15 17:53 abc.s -> abc
263563 -rw-r--r--. 2 root root 0 9⽉ 15 17:45 def用途:类似快捷方式。