字符设备

提供连续的数据流,应用程序可以顺序读取,通常不支持随机存取。相反,此类设备支持按字节/字符来读写数据。举例来说,键盘、串口、调制解调器都是典型的字符设备。

块设备, block device

块设备也就是存储以“块”为单位数据的设备,比较典型的如磁盘设备, 硬盘、软盘,光盘或者优盘/闪存。在 Linux 系统中,一切皆文件,磁盘设备也是文件 应用程序可以随机访问设备数据,程序可自行确定读取数据的位置。数据的读写只能以块(通常是512B)的倍数进行
与字符设备不同,块设备并不支持基于字符的寻址。

用 ls 查看磁盘分区文件

1
2
3
4
5
6
7
8
9
ls -l /dev/sd*

# output
➜  ~ 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)。当没人敲键盘时,字符流就是空的。硬盘设备的情况就不大一样了。硬盘设备的驱动可能要求读取磁盘上任意块的内容,然后又转去读取别的块的内容,而被读取的块在磁盘上位置不一定要连续,所以说硬盘可以被随机访问,而不是以流的方式被访问,显然它是一个块设备。 内核管理块设备要比管理字符设备细致得多,需要考虑的问题和完成的工作相比字符设备来说要复杂许多。这是因为字符设备仅仅需要控制一个位置—当前位置—而块设备访问的位置必须能够在介质的不同区间前后移动。所以事实上内核不必提供一个专门的子系统来管理字符设备,但是对块设备的管理却必须要有一个专门的提供服务的子系统。不仅仅是因为块设备的复杂性远远高于字符设备,更重要的原因是块设备对执行性能的要求很高;对硬盘每多一分利用都会对整个系统的性能带来提升,其效果要远远比键盘吞吐速度成倍的提高大得多。另外,我们将会看到,块设备的复杂性会为这种优化留下很大的施展空间。

字符设备与块设备的区分 每一个字符设备或者块设备都在/dev目录下对应一个设备文件。读者可以通过查看/dev目录下的文件的属性,来区分设备是字符设备还是块设备。使用cd命令进入/dev目录,并执行ls -l命令就可以看到设备的属性

[root@tom /]# cd /dev /进入/dev目录/
[root@tom dev]# ls -l /列出/dev中文件的信息/、 /*第1字段 2 3 4 5 6 7 8 */
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

ls -l命令的第一字段中的第一个字符c表示设备是字符设备,b表示设备是块设备。第234字段对驱动程序开发来说没有关系。第5,6字段分别表示设备的主设备号和次设备号。第7字段表示文件的最后修改时间。第8字段表示设备的名字。 由第1和8字段可知,adsp是字符设备,dm-0是块设备。其中adsp设备的主设备号是14,次设备号是12。

网络设备

网络设备是特殊设备的驱动,它负责接收和发送帧数据,可能是物理帧,也可能是ip数据包,这些特性都有网络驱动决定。它并不存在于/dev下面,所以与一般的设备不同。网络设备是一个net_device结构,并通过register_netdev注册到系统里,最后通过ifconfig -a的命令就能看到。

作者:CodeMyLove 链接:https://www.jianshu.com/p/477c5b583fbe 来源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

BDEV, CDEV

BDEV和CDEV在IO操作上有很大的不同。 CDEV是直来直去的,用户进程请求文件操作syscall,syscall调用FOPS,整个调用栈就完成了。 但是BDEV要用到内核的更多机制,例如缓冲,IO调度,请求队列等。

BDEV只能以block为单位,接受输入或者输出,而CDEV是以byte为单位。所以大多数设备属于CDEV,因为他们不需要块缓冲,而且size不固定。 BDEV对IO请求存在对应的块缓冲,BDEV要先对IO请求进行排序,然后再按照排序后的IO请求来发起实际的IO。 BDEV可以随机访问,因为BDEV具有position pointer ,但是CDEV只能顺序IO。 BDEV通常不直接由用户进程通过文件操作机制进行访问,而是在BDEV上,部署IO调度,在IO调度层之上,又部署文件系统,例如ext4等,用户通过文件操作机制访问FS,由FS将用户的文件请求映射成BDEV的实际IO请求,经过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角度来描述一个文件系统,会是什么情况?

伪文件系统,就是这样的一种表示,它不能装载,不可能从用户空间看到,但它不会带来任何的信息损失。看不到,不等于它不存在。

伪文件系统,包括1)负责管理块设备inode的bdev;2)负责处理管道的pipefs;3)处理套接字的sockfs; 这些都出现在 /proc/filesystems中。

伪文件系统对于内核来说,就是一个普通的文件系统,按通用方法来使用即可,对于用户来说,他不存在.

所有表示块设备的inode都保存在伪文件系统 bdev中,这些对用户层不可见。这使得可以使用标准的VFS函数,来处理块设备inode。

读取一个文件,首先必须确定文件块所属的磁盘块,也就是文件的元数据。由get_block函数(针对不同文件系统,有不同实现,祼设备也其对应函数),而这种对应关系会记录在buffer_head中,它记录了磁盘块和文件块之间的映射关系。读到的文件的元数据会缓存到该文件对应的块设备block_device的地址空间address_space,如果下次再读到同一文件,其元数据就可以从该文件对应bdev的cache中取得了。

如果,我们直接对块设备文件(如/dev/sdx)进行读写,那么块设备文件也会被缓存到内存中其对应的基树address_space中。对bdev这种特殊文件来说,其不光缓存常规文件的元数据,也会缓存真实的数据,dd命令就是这种应用。

可以通过dd if=/dev/sda of=/tmp/dest bs=1 count=4096命令,然后用free来查看cache的变化,记住在执行上述命令之前首先通过sysctl -w vm.drop_caches=3来清空文件的cache。对于文件系统层的代码来看,它根本不管你是块设备还是常规文件或者是一个字符设备文件,它只要你提供file_operations函数集合而不会平白无故给与任何文件系统以特权。

伪文件系统和普通文件系统的区别在于,其inode对用户不可访问,即仅在内核态可见,从用户层的视角来看该文件系统并不存在。伪文件系统的作用是对一些操作系统中的元素进行封装,和普通的文件统一接口,如块设备bdevfs,管道文件pipefs,套接字socketfs等。通过这种方式的统一封装,才实现了Linux一切皆文件的思想。

https://ty-chen.github.io/linux-kernel-block-device/