☰
Linux系统——文件(上)
2026/9/28 7:14:19 网站建设 项目流程

💁‍♂️个人主页:进击的荆棘

👇作者其它专栏:

《数据结构与算法》《算法》《C++起始之路》《Linux》


目录

1.理解硬件

2.引入文件系统

3.ext2文件系统

4.软硬连接


1.理解硬件

1.1磁盘、服务器、机柜、机房

●机械磁盘是计算机中唯一的一个机械设备

●磁盘——外设

●慢

●容量大,价格便宜

1.2磁盘物理结构

1.3磁盘的存储结构

扇区:是磁盘存储数据的基本单位,512字节,块设备

如何定义一个扇区?

●可以先定位磁头(header)

●确定磁头要访问哪一个柱面(磁道)(cylinder)

●定位一个扇区(sector)

●CHS地址定位

文件=内容+属性,都是数据,本质是占据几个扇区的问题。能定位一个扇区,能不能定位多个扇区?

●扇区是从磁盘读出和写入信息的最小单位,通常大小为512字节

●磁头(head)数:每个盘片上一般有上下两面,分别对应1个磁头,共2个磁头

●磁道(track)数:磁道是从盘片外圈往内圈编号0磁道,1磁道……,靠近主轴的同心圆用于停靠磁头,不存储数据

●柱面(cylinder)数:磁道构成柱面,数量上等同磁道个数

●扇区(sector)数:每个磁道都被切分为很多扇形区域,每道的扇区数量相同

●圆盘(platter)数:盘片的数量

●磁盘容量=磁头数 X 磁道(柱面)数 X 每道扇区数 X 每扇区字节数

●细节:传动臂上的磁头是共进退的

柱面(cylinder),磁头(head),扇区(sector),可以定位数据,这就是数据定位(寻址)方法之一,CHS寻址方式。

CHS寻址

对早期的磁盘非常有效,知道用哪个磁头,读取哪个柱面上的第几个扇区就可以读到数据了。但是CHS模式支持的硬盘容量有限,因为系统用8bit来存储磁头地址,用10bit来存储柱面地址,用6bit来存储扇区地址,而一个扇区512Byte,这样使用CHS寻址一块硬盘最大容量为256*1024*64*512B=8064(1MB=1048576B)(若按1MB=1000000B来算就是8.4GB)

1.4磁盘的逻辑结构

1.4.1理解过程

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

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

这样每个扇区就有了一个线性地址(其实就是数组下标),这种地址叫做LBA(Logical Block Address)

1.4.2真实过程

传动臂上的磁盘是共进退的

柱面是一个逻辑上的概念,其实就是每一面上,相同半径的磁道逻辑上构成柱面

所以,磁盘逻辑上分了很多面,但是在我们看来,逻辑上,磁盘整体是由“柱面”卷起来的

所以,磁盘的真实情况是:

磁道:

某个盘面的某一个磁道展开:

即:一维数组

柱面:

正磁盘所有盘面的同一个磁道,即柱面展开:

●柱面上的每个磁盘,扇区个数是一样的

●就像二维数组

整盘:

整个磁盘就是多张二维的扇区数组表(三维数组)

所以,寻址一个扇区:先找到哪一个柱面(Cylinder),在确定柱面内哪一个磁道(其实就是磁头位置,Head),在确定扇区(Sector),所以就有了CHS

因此,在我们看来,其实全部都是一维数组:

所以,每一个扇区都有一个下标,被称为LBA(Logical Block Address)地址,其实就是线性地址。如何得到这个LBA地址?

OS只需要使用LBA就可以了。LBA可以转成CHS地址,CHS可以转成LBA地址。这不需要用户,磁盘自己就可以做。

1.5CHS&&LBA地址

CHS转成LBA:

●磁头数*每磁道扇区数=单个柱面的扇区总数

●LBA=柱面号C*单个柱面的扇区总数+磁头号H*每磁道扇区数+扇区号S-1

●即:LBA=柱面号C*(磁头数*每磁道扇区数)+磁头号H*每磁道扇区数+扇区号S-1

●扇区号通常是从1开始的,而在LBA中,地址是从0开始的

●柱面和磁道都是从0开始编号的

●总柱面,磁道个数,扇区总数等信息,在磁道内部会自动维护,上层开机的时候,会获取道这些参数

LBA转成CHS:

●柱面号C=LBA//(磁头数*每磁道扇区数)【就是单个柱面的扇区总数】

●磁头号H=(LBA%(磁头数*每磁道扇区数))//每磁道扇区数

●扇区号S=(LBA%每磁道扇区数)+1

●“//”:表示除取整

所以:从此往后,在磁盘使用者看来,根本就不关心CHS地址,而是直接使用LBA地址,磁盘内部自己转化。因此:

从现在开始,磁盘就是一个元素为扇区的一维数组,数组的下标就是每个扇区的LBA地址。OS使用磁盘,就可以用一个数字访问磁盘扇区。

2.引入文件系统

2.1引入“块”概念

其实硬盘是典型的“块”设备,操作系统读取硬盘数据的时候,其实是不会一个一个扇区读取的,这样效率太低,而是一次性连续读取多个扇区,即一次性读取一个“块”(block)。

硬盘的每个分区是被划分为一个个的“块”。一个“块”的大小是由格式化的时候确定的,并且不可更改,最常见的是4KB,即连续8个扇区组成一个“块”。“块”是文件存取的最小单位。

注意:

●磁盘就是一个三维数组,而我们把它看成一个“一维数组”,数组下标就是LBA,每个元素都是扇区

●每个扇区都有LBA,那么8个扇区一个块,每一个块的地址也能算出来

●知道LBA:块号=LBA/8

●知道块号:LBA=块号*8+n(n是块内第几个扇区)

2.2引入“分区”概念

其实磁盘是可以被分成多个分区(partition)的,以Windows观点来看,一块磁盘可能被分区为C,D,E盘。C,D,E就是分区。分区从实质上说就是对硬盘的一种格式化。但是Linux的设备都是以文件形式存在,又该如何区分?

柱面是分区的最小单位,可以利用参考柱面号码的方式来进行分区,其本质就是设置每个区的起始柱面和结束柱面号码。此时我们可以将硬盘上的柱面(分区)进行平铺,将其想象为一个大的平面,如下图所示:

注:

●柱面大小一致,扇区个位一致,所以只要知道每个分区的起始和结束柱面号,知道每个柱面有多少个扇区,那么该分区多大,与解释LBA是多少也就清楚了。

2.3引入“inode”概念

文件=数据+属性,使用ls -l的时候除了能看到文件名,还能看到文件元数据(属性)

[sjx@VM-0-6-centos ~]$ ls -l total 12 -rw-rw-r-- 1 sjx sjx 827 Jul 20 18:04 install.sh drwxrwxr-x 12 sjx sjx 4096 Sep 17 22:00 linux -rw-rw-r-- 1 sjx sjx 625 Sep 10 20:18 Makefile

每行包含7列:

●模式

●硬链接数

●文件所有者

●组

●大小

●最后修改时间

●文件名

ls -l读取存储在磁盘上的文件信息,然后显示出来

这个信息除了通过这种方式来读取,还可以使用stat命令看到更多信息

[sjx@VM-0-6-centos ~]$ stat Makefile File: ‘Makefile’ Size: 625 Blocks: 8 IO Block: 4096 regular file Device: fd01h/64769d Inode: 658165 Links: 1 Access: (0664/-rw-rw-r--) Uid: ( 1001/ sjx) Gid: ( 1001/ sjx) Access: 2026-09-13 21:08:03.034928673 +0800 Modify: 2026-09-10 20:18:12.216482861 +0800 Change: 2026-09-10 20:18:12.216482861 +0800 Birth: -

此时还要思考一个问题,文件数据都存储在“块”中,所以我们还需要找到一个地方存储文件的元信息(属性信息),如文件的创建者、文件创建日期、文件大小等。这种存储文件元信息的区域叫做inode,也称“索引节点”。

每个文件都有对应的inode,里面包含了与文件有关的信息。

注:

●Linux下文件的存储是属性和内容分离存储的

●Linux下,保存文件属性的集合叫做inode,一个文件对应一个inode,inode内有一个唯一的标识符,叫做inode号

以下为一个文件的属性inode

/* * Structure of an inode on the disk */ struct ext2_inode { __le16 i_mode; /* File mode */ __le16 i_uid; /* Low 16 bits of Owner Uid */ __le32 i_size; /* Size in bytes */ __le32 i_atime; /* Access time */ __le32 i_ctime; /* Creation time */ __le32 i_mtime; /* Modification time */ __le32 i_dtime; /* Deletion Time */ __le16 i_gid; /* Low 16 bits of Group Id */ __le16 i_links_count; /* Links count */ __le32 i_blocks; /* Blocks count */ __le32 i_flags; /* File flags */ union { struct { __le32 l_i_reserved1; } linux1; struct { __le32 h_i_translator; } hurd1; struct { __le32 m_i_reserved1; } masix1; } osd1; /* OS dependent 1 */ __le32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */ __le32 i_generation; /* File version (for NFS) */ __le32 i_file_acl; /* File ACL */ __le32 i_dir_acl; /* Directory ACL */ __le32 i_faddr; /* Fragment address */ union { struct { __u8 l_i_frag; /* Fragment number */ __u8 l_i_fsize; /* Fragment size */ _le16 l_i_uid_high; /* these 2 fields */ __le16 l_i_gid_high; /* were reserved2[0] */ __u32 l_i_reserved2; } linux2; struct { __u8 h_i_frag; /* Fragment number */ __u8 h_i_fsize; /* Fragment size */ __u16 i_pad1; __le16 h_i_mode_high; __le16 h_i_uid_high; __le16 h_i_gid_high; __le32 h_i_author; } hurd2; struct { __u8 m_i_frag; /* Fragment number */ __u8 m_i_fsize; /* Fragment size */ __u16 m_pad1; __u32 m_i_reserved2[2]; } masix2; } osd2; /* OS dependent 2 */ }; /* * Constants relative to the data blocks */ #define EXT2_NDIR_BLOCKS 12 #define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS #define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1) #define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1) #define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1) 备注:EXT2_N_BLOCKS = 15

注:

●文件名属性并未纳入道inode数据结构内部

●inode的大小一般为128字节或256

●任何文件的内容大小可以不同,但属性大小一定是相同的(128)

3.ext2文件系统

3.1宏观认识

想要在硬盘上存储文件,必须先把硬盘格式化为某种格式的文件系统,才能存储文件。文件系统的目的就是组织和管理硬盘中的文件。在Linux系统中,最常见的是ext2系列的文件系统。其早期版本为ext2,后来发展除ext3和ext4.ext3和ext4虽然对ext2进行了增强,但是其核心设计并没有改变。

ext2文件系统将整个分区划分为若干同样大小的块组(Block Group),如下图。只要能管理一个分区就能管理所有分区,也就能管理所有磁盘文件。

上图启动块(Boot Block/Sector)的大小是确定的,为1KB,由PC标准规定,用来存储磁盘分区信息和启动信息,任何文件系统都不能修改启动块。启动块之后才是ext2文件系统的开始。

3.2Block Group

ext2文件系统会根据分区的大小划分为数个Block Group。而每个Block Group都有相同的结构组成。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询