文件与目录类型
常见的文件类型
- 普通文件:最为常见的文件类型,包括纯文本文件(ASCII),二进制文件(binary),数据文件(data)等
- 目录:即文件夹,用于包含更多目录和文件
- 块设备文件:将硬盘、光盘等存储设备以文件形式供用户操作
- 字符设备文件:将串行端口的接口设备,如键盘、鼠标等以文件形式供用户操作
- 套接字文件:又称为数据接口文件,用于网络数据连接
- 管道文件:用于进程间的通讯
- 链接文件:分为硬链接和软链接,用于通过快捷方式或引用快速访问另一个文件或目录
Linux目录
指令集
- /bin Binaries的缩写,存放普通用户可使用的系统命令,如:ls
- /sbin Super user Binary的缩写,存放只有系统管理员才能使用的系统命令,如:shutdown、reboot
- /usr/bin 存放安装软件后,普通用户可以使用的软件命令,如:c++、make、wget等
- /usr/sbin 存放系统管理员用户安装使用的高级管理程序和系统服务程序,如:httpd、netconfig、tcpd等
系统文件
- /etc Etcetera(其他)的缩写,这个目录用来存放所有系统管理所需要的配置文件和子目录
- /var 存放一些经常被修改、扩充的文件,如各种日志文件
- /boot 存放引导启动Linux时使用的核心文件,如镜像文件等
- /sys Linux2.6内核新增的文件系统sysfs,sysfs文件系统集成了3种文件系统的信息:针对进程信息的proc文件系统、针对设备的devfs文件系统以及针对伪终端的devpts文件系统
- /lib 存放系统所需要的动态链接库(如C++库),相当于windows的dll文件
- /dev Device的缩写, 将Linux主机的硬件以文件形式存储并提供访问,相当于Windows的设备管理器
- /usr/src 内核源代码、说明文档等默认放置目录
- /opt 默认为空,常用于安装额外软件,通常为第三方软件
- /proc Processes(进程)的缩写,虚拟的目录,用于管理内存空间,是系统内存的映射,我们可以直接访问这个目录来获取系统信息。这个目录的内容不在硬盘上而是在内存里
- /selinux 全称为security-enhanced linux,该目录是 Redhat/CentOS 所特有的目录,是Redhat/CentOS的安全子系统
- /srv service缩写,存放一些服务启动后需要提取的数据
用户
- /root 系统管理员的账号主目录
- /home 存放普通用户的相关文件,Linux会在home目录下为每一个用户生成一个以用户账号命名的目录
- /usr Unix Software Resource(共享资源)的缩写,放置用户的应用程序和文件,类似于windows下的program files目录
- /usr/local 软件安装目录,一般通过源码编译安装方式安装的软件都会存放于该目录下
- /usr/include 放置如c/c++等程序语言的头文件(header)与包含档(include)
- /usr/lib 放置各应用软件的函式库、目标文件等,如果使用的是X86_64的Linux系统,则可能会生成/usr/lib64文件夹
外部文件
- /media 挂载U盘、光驱等设备的目录,类似于windows的其他设备
- /mnt 让用户挂载其他的文件系统,如将Windows上的某个目录挂载在/mnt下,可用于共享文件等
临时文件
- /lost+found 一般情况下为空目录,用于存放系统非法关机或者发生意外错误后,fsck(磁盘修复)过程修复的部分文件
- /tmp 用于存放临时文件
- /run 一个临时文件系统,存放存储系统启动以来的信息。当系统重启时,这个目录下的文件应该被删掉或清除。
链接文件
链接文件是Linux文件系统的一个优势。当需要在系统上维护同一文件的两份或多份副本时,除了保存多份单独的物理文件副本之外(复制文件),还可以采用保存一份物理文件副本和多个虚拟副本的方法(链接文件),这种虚拟的副本就称为链接。Linux文件系统有两种链接文件:
- 软链接:也称为符号链接或软连接,相当于文件的快捷方式。为了方便跨分区指向,软链接文件拥有独立的inode号,是一个单独的文件,但文件本身只包含指向原文件或原目录的路径,而不包含实际的文件内容,所有对软链接的读取、执行等操作都是基于原文件。当原文件删除,软链接文件也将失效,因此可视为软链接只是一个指向原文件的指针
- 硬链接:是一个被创建出来的独立虚拟文件,其中包含了原文件的信息及位置。但是硬链接文件和原文件本质上是同一个文件,inode号相同,删除原文件并不会造成硬链接文件的失效,也不会造成文件内容丢失,因为此时仍然还存在一个可以访问文件存储区域的通道(硬链接文件)
二者区别:
- 生成的软链接权限都为 rwxrwxrwx,实际权限取决于原文件权限
- 硬链接文件 inode 节点与原文件相同,软链接不同
- 硬链接指向不能跨分区,软链接可以
- 不能给目录生成硬链接,软链接可以
inode(索引节点):是Linux文件系统中的一个概念,用于存储文件的元数据信息。每个文件在文件系统中都有一个对应的inode,它包含了文件的具体信息,如文件类型、文件大小、权限信息、所有者、访问时间、修改时间、链接数等。在Linux文件系统中,文件内容被存储于数据块中,而inode存储了文件的元数据信息和指向文件数据块的指针。当用户创建一个文件时,系统会分配一个inode给这个文件,并记录文件的元数据信息。每个inode都有一个唯一的索引号,即文件或目录的inode编号,它是一个用于标识的唯一数字,这个数字由内核分配给文件系统中的每一个对象。要查看文件或目录的inode编号,可以使用ls -i命令,文件系统可以通过该索引号来找到对应的inode和文件。硬链接文件和源文件共享相同的inode,即它们指向同一个文件的元数据信息,因此在inode中会有一个链接计数器,记录有多少个目录项指向这个inode,这样系统可以正确处理不同目录下的链接关系。
对于硬链接,硬链接和原始文件本质上是同一个文件,它们共享相同的inode。当用户创建一个硬链接时,实际上是在创建一个指向相同inode的新目录项,使得该文件在文件系统中有多个名称。因此,删除源文件时,不会影响到已经创建的硬链接文件,因为这其实只是减少了一个指向该inode的目录项,而硬链接文件依然指向这个inode,因此硬链接文件会继续存在。只有当所有指向该inode的目录项都被删除后,文件系统才会释放该inode及其对应的数据块,这时硬链接文件也会被删除。
对于软链接(Symbolic Link),它是一个特殊的文件,用于指向另一个文件的路径。和硬链接不同,软链接创建了一个新的inode来存储软链接文件的元数据信息。软链接和原始文件是两个独立的文件,它们可能位于不同的文件系统中。因此,软链接需要有自己的inode来存储自己的元数据信息,以确保其独立性。软链接的实现方式是通过存储目标文件的路径信息,而不是直接指向目标文件的inode。这样做的好处是可以在文件系统中创建指向不同文件系统的软链接,而硬链接只能在同一文件系统中有效。软链接文件的存储内容是指向另一个文件的路径,而不是具体的文件内容,因此即便源文件很大,软链接文件依旧可能很小。而所有通过vim等软件修改软链接内容,实际是在修改源文件的内容,所有对软链接的读取、执行等操作都会基于源文件,软链接只是一个指向源文件的指针,当源文件删除,软链接文件也将失效。
link创建硬链接
该命令只能创建硬链接
link 源文件 硬链接名
ln创建链接文件
ln 源文件 目标文件
- 默认会创建硬链接,如果指定路径下已有与目标文件同名的文件,则返回错误,如果源文件不存在,则返回错误
- -s 创建软链接,对于软链接,如果源文件不存在,依旧会创建软链接文件(悬空链接),指向一个不存在的文件。因此软链接支持先创建链接,后补源文件
- -b 创建链接时如果已有同名文件,则备份该文件,参考通用的备份方案
- -S “字符串”:指定备份文件的后缀名
- -f 强制创建链接文件,有同名文件直接覆盖
- -i 有同名文件时,询问用户是否覆盖
- -v 打印每个创建链接的文件名
- -L 当源文件是软链接文件时,创建的新链接指向该软链接所指向的文件,该选项会创建硬链接
- -P 当源文件是软链接文件时,创建的新链接指向该软链接本身(默认)
- -r 创建基于相对路径(默认为绝对路径)的软链接,这在目录结构整体发生移动时,链接仍然有效,该选项需要搭配-s选项
readlink查看软链接的源文件
readlink [选项] 文件名 查看软链接所指向的实际文件路径
- 默认情况下,命令会直接输出符号链接文件本身所存储的源文件的文件路径,这个路径可能是绝对路径,也可能是相对路径,这取决于软链接创建时的选项
- -f 输出符号链接所指向的文件或目录的绝对路径。如果符号链接指向另一个符号链接,则会继续解析直到找到最终的源文件或目录。即使路径中的某些目录或文件不存在(这些文件未来可能会由其他程序创建),也返回该路径而不报错
- -e 输出符号链接所指向的文件或目录的绝对路径,这些路径必须是存在的,否则返回空并报错,该选项适用于要保证整个路径都真实存在的情况
- -m 类似于-m选项,如果路径中的某个目录或文件不存在,命令会直接将其视为目录,然后返回完整的绝对路径
- -n 输出的路径末尾不添加换行符,方便与其他命令结合使用
- -s或-q 静默模式,禁止显示大多数错误消息(默认)
- -v 输出错误消息
管道文件
管道(pipe)是一种在不同进程之间进行数据传输的通信机制,它允许一个进程写入数据,另一个进程按顺序读取数据,从而实现进程间的通信。管道中的数据是以”流”的形式进行传输,管道的使用能够有效地实现数据流的连接,使得用户能够将多个命令串联起来,形成一个复杂的命令执行流程。管道通信有以下特点:
- 先进先出:先写入的数据会被先读取,遵循”First In, First Out”原则。
- 双进程通信:管道允许两个进程之间进行数据传输,一个进程写入数据,另一个(或多个)进程读取数据,读与写可以同步进行
- 流式数据:管道中的数据被存储于内存的内核缓冲区,数据是一次性传输的,被读取一次后就会消失,是一种流式数据
- 阻塞行为:为了保证进程间数据传输的有序性和同步性,管道通过阻塞读写操作来协调数据的传输。进程在写入数据时,如果缓冲区已满,进程的写入操作会被阻塞,直到另一个进程从管道中读取数据,腾出缓冲区空间,写操作才会继续。类似的,读操作也会被阻塞,当进程从管道中读取数据时,如果缓冲区为空,进程的读操作会被阻塞,直到有数据写入。如果写入进程已经终止(写端关闭),且管道内的数据已被读完,则读操作会立即返回EOF(End Of File),表示管道结束。
匿名管道
匿名管道的创建完全基于内存,不会在文件系统中生成任何文件或路径,在创建时不分配名称,它只能在有关系的进程(如父子进程)间使用,而不能在任意进程之间通信。匿名管道的生命周期与创建它的进程相关,当创建这个管道的进程结束时,管道也会被关闭,匿名管道只能通过文件描述符来访问。
在C语言中,可以使用系统调用pipe()来创建匿名管道,在命令行中使用管道符|创建的也是匿名管道,此时shell会创建子shell,管道符两侧的命令都将在独立的子shell中并行执行,虽然子shell中运行的命令是独立的进程,但他们是在同一个父shell上下文中执行的,因此它们可以通过管道完成通信。
mkfifo创建命名管道(管道文件)
命名管道(named pipes)通常被直接称为FIFO(First In, First Out的缩写),它会被显式地创建在文件系统中,称为管道文件。管道文件是一种特殊的文件,它虽然在文件系统中拥有文件路径,但数据的存储位置依旧位于内存缓冲区,管道文件本身并不存储数据,管道文件可以通过以下命令创建:
mkfifo [选项] 文件名
- -m 权限:为创建的管道文件指定权限,接收的参数支持权限的八进制值表示形式(如755),也支持符号模式(如:移除组的写权限g-w,默认为a=rw,即允许所有人读写,可以基于此权限进行删减)
mknod创建设备文件或管道文件
该命令用于让用户手动创建特殊文件,比如字符设备、块设备以及命名管道
mknod [选项] 文件名 文件类型 [参数]
- -m 权限:为创建的管道文件指定权限,接收的参数支持权限的八进制值表示形式(如755),也支持符号模式(如:移除组的写权限g-w,默认为a=rw,即允许所有人读写,可以基于此权限进行删减)
- 文件类型有:p(命名管道文件)、c(字符设备文件,如:键盘设备)、b(块设备文件,如:U盘设备)
临时文件
Linux系统提供了一个特殊的目录/tmp,用于存放临时文件。大多数Linux发行版会在系统在启动时自动删除tmp目录下的所有文件,或会周期性清理长期不访问的临时文件,且系统上的任何用户账户都有权限读写tmp目录中的文件,这为用户创建临时文件提供了便利,且不用担心清理工作
创建临时文件
- 使用该命令时,通常会指定一个文件名模板,文件名模板末尾必须包含至少3个(通常6个)X(必须为大写X),mktemp命令在创建该文件时会使用随机字符替换X,以保证临时文件的唯一性。默认情况下,如果文件名模板前未指定路径,命令会在当前目录中创建临时文件或目录,如果指定了路径,则前往指定路径下创建
- 如果不指定文件名模板,命令将使用默认模板’tmp.XXXXXXXXXX’(10个随机字符),且默认会在/tmp目录下创建临时文件,而不管当前路径如何
- -p 路径:在指定路径下创建临时文件或目录
- -t 在 $TMPDIR 环境变量指定的目录中创建文件或目录。如果未设置 $TMPDIR,则在/tmp路径下生成临时文件或目录,返回完整路径名
- -d 创建临时目录
- -q 在无法创建临时文件或目录时不产生错误信息
- --suffix=”字符串”:为生成的文件添加指定后缀
临时文件的清理
Linux中的临时文件主要位于两个路径下:
- /tmp:用于存放短期临时文件
- /var/tmp:用于存放长期的临时文件,默认情况下,文件可能保留30天或更久
大多数现代Linux发行版使用systemd-tmpfiles来管理临时文件,部分系统可能使用cron定时任务来进行清理。systemd-tmpfiles的配置文件通常位于/usr/lib/tmpfiles.d/tmp.conf或/etc/tmpfiles.d/路径下。如:配置文件 /usr/lib/tmpfiles.d/tmp.conf 中的内容可能如下:
该配置表示:
- /tmp 目录中超过 10 天未被访问的文件会被清理
- /var/tmp 目录中超过 30 天未被访问的文件会被清理
脚本中临时文件的使用
在脚本中创建临时文件时,使用touch、echo等命令创建临时文件有可能带来文件名冲突等问题,且所创建的文件容易受到符号链接攻击,使用mktemp命令创建临时文件是一种更安全的推荐方法
设备文件
设备挂载参考下文”文件系统挂载与卸载”,这里只介绍Linux内置有特殊用途的设备文件
数据
- /dev/null 数据”黑洞”,所有写入该文件的数据都会被丢弃;读取该文件会立即返回EOF(文件结束),导致读取为空
- /dev/zero 提供无限的空字符(\0),可用于初始化文件或内存
- /dev/full 始终写满,写入返回 ENOSPC 错误,可用于测试磁盘写满场景
随机数生成
以下文件生成的是二进制数据,且包含不可打印字符,通过cat、head命令读取时会显示为乱码(因为终端尝试将其解释为文本字符),因此在使用时通常需转码使用
- /dev/random 生成来自系统熵池的随机数,会被阻塞,适合对安全性要求极高的场景
- /dev/urandom 一开始也会根据系统熵池生成随机数,当系统熵池不足时会开始使用算法生成的伪随机数,因此不会阻塞
二者的区别:/dev/random严格依赖系统熵池,系统熵池的数据来自硬件噪声、键盘/鼠标输入等,通过其生成的加密密钥安全性极高,但在虚拟机或嵌入式设备中,熵源可能较少,当系统熵池耗尽时会因熵不足而阻塞。/dev/urandom生成随机数通常更快,它一开始也会根据系统熵池生成随机数,当系统熵池不足时会开始降级为使用算法生成随机数,因此它不会因熵不足而阻塞。在现代Linux内核中,/dev/urandom已经被优化得安全性十足,能满足大部分使用场景,推荐优先使用。
帮助文件 (manual)
1. 查看完整帮助man
man [命令或配置文件]
- 查看配置文件的帮助时,直接写文件名,不能加上文件路径,使用文件路径会直接显示文件内容而不是该配置文件的使用说明
man命令返回的手册页一般包括以下信息,但不一定包括所有节,信息通过分页程序显示,分页程序可以通过PageUp和PageDown或空格上下翻页,也可以通过上下方向键逐行滚动,或者使用回车键逐行向下查看,查看完毕后可以通过q键退出
| 节 | 内容 |
|---|---|
| Name | 显示命令名和一段简短的描述 |
| Synopsis | 命令的语法 |
| Confi guration | 命令配置信息 |
| Description | 命令的一般性描述 |
| Options | 命令选项描述 |
| Exit Status | 命令的退出状态指示 |
| Return Value | 命令的返回值 |
| Errors | 命令的错误消息 |
| Environment | 描述所使用的环境变量 |
| Files | 命令用到的文件 |
| Versions | 命令的版本信息 |
| Conforming To | 命名所遵从的标准 |
| Notes | 其他有帮助的资料 |
| Bugs | 提供提交bug的途径 |
| Example | 展示命令的用法 |
| Authors | 命令开发人员的信息 |
| Copyright | 命令源代码的版权状况 |
| See Also | 与该命令类型的其他命令 |
对于命令,man 有多个不同类型的帮助文档,并使用数字区分这些区域(通常为1-9),可以使用 whereis 命令查看该命令在man目录下有几种类型,如果有多个类型,可以使用man [值] [命令]来查看对应帮助。如:1为通常为解释该命令如何使用,5通常为命令对应的说明文档如何阅读。即:使用man 命令和man 1 命令为查看命令的帮助,man 5 命令为查看命令说明文档的帮助(具体区域号视命令而定),以下为不同类型内容所包含的内容
| 区域号 | 所含内容 |
|---|---|
| 1 | 用户命令和可执行程序的帮助手册 |
| 2 | 系统调用和内核函数的帮助手册 |
| 3 | C库函数的帮助手册 |
| 4 | 设备文件和特殊文件的帮助手册 |
| 5 | 配置文件的格式和约定的帮助手册 |
| 6 | 游戏的帮助手册 |
| 7 | 杂项(如宏包、约定等)的帮助手册 |
| 8 | 系统管理员手册和管理命令的帮助手册 |
| 9 | 内核例程的帮助手册 |
2. 查看简短帮助
- what 命令 只显示命令帮助文档中NAME部分的内容
- apropos 配置文件 简短查看配置文件作用
3. 查看命令的选项
只查看命令的可选参数选项,不需要查看命令完整帮助信息
命令 --help
4. 查看shell内置命令
有些命令是bash(shell)内置命令而不是Linux的命令,使用上述命令查看不到帮助,可以使用
help 命令
文件系统
介绍
简介
与Windows不同,Linux在路径中不使用驱动器盘符。Windows将物理磁盘驱动器分为盘符(如C盘、D盘),每个盘都会有自己的目录结构,并通过诸如C:\Users\ Administrator \Documents等方式访问文件。
Linux则采用了一种不同的方式,Linux内核采用虚拟文件系统(Virtual File System,VFS),内核将所有安装在PC上的存储设备的文件纳入单个目录结构中,这个目录被称为虚拟目录(virtual directory)。Linux虚拟目录结构只包含一个称为根(root)目录的基础目录。根目录下的目录和文件会按照访问它们的目录路径一一列出,并使用正斜线 /(windows使用反斜线\)来做路径划分。
Linux文件系统结构是从Unix文件结构演进过来的,并遵守文件系统层级标准(filesystem hierarchy standard,FHS),它确定了Linux系统中每个目录的用途和应该包含的内容,并保证不同Linux发行版之间的文件布局是一致的
Linux可用的文件系统
Linux内核支持通过不同类型的文件系统从硬盘中读写数据。除了自有的诸多文件系统外,Linux还支持从其他操作系统(比如Windows)采用的文件系统中读写数据,但内核必须在编译时加入对所有可能用到的文件系统的支持,以下为Linux系统用来读写数据的标准文件系统
| 文件系统 | 说明 |
|---|---|
| ext | Linux扩展文件系统,最早的Linux文件系统 |
| ext2 | 第二代扩展文件系统,在ext的基础上提供了更多的功能 |
| ext3 | 第三代扩展文件系统,支持日志功能 |
| ext4 | 第四代扩展文件系统(Fourth Extended File System),支持高级日志功能,目前Linux主流的文件系统 |
| tmpfs | 一种临时文件系统,常见于类Unix操作系统,使用内存(RAM)作为文件存储区,适合需要高速读写和不需要持久存储的数据情况 |
| devtmpfs | 临时设备文件系统,常见于类Unix操作系统,该文件系统会在内存中创建一个区域,用于管理/dev目录下的设备文件,方便动态管理硬盘、网络接口、终端等物理设备,可以简化设备管理,提高系统启动速度 |
| FAT16 | 用于微软的ms-dos操作系统,Windows最初是作为MS-DOS的一个图形用户界面(GUI)扩展而开发的,但随着技术的进步,Windows操作系统逐渐发展成一个独立的操作系统,从Windows NT 4.0 开始,Windows不再依赖于MS-DOS |
| VFAT | FAT32的扩展版本,在FAT32的基础上加入了长文件名支持功能,名称上实际仍称为FAT32。FAT32是windows98等旧版本windows的主要文件系统,现在广泛用于相机SD卡、U盘等,最大支持的单个文件大小为4GB,最大分区大小为2TB |
| NTFS | 全称为New Technology File System,目前windows主要使用的高级文件系统,广泛用于windows7、10,支持数据加密,文件权限控制,日志记录与恢复等功能,最大支持的单个文件大小为16TB(取决于分区大小),分区大小可达到256TB或更高 |
| hpfs | OS/2高性能文件系统 |
| jfs | IBM日志文件系统 |
| iso9660 | 标准CD-ROM文件系统,主要用于CD |
| minix | MINIX文件系统 |
| ncp | Netware文件系统 |
| nfs | 网络文件系统 |
| proc | 访问系统信息 |
| ReiserFS | 高级Linux文件系统,能提供更好的性能和硬盘恢复功能 |
| smb | 支持网络访问的Samba SMB文件系统 |
| sysv | 较早期的Unix文件系统 |
| ufs | BSD文件系统 |
| umsdos | 建立在msdos上的类Unix文件系统 |
| XFS | 高性能64位日志文件系统 |
文件系统的架构
Linux 文件系统采用了层次化的设计,通常分为以下几层:
- 虚拟文件系统(Virtual File System,VFS):虚拟文件系统是操作系统内核的一部分,它为不同类型的文件系统提供了统一的接口,屏蔽了底层文件系统的差异性,使Linux能够同时挂载各种文件系统
- 实际文件系统(File System Implementation Layer):该层实现了具体的文件系统,如 ext4、XFS、Btrfs、FAT32 等,每种文件系统都有其独特的数据结构和实现方式,但它们都通过 VFS 提供一致的接口,向上层应用程序隐藏具体细节
- 存储设备层(Storage Device Layer):该层包括实际的存储设备(如 HDD、SSD、USB 闪存盘等)及其驱动程序,管理设备的物理 I/O 操作。文件系统将逻辑数据映射到这些物理设备上,通过块设备接口(如 /dev/sda)来访问硬盘的块(block)数据
Linux文件系统都有以下几个重要组成部分:
- 超级块(Superblock):超级块包含了文件系统的元数据,比如文件系统的大小、块大小、inode 数量、已用和可用的 inode 及数据块等信息。超级块是文件系统的控制信息,通常被加载到内存中,用于文件系统的管理和访问。
- 索引节点(Inode):Inode是每个文件或目录的描述符,每个文件都有唯一的inode标识符,在文件系统中,文件通过inode号来唯一标识,inode包含文件的元数据,如:
- 文件类型(普通文件、目录、符号链接等)
- 文件大小
- 所有者(用户 ID 和组 ID)
- 访问权限(读、写、执行)
- 时间戳(创建时间、修改时间、访问时间)
- 指向数据块的指针
- 数据块(Data Block):数据块是文件的实际内容存储区域。每个数据块大小通常为4KB,文件系统通过 inode 中的指针(direct 和 indirect pointers)来定位文件的数据块
- 目录(Directory):目录是一种特殊类型的文件,它包含了其他文件或子目录的列表。每个目录项包含文件名和对应的inode号。当用户查找一个文件时,系统会先根据目录文件中的inode号找到对应的 inode,再通过inode中的指针找到数据块。
- 日志(Journaling):大多数现代Linux文件系统(如 ext3、ext4、XFS)都使用日志机制来提高数据可靠性。日志记录文件系统中所有的元数据变化操作,确保在系统崩溃或突然断电时,可以通过重播日志恢复文件系统的完整性。
文件系统的工作流程
- 文件查找: 当用户要访问某个文件时(如 /home/user/file.txt),系统会按照以下步骤进行查找:
- 从根目录 / 开始,找到 home 目录的 inode。
- 根据 home 目录 inode 中的数据块指针,找到 user 目录的 inode。
- 最终找到 file.txt 的 inode,然后通过该 inode 访问文件的数据块。
- 文件读操作: 当文件被读取时(例如使用 cat 命令),系统会:
- 根据目录结构找到文件的 inode。
- 读取 inode 中指向的数据块指针。
- 从数据块中读取文件内容,并将其返回给用户。
- 文件写操作: 当文件被修改或创建时(例如使用 echo 命令),系统会:
- 为新文件分配一个 inode,设置文件的元数据(所有者、权限等)。
- 分配新的数据块,并写入文件内容。
- 更新 inode 中的指针,使其指向新的数据块。
- 更新文件系统的超级块信息(例如可用 inode 和数据块数量)。
- 元数据更新和日志记录:为了防止数据丢失,文件系统通常会先将元数据更新写入到日志区域中,然后再进行实际操作。这种机制被称为 “Write Ahead Logging”。在日志写入成功后,再进行实际的文件写操作,确保在系统故障时能够快速恢复文件系统。
文件的时间戳
在 Linux 系统中,文件的时间戳主要包括以下三种类型:
- 访问时间(Access Time,atime):文件上次被读取的时间,使用cat、less、head等命令读取文件内容,或通过bash script.sh执行脚本文件,都会更新atime。但认情况下,为了提升性能,大多数 Linux 文件系统(如 ext4)会使用relatime挂载选项,这意味着只有在 atime 比 mtime 或 ctime 旧时,atime 才会更新。因此,某些文件访问操作不会立即反映到atime中
- 修改时间(Modification Time,mtime):文件内容上次被修改的时间,通过echo、vim、nano和重定向符修改文件内容都会更新mtime
- 更改时间(Change Time,ctime):文件的元数据(如权限、所有者、文件名等文件属性)上次被更改的时间,通过chmod、chown、chattr修改文件属性,使用mv命令移动、重命名文件都会更新ctime,使用vim,nano修改文件时,编辑器可能会创建临时文件,并使用新文件覆盖原文件,也会更新ctime
- 创建时间(Birth Time或Creation Time,btime):表示文件首次被创建时的时间,这是一个教新引入的时间戳,因此,一些传统的文件系统不支持该时间戳,一些新的文件系统(如 ext4)也默认不保存创建时间,需要特定文件系统(如 btrfs)或内核版本支持才可以查看
命令
df查看文件系统空间使用情况
GNU提示:df命令仅安装在拥有挂载表的系统上,因此跨平台可移植脚本不应该依赖该命令
df [参数] [挂载点]
- 默认情况下,命令会输出所有当前已挂载文件系统的信息
- -a 显示所有文件系统信息,包括特殊文件系统,这些文件系统通常无法直接访问,因此默认不显示
- -h 将磁盘大小单位换算为KB、MB等单位,以1024作为基数进行换算
- -H 等价于--si选项,换算单位为K、M等单位,以1000作为基数进行换算
- -m 以MB为单位显示容量
- -k 以KB为单位显示容量,默认值
- -T 显示文件系统类型
- -i 列出 inode 使用情况信息,而不是块使用情况
- -l 只列出本地文件系统,默认情况下还会列出远程文件系统
- --output=项目:只列出指定项目,指定多个项目可以用逗号分隔(如--output=source,target),接收的参数有:source(挂载来源,通常是设备)、target(挂载点)、fstype(文件系统类型)、itotal(inode总数)、iused(已用inode数量)、iavail(可用inode数量)、ipcent(iused除以 itotal的百分比)、size(块总数)、used(已使用的块数)、avail(可用的块数)、pcent(used除以size)、file(文件名,需要在命令行指定)
- -t 文件系统:只显示某个文件系统的信息,可以指定多个-t选项
du显示目录或文件大小
通过df命令发现磁盘空间快满时,可以通过du命令查看是哪些文件占用了较大的存储空间
du [参数] [目录或文件名]…
- 默认情况下,命令会显示当前目录中每个子目录的磁盘块占用数量,并在最后一行输出当前目录总占用数量,该行为会递归进行,即会打印子目录的后代子目录信息,它会以磁盘块为单位来表明每个文件或目录占用了多大存储空间
- -a 打印每个子目录以及子文件的大小
- -h 将文件大小单位换算为K、M等单位
- -k 以K为单位打印占用空间
- -m 以M为单位打印占用空间
- -c 在处理完所有文件后,打印总计
- -s 只统计总大小,不列出子目录和文件
- -d 值depth:只从当前目录向下统计depth层(文件的层次结构),当前目录为第0层
- --inodes 列出inode的使用情况,而不是块使用情况
- -L 显示链接指向的文件或目录的所占用空间大小,而不是链接文件本身
- -t 值:如果给定的值为正数,则只打印大于等于该值的目录或文件信息,如果值为负数,则只打印小于等于该值的目录或文件,这里的值可以使用kB、k、KiB等单位
- --time:打印文件或目录的上一次内容修改时间mtime
- --time=ctime:打印文件或目录上一次属性修改时间ctime
- --time=atime:打印文件或目录上一次访问时间atime
- --exclude=正则pattern:递归统计时,跳过与pattern匹配的子目录或文件,如du --exclude=’*.o’ 排除以.o结尾的文件
- -X 文件名:从该文件中获取需要排除的文件或目录,每一行表示一个或一类文件,可以使用正则表达式,如果文件名为-,表示从标准输入获取
文件系统修复
fsck [参数] 分区设备名
- -a 不显示用户提示,自动修复文件系统
- -y 功能同-a,部分文件系统仅支持-y
文件系统的挂载与卸载
Linux文件系统将所有的磁盘都并入一个虚拟目录下。在使用新的存储媒体之前(如载入U盘等),需要把它映射到虚拟目录下的某个位置,方便通过虚拟目录直接操作文件和设备,这个步骤称为挂载(mounting)
/etc/fstab文件
/etc/fstab(File System Table)文件用来存储文件系统的静态信息,包括可以挂载的文件系统、挂载点路径、文件系统类型以及它们的挂载选项(如读写权限、是否需要自动挂载等),fsck、mount、umount、swapon、swapoff等命令都会读取该文件作为配置来源
/etc/fstab 文件每行定义一个挂载项,字段直接使用空格或制表符分隔,可以使用#注释行,每行挂载项的语法格式为:
挂载源 挂载点路径 文件系统类型 挂载选项 dump备份 fsck检查顺序
- 挂载源是指要挂载的设备、远程文件系统、要启用的虚拟内存交换空间等,该参数可以上述挂载源的文件名,或者远程地址(url:路径形式),也可以UUID(如UUID=3a9f…形式),标签名(如LABEL=DATA),这些标签或uuid可以在mkswap(创建虚拟内存交换文件)、fatlabel时指定
- 挂载点为在文件系统中的挂载路径和文件名,如果文件名包含空格,可以使用\040(空格)和\011(制表符)转义。对于交换空间swap,挂载点应该指定为none
- 文件系统类型参考”Linux可用的文件系统”,swap表示用于交换空间的文件系统
- 挂载选项用来控制挂载后文件系统的行为,可以是以下值:
- defaults 使用内核和文件系统的默认值
- 控制读写权限,如:ro(只读)、rw(可读写,默认)
- noauto:表示mount -a(挂载所有配置的文件系统)或swapon -a(启用所有配置的虚拟内存交换空间)时排除该挂载源
- noatime:不更新文件访问时间atime以提升性能
- user:允许用户挂载
- owner:允许所有者挂载
- sw:表示这是一个交换文件swap
- nofail:如果此设备不存在,不要输出错误
- dump备份用来指定是否需要被dump工具备份,0表示不备份,1表示备份
- fsck检查顺序用来指定启动时文件系统检查顺序,0表示不检查,1表示当前为根分区优先检查(因此对于根文件系统应该指定为1),2表示这是其他分区按顺序检查
查询挂载信息
mount显示已经挂载的设备
- -l显示卷标
自动挂载
系统启动时,会根据文件/etc/fstab中指定的信息自动挂载部分文件系统,也可以根据该文件手动执行该过程
mount -a根据配置文件 /etc/fstab 自动挂载
- -a 挂载所有未挂载的文件系统
- -aF 会同时挂载所有文件系统
- -aO 可以在/etc/fstab中为某个文件系统指定特定的挂载选项,并应用这些选项
手动挂载
mount [-t 文件系统] [-L 卷标名] [-o 特殊选项] 设备文件名 挂载点
- -t 文件系统:挂载指定文件系统,如 ext4、iso9660
- -L 卷标名:自定义卷标的名字
- -f 模拟挂载设备,但并不真的挂载
- -s 忽略该文件系统不支持的挂载选项
- -r 将设备挂载为只读的
- -w 将设备挂载为可读写的(默认参数)
- -v 详细模式,详细说明挂在设备的每一步
- -n 挂载设备,但不注册到/etc/mtab已挂载设备文件中
- -s 忽略该文件系统不支持的挂载选项
- -o 特殊选项:指定挂载的额外选项,以下是几个常用的选项:
| 参数 | 说明 |
|---|---|
| ro | 以只读方式挂载 |
| rw | 以可读写方式挂载 |
| user/nouser | 是否允许普通用户挂载文件系统,默认为不允许 |
| check=none | 挂载文件系统时不进行完整性校验 |
| loop | 挂载一个文件 |
| atime/noatime | 访问分区文件时是否更新文件访问时间 |
| exec/noexec | 是否允许文件系统中的可执行程序可以运行,默认为exec允许 |
| remount | 重挂载已经挂载的文件系统,一般用于修改特殊权限后重挂载 |
硬件设备文件名
通过文件名可以判断该设备文件对应的设备,以下说常用的设备文件名
| 硬件 | 设备文件名 |
|---|---|
| IDE硬盘 | /dev/hd[a-d] |
| SCSI/SATA/USB硬盘 | /dev/sd[a-p] |
| 光驱 | /dev/cdrom 或 /dev/sr0 |
| 软盘 | /dev/fd[0-1] |
| 打印机(25针) | /dev/lp[0-2] |
| 打印机(USB) | /dev/usb/lp[0-15] |
| 鼠标 | /dev/mouse |
挂载光盘
为方便文件查找,一般将光盘挂载于根目录下的 /media ,U盘挂载于/mnt目录下,iso9660为光盘默认文件系统,因此-t iso9660 可以省略
mount -t iso9660 /dev/cdrom /media
挂载U盘
fdisk -l查看U盘设备文件名
mount -t 文件系统 /dev/U盘设备文件名 /mnt
linux默认不支持NTFS文件系统(大部分移动硬盘设备使用NTFS文件系统),但可以通过插件提供支持
卸载设备
注意,如果有任何程序正在使用设备上的文件,系统就不允许卸载,而是会提示 device is busy,注意命令不是un开头,没有n
umount 设备文件名或挂载点目录名卸载设备
如果在卸载设备时,系统提示设备繁忙,无法卸载设备,通常是有进程还在访问该设备或使用该设备上的文件。这时可用lsof命令获得使用它的进程信息,然后在应用中停止使用该设备或停止该进程。如:lsof /path/to/device/node,或者lsof /path/to/mount/point