静态设备号申请:
申请设备号, from --- 要申请的设备号, count --- 申请几个设备, name --- 设备名字
int register_chrdev_region(dev_t from, unsigned count, const char *name)
注销设备号, from --- 要注销的设备号, count--- 注销几个设备
void unregister_chrdev_region(dev_t from, unsigned count)
静态设备号申请弊端:
- 麻烦, cat /proc/devices 查看可用的设备号, 其次在驱动代码里定义,申请
- 静态申请设备号, 会产生冲突
动态设备号的申请:
动态申请设备号, dev 带回的设备号, baseminor 要申请的从设备号的起始, count --- 申请几个设备, name --- 设备名字
int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,
const char *name)
应用程序如何操作设备?
1, sudo insmod ./hello.ko
2, cat /proc/devices 查看设备hahaha 的设备号
- Sudo mknod /dev/hahaha c 250 0 // 在用户空间创建一个设备文件 hahaha , 字符设备, 主设备号 250 从设备号 0
字符设备驱动:
首先了解下cdev 结构体:
struct cdev {
struct kobject kobj;
struct module *owner;
const struct file_operations *ops; //zyb
struct list_head list;
dev_t dev; //zyb
unsigned int count;
};
申请cdev 结构体:
Cdev_alloc
把cdev 结构体 和 设备的操作方法联系起来 :
Cdev_init
把设备赋值给cdev 结构体, 并且把cdev 结构体添加到字符设备表里,
Cdev_add
Linux/Cdev.h
申请cdev 结构体, 错误返回空值
struct cdev *cdev_alloc(void)
把申请到的cdev 结构体 和 该设备的具体操作关联起来
void cdev_init(struct cdev *cdev, const struct file_operations *fops)
struct file_operations {
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
int (*open) (struct inode *, struct file *);
int (*release) (struct inode *, struct file *);
};
把cdev 结构体和 设备号关联起来, 并且把cdev 结构体 添加到字符设备表里,
int cdev_add(struct cdev *p, dev_t dev, unsigned count)
从用户空间copy 数据到内核空间
static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n)
从内核空间copy 数据到用户空间
static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n)
字符设备框架:
- 动态申请设备号 alloc_chrdev_region
- 申请cdev 结构体 cdev_alloc
- 把cdev 结构体 和 设备操作集 关联起来 : cdev_init
- 把cdev 结构体和 设备号关联起来,并且把cdev 添加到字符设备表: cdev_add
- 实现设备的操作方法 :
struct file_operations hahahaOPS =
{
.read = hahahaRead,
.write = hahahaWrite,
.open = hahahaOpen,
.release = hahahaClose,
};
- 实现具体的方法:
int hahahaOpen( struct inode *p, struct file *f)
{
printk("hahaha device open\n");
return 0;
}
测试步骤:
- Make
- Sudo insmod ./hello/ko
- Cat /proc/devices 查看我们申请的字符设备的主设备号
- Mknod /dev/hahaha c 250 0
5, 编写应用程序, 测试驱动