ls -l 文件类型标识
ls -l 输出第一列的第一个字符表示文件类型:
| 字符 | 类型 |
|---|---|
- |
普通文件 |
d |
目录 |
l |
符号链接(symbolic link) |
c |
字符设备(character device) |
b |
块设备(block device) |
p |
命名管道(named pipe / FIFO) |
s |
socket |
例如 /dev/pts/2 这样的伪终端设备文件,ls -l 第一个字符是 c,因为它是字符设备:数据按字节流顺序读写,不支持像块设备那样按"块"随机寻址。下面分别展开字符设备和块设备的区别。
字符设备, character device
提供连续的数据流,应用程序只能顺序读取,没有寻址(seek)的概念——不能像访问数组那样跳到任意位置读取。此类设备按字节/字符读写数据,键盘、串口、调制解调器都是典型的字符设备。
块设备, block device
块设备以"块"为单位存储数据,典型的如磁盘设备、硬盘、软盘、光盘或者优盘/闪存。在 Linux 系统中一切皆文件,磁盘设备也是文件。应用程序可以随机访问设备数据,自行确定读取数据的位置;数据的读写只能以块(通常是 512 字节)的倍数进行。
ls -l /dev/sd*
brw-rw---- 1 root disk 8, 0 Apr 1 07:15 /dev/sda
brw-rw---- 1 root disk 8, 1 Apr 1 07:15 /dev/sda1
brw-rw---- 1 root disk 8, 2 Apr 1 07:15 /dev/sda2
brw-rw---- 1 root disk 8, 3 Apr 1 07:15 /dev/sda3
字符设备与块设备:谁支持随机访问
两者的根本区别在于能否被随机访问——即能否在访问设备时随意跳转到任意位置。
举个例子,键盘提供的是一个数据流:当敲入 “fox” 时,键盘驱动会按输入顺序原样返回这三个字符组成的数据流;让驱动打乱顺序读,或者跳过去只读某一个字符,都没有意义。所以键盘是典型的字符设备,只能顺序读到一个字符流:先 f,再 o,最后 x,然后是 EOF。没人按键时,字符流就是空的。字符设备支持的是按字节顺序读写,不支持随机寻址。
硬盘则不同:驱动可能先读磁盘上某个块,然后跳去读另一个块,这些块在磁盘上的位置不需要连续,所以硬盘可以被随机访问而不是被当作流来访问,这正是块设备的特征——块设备支持按块随机寻址。
内核管理块设备要比管理字符设备细致得多:字符设备只需要维护一个位置——当前位置;块设备访问的位置则必须能在介质的不同区间前后跳转,因此内核专门有一个子系统来管理块设备(对性能要求也更高),而字符设备不需要这样的专门子系统。
用 ls -l 区分字符设备与块设备
每个字符设备或块设备都在 /dev 目录下对应一个设备文件,通过查看文件属性就能区分类型:
cd /dev
ls -l
crw-rw----+ 1 root root 14, 12 12-21 22:56 adsp
crw------- 1 root root 10, 175 12-21 22:56 agpgart
crw-rw----+ 1 root root 14, 4 12-21 22:56 audio
brw-r----- 1 root disk 253, 0 12-21 22:56 dm-0
brw-r----- 1 root disk 253, 1 12-21 22:56 dm-1
crw-rw---- 1 root root 14, 9 12-21 22:56 dmmidi
第 1 字段第一个字符 c 表示字符设备,b 表示块设备(完整对照见上文表格);第 2-4 字段对驱动开发没有影响;第 5、6 字段分别是主设备号和次设备号;第 7 字段是最后修改时间;第 8 字段是设备名。由此可知 adsp 是字符设备(主设备号 14,次设备号 12),dm-0 是块设备。
网络设备:不在 /dev 下
网络设备是特殊设备的驱动,负责收发帧数据(物理帧或 IP 数据包,具体由网络驱动决定)。它不存在于 /dev 下,与一般设备不同:网络设备是一个 net_device 结构,通过 register_netdev 注册到系统里,可以用 ifconfig -a 查看。
作者:CodeMyLove 来源:简书,著作权归作者所有,商业转载请联系作者授权,非商业转载请注明出处。
BDEV 与 CDEV 的 IO 差异
BDEV 和 CDEV 在 IO 操作上差异很大:
- CDEV 很直接:用户进程发起文件操作系统调用,系统调用直接进到驱动的 file_operations,调用栈就完成了
- BDEV 要用到内核更多机制,比如缓冲、IO 调度、请求队列等
- BDEV 只能以 block 为单位接受输入/输出,CDEV 是以 byte 为单位;大多数设备属于 CDEV,因为它们不需要块缓冲,size 也不固定
- BDEV 对 IO 请求有对应的块缓冲,会先对请求排序,再按排序后的顺序发起实际 IO
- BDEV 可以随机访问,因为具有 position pointer;CDEV 只能顺序 IO
- BDEV 通常不由用户进程直接通过文件操作访问,而是在 BDEV 上部署 IO 调度,调度层之上再部署文件系统(如 ext4);用户通过文件操作访问文件系统,文件系统把请求映射成 BDEV 的实际 IO 请求,经过调度后发给 BDEV。不过 Linux 也保留了
direct_access方式可以直接访问 BDEV,比如直接读写/dev/sdb1
版权声明:本节整理自 CSDN 博主「Huskar_Liu」的原创文章,遵循 CC 4.0 BY-SA 版权协议,原文链接:https://blog.csdn.net/weixin_42418557/article/details/106112364
bdev 伪文件系统
文件系统是对磁盘数据进行组织和管理的一种机制。它可以通过装载,以目录和文件的形式向用户层呈现;但文件和目录只是文件系统的前端,是用户视图,本质还是 inode 这个数据结构。
纯粹从 inode 角度描述文件系统,就是伪文件系统:它不能被装载,不可能从用户空间看到,但不会带来任何信息损失——看不到不等于不存在。伪文件系统包括:负责管理块设备 inode 的 bdev、负责处理管道的 pipefs、处理套接字的 sockfs,这些都出现在 /proc/filesystems 中。
伪文件系统对内核来说就是一个普通文件系统,按通用方法使用即可;对用户来说它不存在。所有表示块设备的 inode 都保存在伪文件系统 bdev 中,这些对用户层不可见,这使得可以用标准的 VFS 函数来处理块设备 inode。
读取一个文件,首先要确定文件块所属的磁盘块,也就是文件的元数据,由 get_block 函数负责(不同文件系统有不同实现,裸设备也有对应函数),这种对应关系记录在 buffer_head 中,记录了磁盘块和文件块的映射关系。读到的元数据会缓存到该文件对应块设备 block_device 的地址空间 address_space 中,下次再读同一文件时,元数据就可以直接从对应 bdev 的缓存中取得。
如果直接对块设备文件(如 /dev/sdx)进行读写,块设备文件也会被缓存到内存中对应的基树 address_space 中。对 bdev 这种特殊文件来说,不仅缓存常规文件的元数据,也缓存真实数据,dd 命令就是这种应用:
dd if=/dev/sda of=/tmp/dest bs=1 count=4096
执行前可以先用 sysctl -w vm.drop_caches=3 清空文件缓存,再用 free 观察 cache 的变化。对文件系统层的代码来说,它不关心你是块设备、常规文件还是字符设备文件,只要你提供 file_operations 函数集合,不会平白给任何文件系统特权。
伪文件系统和普通文件系统的区别在于:其 inode 对用户不可访问,仅在内核态可见,从用户层视角看该文件系统并不存在。伪文件系统的作用是把操作系统中的一些元素(块设备 bdevfs、管道文件 pipefs、套接字 socketfs 等)封装成和普通文件统一的接口,正是通过这种封装,才实现了 Linux “一切皆文件” 的思想。
loop 设备
在类 UNIX 系统里,loop 设备是一种伪设备(pseudo-device),也可以说是仿真设备,它能让我们像访问块设备一样访问一个文件。
使用之前,一个 loop 设备必须先和一个文件建立连接,这种结合方式给用户提供了一个替代块特殊文件的接口——如果这个文件包含一个完整的文件系统,它就可以像磁盘设备一样被 mount 起来。
常见的这类文件格式有 CD/DVD 的 ISO 光盘镜像文件,或者软盘(硬盘)的 *.img 镜像文件。通过 loop mount(回环挂载)的方式,这些镜像文件可以被 mount 到当前文件系统的某个目录下。
顺便理解一下 “loop” 这个名字的含义:第一层文件系统直接安装在物理设备之上;而被 mount 起来的镜像文件(本身也包含文件系统)建立在第一层文件系统之上——看起来就像是在第一层文件系统之上又绕了一圈的文件系统,所以称为 loop。
维护记录
| 时间 | 修改内容 | 原因 |
|---|---|---|
| 2026-07-26 | categories 由 Inbox 改为 Linux;新增 lastmod;补充「ls -l 文件类型标识」小节(-/d/l/c/b/p/s 完整对照表);标签 reprint 改为 remix + AI-assisted,新增 device-file、file-types |
原文档只零散提到 c/b 两种类型,缺少完整的 ls -l 文件类型对照;分类与内容不符 |