linux系统将设备分为3类:字符设备、块设备、网络设备
1、字符设备:是指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据,读取数据需要按照先后数据。字符设备是面向流的设备,常见的字符设备有鼠标、键盘、串口、控制台和LED设备等。
2、块设备:是指可以从设备的任意位置读取一定长度数据的设备。块设备包括硬盘、磁盘、U盘和SD卡等。
每一个字符设备或块设备都在/dev目录下对应一个设备文件。
linux用户程序通过设备文件(或称设备节点)来使用驱动程序操作字符设备和块设备。
字符设备
字符设备的核心结构体是cdev,该结构体定义在include/linux/cdev.h中:
struct cdev {
struct kobject kobj; // 内嵌的kobject对象
struct module *owner; // 所属模块
const struct file_operations *ops; // 文件操作结构体
struct list_head list; //linux内核所维护的链表指针
dev_t dev; //设备号
unsigned int count; //设备数目
};
其中dev_t是专为设备号定义的数据类型,dev为设备号,设备号中包含了主设备号和次设备号。一个字符设备或块设备都有一个主设备号和一个次设备号。主设备号用来标识与设备文件相连的驱动程序,用来反映设备类型。次设备号被驱动程序用来辨别操作的是哪个设备,用来区分同类型的设备。
在内核中,dev_t
用来保存设备编号,包括主设备号和次设备号。dev_t
是一个32位的数,其中12位用来表示主设备号,其余20位用来标识次设备号。
通过dev_t
获取主设备号和次设备号使用下面的宏:
#define MINORBITS 20
#define MINORMASK ((1U << MINORBITS) - 1)
#define MAJOR(dev) ((unsigned int) ((dev) >> MINORBITS))//获得主设备号
#define MINOR(dev) ((unsigned int) ((dev) & MINORMASK)) //获得次设备号
#define MKDEV(ma,mi) (((ma) << MINORBITS) | (mi)) //由主次设备号得到设备号
对于字符设备的访问是通过文件系统中的设备名称进行的。它们通常位于/dev目录下。如下:
xxx@ubuntu:~$ ls -l /dev/
total 0
brw-rw---- 1 root disk 7, 0 12月 25 10:34 loop0
brw-rw---- 1 root disk 7, 1 12月 25 10:34 loop1
brw-rw---- 1 root disk 7, 2 12月 25 10:34 loop2
crw-rw-rw- 1 root tty 5, 0 12月 25 12:48 tty
crw--w---- 1 root tty 4, 0 12月 25 10:34 tty0
crw-rw---- 1 root tty 4, 1 12月 25 10:34 tty1
crw--w---- 1 root tty 4, 10 12月