chapter 7 文件操作&chapter 8 使用系统调研进行文件操作
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 命令分别卸载和删除回环设备。
苏格拉底挑战
点击查看问答详情
Linux文件操作知识问题
当然,让我们开始以苏格拉底的方式进行提问来探讨Linux系统中的文件操作和使用系统调用进行文件操作的知识点:
- 你认为在Linux系统中,文件是什么?它们有什么作用?
非常好,你已经提供了一个很好的定义。接下来的问题:
- 在Linux中,每个文件都有一个唯一的标识符吗?如果是的话,这个标识符是什么?如果不是,那么是如何标识文件的?
正确,每个文件都有一个唯一的inode号码。下一个问题:
- 在Linux中,如何创建一个新文件?请描述一下创建文件的基本步骤。
使用cd命令切换到想要创建文件的目录,例如:cd /path/to/directory。
使用touch命令创建新文件,例如:touch filename。这会在当前目录下创建一个名为"filename"的新文件。 可以使用其他编辑器,如vi、nano、gedit等来创建文件,例如:vi filename、nano filename、gedit filename。这些编辑器可以提供更多的编辑功能。
检查文件的创建结果,可以使用ls命令查看当前目录下的文件列表。
非常好,你描述了创建文件的基本步骤。接下来的问题:
- 一旦文件被创建,在Linux系统中,如何查看文件的内容?
使用less命令:命令less是一种类似于文本编辑器的工具,可以按页显示文件的内容,并且支持搜索和浏览大文件。可以使用less命令来查看文件的内容,例如:less filename。
使用more命令:命令more也是类似于less的工具,可以按页显示文件内容,但是不支持搜索和浏览大文件,可以使用more命令来查看文件的内容,例如:more filename。
使用vi或nano编辑器:vi和nano是常见的Linux文本编辑器,可以打开一个文件并提供编辑和查看功能,可以用vi或nano打开文件来查看其内容,例如:vi filename或nano filename。
非常好,你解释了如何查看文件的内容的不同方法。下一个问题:
- 在Linux中,如何复制文件?请描述一下复制文件的基本步骤。
使用cp命令来复制文件,语法如下:cp source_file destination_file 其中,source_file是要复制的源文件的路径,destination_file是目标文件的路径和名称。 例如,要将一个名为"file1.txt"的文件复制到当前目录下,并重命名为"file2.txt",可以使用命令:cp file1.txt file2.txt。 可以使用绝对路径或者相对路径指定文件的位置。
检查复制结果,可以使用ls命令来查看目标目录下是否存在新复制的文件。
非常好,你描述了复制文件的基本步骤。接下来的问题:
- 当需要在Linux中移动文件或重命名文件时,应该采取什么步骤?请简要描述一下。
使用mv命令来移动文件或重命名文件,语法如下:
若需要移动文件,可以使用命令:mv source_file destination_directory 其中,source_file是要移动的源文件的路径和名称,destination_directory是目标目录的路径。 例如,要将一个名为"file1.txt"的文件移动到目录"folder"中,可以使用命令:mv file1.txt folder/。 可以使用绝对路径或者相对路径指定文件的位置和目标目录的位置。
若需要重命名文件,可以使用命令:mv old_file_name new_file_name 其中,old_file_name是源文件的名称,new_file_name是重命名后的新文件名称。 例如,要将文件"file1.txt"重命名为"file2.txt",可以使用命令:mv file1.txt file2.txt。
检查移动或重命名结果,可以使用ls命令来查看目标目录下是否存在移动后的文件或重命名后的文件。
非常好,你描述了移动文件和重命名文件的基本步骤。下一个问题:
- 在Linux中,如何删除文件?请简要描述一下删除文件的基本步骤。
使用rm命令来删除文件,语法如下:rm file_name 其中,file_name是要删除的文件的路径和名称。可以使用绝对路径或者相对路径指定文件的位置和名称。 例如,要删除一个名为"file1.txt"的文件,可以使用命令:rm file1.txt。
确认删除操作,可以使用命令带上选项-r或者-f来进行确认,语法如下:
若要删除目录及其内部所有文件和子目录,需要加上选项-r,例如:rm -r folder。
若要强制删除文件或目录,并避免出现询问确认操作,需要加上选项-f,例如:rm -f file1.txt。
检查删除结果,可以使用ls命令来查看文件或目录是否已被成功删除。
非常好,你解释了删除文件的基本步骤以及如何使用选项-r和-f来进行确认或强制删除操作。下一个问题:
- 什么是Linux系统调用,以及它们在文件操作中的作用是什么?
让我们回顾一下你的学习:
你已经了解了在Linux系统中文件是用来存储数据的数据块,用于用户和系统之间交换信息。
你知道每个文件都有一个唯一的inode号码用于标识。
你已经学会了如何创建、查看、复制、移动、重命名和删除文件,以及如何使用不同的命令来执行这些操作。
你了解了Linux系统调用,尤其是在文件操作方面的作用。
总的来说,你已经对Linux系统中的文件操作和系统调用有了基本的理解。是否还有其他关于这个主题的问题,或者是否需要进一步探讨某个方面的知识点?
你的回答总结如下:
你已经学习了关于在Linux系统中进行文件操作以及使用系统调用进行文件操作的知识点。你理解了文件的基本定义和作用,知道了文件的唯一标识符是inode号码。此外,你也学会了如何创建、查看、复制、移动、重命名和删除文件,以及如何使用不同的命令来执行这些操作。你还提到了系统调用在文件操作中的作用。
总的来说,你已经掌握了Linux系统中文件操作的基本概念和常见操作。如果你有进一步的问题或需要深入了解特定方面的知识,可以随时提出。继续学习和实践将有助于加强你在这个领域的技能。