chapter 7 文件操作&chapter 8 使用系统调研进行文件操作
7.1 文件操作
文件操作由五个层次构成,从低到高,如下图所示。
7.1.1 硬件级别
硬件级别的文件操作包括以下程序:
- fdisk:将硬盘、USB 或 SDC 驱动器分成分区。
- mkfs:格式化磁盘分区以准备它们用于文件系统。
- fsck:检查和修复文件系统。
- 碎片整理:压缩文件系统中的文件。
7.1.2 操作系统内核中的文件系统函数
每个操作系统内核都提供基本的文件系统操作支持。这些函数往往是系统面向的工具程序。
kmount(), kumount() // 挂载/卸载文件系统
kmkdir(), krmdir() // 创建/删除目录
kchdir(), kgetcwd() // 更改目录,获取当前工作目录路径名
klink(), kunlink() // 硬链接/取消链接文件
kchmod(), kchown(), kutime() // 更改 r|w|x 权限、所有者、时间
kcreat(), kopen() // 创建/打开文件以进行读取、写入、读写、添加操作
kread(), kwrite() // 读取/写入已打开的文件
klseek(), kclose() // 定位、关闭文件描述符
ksymlink(), kreadlink() // 创建、读取符号链接文件
kstat(), kfstat(), klstat() // 获取文件状态/信息
kopendir(), kreaddir() // 打开、读取目录
7.1.3 系统调用
用户模式程序使用系统调用来访问内核函数。可以使用 C 库提供的一系列标准 I/O 函数来发出系统调用。
7.1.4 库 I/O 函数
标准 I/O 函数通过系统调用间接调用内核的文件系统函数。
7.1.5 Shell 命令
用户可以使用 Unix/Linux 命令而不是编写程序来进行文件操作。
7.1.6 sh脚本
sh脚本是用sh编程语言编写的程序,可通过命令解释程序sh来执行。
7.2 文件I/O操作
文件I/O操作是在计算机中对文件进行读写的过程。下面是文件I/O操作的流程:
- 用户进程执行
fopen()
函数来打开读/写文件流。 fopen()
函数在用户空间中创建一个文件结构体,同时向内核发出打开文件的系统调用。- 内核根据系统调用创建一个
OpenTable
表示打开的文件实例,并将其与用户空间的文件结构体相关联。 - 用户进程使用
fread()
或fwrite()
函数读取或写入文件内容。- 如果文件结构体中有足够的数据,就直接返回。
- 如果文件结构体中没有更多数据,则向内核发出读取块的系统调用,将文件块读取到文件结构体中,并将数据复制到用户空间中。
- 如果文件结构体中还有空间,则将数据复制到文件结构体中。
- 如果文件结构体已满,则向内核发出写入块的系统调用,将文件块写入内核空间。
- 文件系统函数操作中,如果是非特殊文件,则使用
read()
系统调用从内核中读取文件块。 - 在
read()
系统调用中,根据文件描述符找到相应的OpenTable
,其中存储了文件的一些属性和控制信息。 - 根据
OpenTable
的偏移量,计算逻辑块号,并将其转换为物理块号。 - 根据物理块号读取磁盘块中的数据。
- 为了提高磁盘I/O效率,内核通常使用一组I/O缓冲区进行缓存。
- 如果缓冲区的数据无效,则进行物理I/O操作,将数据从磁盘读取到缓冲区中。
- 如果缓冲区的数据有效,则将数据从缓冲区复制到文件结构体中。
- 最终,设备驱动程序会执行物理I/O请求,将数据从缓冲区写入磁盘。
7.3 低级文件操作
7.3.1 分区
- 块存储设备(如硬盘、USB驱动器、SD卡等)可以分为多个逻辑单元,称为分区。
- 每个分区可以格式化为特定的文件系统,并安装不同的操作系统。
- 大多数引导程序(如GRUB、LILO等)可以配置从各个分区启动不同的操作系统。
- 分区表位于第一个扇区的字节偏移量0x1BE(即设备的主引导记录MBR)。该表有4个条目,每个条目由16个字节的分区结构定义。
struct partition {
u8 drive; // 0x80 - 活动分区
u8 head; // 起始磁头
u8 sector; // 起始扇区
u8 cylinder; // 起始柱面
u8 sys_type; // 分区类型
u8 end_head; // 结束磁头
u8 end_sector; // 结束扇区
u8 end_cylinder; // 结束柱面
u32 start_sector; // 从0开始计数的起始扇区
u32 nr_sectors; //分区中的扇区数
};
-
如果分区是EXTEND类型(类型号=5),则可以分成更多分区。假设分区P4是EXTEND类型,分为扩展分区P5、P6、P7。扩展分区在扩展分区区域形成链接列表,如图所示。
-
每个扩展分区的第一个扇区是一个本地MBR。每个本地MBR也有一个分区表,位于0x1BE的字节偏移,仅包含两个条目。第一个条目定义扩展分区的起始扇区和大小。第二个条目指向下一个本地MBR。所有本地MBR的扇区号都是相对于P4的起始扇区的。通常,链接列表以最后一个本地MBR中的0结束。在分区表中,CHS值只对小于8GB的磁盘有效。对于大于8GB但小于4G扇区的磁盘,只有最后2个条目,即start_sector和nr_sectors有意义。
7.3.2 格式化分区
在 Linux 系统中,要将一个分区用于文件存储,必须先将它格式化为指定的文件系统类型。Linux 支持许多种不同的文件系统类型,可以使用 mkfs 命令来对存储设备进行格式化操作。
filetype和mkfs命令
mkfs 命令格式如下:
mkfs -t TYPE [-b bsize] device nblocks
其中,TYPE 表示要创建的文件系统类型;bsize 表示块大小,如果未指定,则默认为 1KB;device 表示要格式化的设备名称;nblocks 表示设备中块的总数。
例如,要将 vdisk 格式化为 EXT2 文件系统,可以使用以下命令:
mkfs –t ext2 vdisk 1440
还可以使用 mke2fs 命令:
mke2fs vdisk 1440
挂载和卸载存储设备
格式化后的存储设备不会立即存储文件,还需要将它挂载到已有的目录中,作为文件系统的一部分。通常使用 /mnt 目录来挂载其它文件系统设备。
使用 mount 命令可以挂载存储设备,例如:
sudo mount –o loop vdisk /mnt
此命令会将 vdisk 挂载到 /mnt 目录。
使用 umount 命令可以对挂载的设备进行卸载操作,例如:
sudo umount /mnt
卸载设备后,文件应该仍然保存在设备中。
7.3.3 挂载分区
mount 命令可以挂载实际设备的分区或整个虚拟磁盘,但不能挂载虚拟磁盘的分区。如果虚拟磁盘包含分区,必须先关联分区和回环设备。
使用 losetup 命令可以创建回环设备,例如:
losetup -o $(expr 2048 \* 512) --sizelimit $(expr 65535 \* 512) /dev/loop1 vdisk
此命令会创建一个回环设备 /dev/loop1 并关联到 vdisk 的第一个分区。
创建好回环设备后,可以使用 mkfs 命令对分区进行格式化:
mke2fs -b 4096 /dev/loop1 7936
然后,可以使用 mount 命令挂载回环设备:
mount /dev/loop1 /mnt
操作完成后,应该使用 umount 和 losetup 命令分别卸载和删除回环设备。
标签:chapter,文件,分区,扇区,文件系统,内核,操作 From: https://www.cnblogs.com/yuzhenyang/p/17735557.html