目录

Linux 文件类型

在 Linux 系统中,一切皆为文件,包括硬盘与键盘等外接设备,所以 Linux 规定了七种不同的文件类型来对系统的所有文件进行了功能性划分。对于文件类型的检查可以使用 file 命令直接检查文件的类型,或者使用 ls 命令检查文件的模式。下表列出了所有七种文件类型,并给出了模式字符串中文件标志位对应的标志。

文件类型 模式标志 描述
普通文件 - 普通文件即日常使用的普通文件,如程序、文本或者数据等
目录文件 d 目录文件存放它所包含的每个文件和子目录的目录项
字符设备文件 c 字符设备文件提供对串行流设备的访问,如串口、tty 终端等
块设备文件 b 块设备文件为块设备提供文件接口,如硬盘等
符号链接文件 l 符号链接文件指向设备上的另一个文件或文件夹
管道文件 p 管道文件可以将数据先进先出(FIFO)的方式发送到另一个进程
套接字文件 s 套接字文件可以使进程之间通过本地套接字的方式通信

普通文件

普通文件是我们在日常使用中接触最多的一类文件,包含文本文件、二进制文件以及特殊格式文件。像代码文件、图片、压缩文件等都属于普通文件,并且文件扩展名或者幻数可以用来检测文件格式。这里要注意,Linux 的文件类型与文件格式并不是同一个概念,文件类型相对于文件格式更加底层,并且文件类型并不依赖文件扩展名,而文件格式通常使用扩展名来进行区分。

使用 ls 来查看文件系统的文件时,如果使用了 --color=auto 参数,普通文件一般显示为「白色」,如果使用了 -l 选项,模式一栏中的第一个字符为「-」为普通文件,例如:

~ $ ls -l .bashrc
-rw-r--r--  1 sam  sam     3819 2021年 5月26日 .bashrc

或者使用 file 命令来检查文件类型:

~ $ file .bashrc
.bashrc: ASCII text

目录文件

目录文件是我们日常接触第二多的一类文件,目录文件中存放有它所包含的每个子文件以及子目录的目录项。通过目录文件,Linux 的所有文件目录会形成树形结构,称之为做目录树,可以通过 tree 命令来生成某一目录的目录树。

使用 ls 来查看文件系统的目录时,如果使用了 --color=auto 参数,目录文件一般显示为「蓝色」,如果使用了 -l 选项,模式一栏中的第一个字符为「d」为目录文件,例如:

~ $ ls -l Documents
drwxr-xr-x  1 sam  sam      198  1月18日 11:10 Documents

或者使用 file 命令来检查文件类型:

~ $ file Documents
Documents: directory

特殊文件

字符设备文件

字符设备文件为串行流设备提供了访问接口,例如串口、终端等,应用程序可以使用统一的调用方式对这些设备文件进行访问。字符设备文件通常位于 /dev 目录下:

$ ls -l /dev | grep "^c"
crw-rw-rw-   1 root root     1,     3  6月27日 11:58 null
crw-rw-rw-   1 root tty      5,     0  6月30日 16:37 tty
crw-rw-rw-   1 root root     1,     8  6月27日 11:58 random
crw-rw-rw-   1 root root     1,     5  6月27日 11:58 zero

可以通过向 /dev/tty 中写入字符,以向当前终端中打印字符:

$ echo "write to /dev/tty" > /dev/tty
write to /dev/tty

或者从随机数据流读取数据并转换成十六进制显示:

$ cat /dev/random | od -x | head -n 5
0000000 a85d 59aa 00e8 f49a ae47 93d2 ef25 8229
0000020 c2f4 250d 654e ef35 513d dd19 37cc e66f
0000040 85c8 cafe 658f 3604 53c8 a035 6f4e dd4e
0000060 bc38 3173 04f1 26ff 6d85 733b a536 3c17
0000100 cfbd f162 e7a9 b940 fcd0 eca5 8787 3462

块设备文件

块设备文件为块设备提供了访问接口,例如硬盘、可移动存储设备等,与字符设备文件类似,可以通过对块设备文件的读写来修改块设备的内容。块设备文件通常位于 /dev 目录下:

$ ls -l /dev | grep "^b"
brw-rw----   1 root disk     8,     0  6月30日 18:36 sda
brw-rw----   1 root disk     8,     1  6月30日 18:36 sda1

可以通过对块设备文件操作来直接读取文件信息。例如在块设备 /dev/sda1 的根目录下存在 file 文件:

(root of sda1) $ cat file
this is the "file"

通过 debugfs 程序输出 /dev/sda1 下的文件 file 的区块号:

$ sudo debugfs /dev/sda1
debugfs:  blocks file
34816

随后使用 dd 命令输出该区块的数据:

$ sudo dd if=/dev/sda1 bs=4k count=1 skip=34816
this is the "file"
输入了 1+0 块记录
输出了 1+0 块记录
4096 字节 (4.1 kB, 4.0 KiB) 已复制,2.6699e-05 s,153 MB/s

符号链接文件

符号链接文件是一类存储着其他文件或目录路径的特殊文件,操作系统会将存储的文件路径解释为链接,从而使得对符号链接文件的操作是透明的,会直接生效于目标文件。

假设文本文件 file 的内容是「this is the “file”」,查看其 inode 信息:

$ ls -li file
6599999 -rw-r--r-- 1 sam sam 19  7月 1日 09:55 file

创建 file 文件的符号链接 file.symlink

$ ln -s file file.symlink

查看 file.symlinkinode 信息:

$ ls -li file.symlink
6600033 lrwxrwxrwx 1 sam sam 4  7月 1日 09:57 file.symlink -> file

可以看到 filefile.symlinkinode 不同,说明符号链接为一个单独的文件,同时 file.symlink 的模式一栏中标明了文件类型为 l,指向 file

管道文件

管道文件可以使两个不相关的进程之间进行通信,在日常使用中比较少见。Linux 中存在两种管道:匿名管道与命名管道,匿名管道只能用于父子进程之间进行通信,而命名管道则通过区分管道文件的文件名来实现不同进程的通信。实际上,在使用管道文件时,并不会向文件系统中写入数据,占用的仍然是内存空间。

使用 mkfifo 命令可以创建一个名为 pipe 的管道文件:

$ mkfifo pipe

使用 ls 查看其类型:

$ ls -l pipe
prw-r--r-- 1 sam sam 0  7月 1日 10:51 pipe

下面可以通过这个 pipe 文件实现两个进程之间的通信:

$ echo "one:two:three:four:five:six:seven" > pipe

此时该进程被阻塞,使用另一终端对 pipe 文件进行读取并输出第 5 栏至行尾:

$ cut -d : -f 5- pipe
five:six:seven

此时被阻塞的进程正常返回了。

套接字文件

套接字文件同样用来进行本地进程间通信,与管道文件单向不同,套接字文件可以实现进程的双向通信。套接字文件只能使用系统调用来创建,所以套接字文件常见于软件配置中。

套接字文件可以使用 ls 来查看:

$ ls -l /run/dbus | grep "^s"
srw-rw-rw- 1 root root  0  6月30日 18:11 system_bus_socket