编写流程
1.设备号: /dev 设备文件目录
Linux会给 每个设备 分配一个 唯一的 id ---> 设备号
设备号: 就是一个整数, 分为 设备号 32bit int = 主设备号|次设备号
主设备号: 表示一类设备,针对的是 设备驱动
次设备号: 表示某个具体的设备
如下: 4个 UART---串口PC
UART 电压3.3V : -----SP3232电压转换------串口-----PC
crw-rw---- 1 root dialout 204, 64 Jan 1 02:49 ttySAC0
crw-rw---- 1 root dialout 204, 65 Jan 1 02:49 ttySAC1
crw-rw---- 1 root dialout 204, 66 Jan 1 02:49 ttySAC2
crw-rw---- 1 root dialout 204, 67 Jan 1 02:49 ttySAC3
主设备号:204
次设备号:64,65,66,67
typedef u_long dev_t ;
主设备号: 高12位
次设备号: 低20位
设备号: 主设备号|次设备号
MAJOR(dev) 分离 dev 的 主设备号
MINOR(dev) 分离 dev 的 此设备号
MKDEV(ma, mi) 构造一个 设备号
dev_t devno = MKDEV(200,0);
2. 向内核申请设备号
静态申请: int register_chrdev_region(dev_t from, unsigned count, const char * name)
from : 你要申请的 第一个设备号
count : 你要申请几个设备号
name: 驱动的名字
返回值: 0 : 成功
其他: 失败
动态申请: alloc_chrdev_region(dev_t * dev, unsigned baseminor, unsigned count, const char * name)
dev : 指针,用来保存 申请到的 设备号
baseminor : 要申请的第一个 次设备号
count : 你要申请几个设备号
name: 驱动的名字
返回值: 0 : 成功
其他: 失败
注销设备号: void unregister_chrdev_region(dev_t dev, unsigned count )
dev: 要注销的第一个设备号
count : 要注销设备号的数量
3. 字符设备
struct cdev {
struct kobject kobj;
struct module *owner;
const struct file_operations *ops; 文件操作结构体
struct list_head list;
dev_t dev; 设备号
unsigned int count; 设备的数量
};
struct cdev *cdev_alloc(); 分配一个字符设备
cdev_init(struct cdev * cdev, const struct file_operations * fops); 初始化一个 cdev结构体
cdev_add(struct cdev * p, dev_t dev, unsigned count); 把 cdev 结点,添加到内核 字符设备链表中
cdev_del(struct cdev * p); 把一个 cdev结点 ,从内核的 字符设 备链表中删除
4. 在 /dev 创建 设备文件的节点
cat /proc/devices 查看当前linux内核 有哪些 设备驱动
4.1手动创建 设备节点文件:
mknod /dev/yourname c major minor
4.2 自动创建 设备节点文件:
class_create -----> 创建一个设备类
class_create(owner, name)
owner: 创建的设备类,属于哪个模块: THIS_MODULE
name: 设备类的名字
device_create( struct class *class, struct device *parent, dev_t devno, void *drvdata, const char *fmt,...);
device_destroy(mycls, devno);
class_destroy(mycls);