一、优化——自动申请设备号、自动创建节点
设备号类型:①主设备号 ②子设备号 类型:unsigned int <==>dev_t
12 major (主设备号) | 20 minor (子设备号)<区分相同驱动下的不同设备> |
编写模块初始化设备流程:
(1)申请设备号的函数为:
int alloc_chrdev_region(dev_t *dev(设备号), unsigned baseminor(设备号起始地址), unsigned count(申请该设备个数), const char *name(设备名称));
(2)初始化cdev,将字符设备与驱动程序关联起来:
void cdev_init(struct cdev *cdev, const struct file_operations *fops);
(3)将注册好的设备添加到操作系统当中:
int cdev_add(struct cdev *p, dev_t dev, unsigned count(次设备号个数));
(4)归还设备号
void unregister_chrdev_region(dev_t from, unsigned count)
(5)创建设备节点(带参宏)
#define class_create(owner, name(设备类型 名字))
注:①owner指向模块的指针,这里只需传THIS_MODULE。
②该函数返回struct class *,用宏IS_ERR判断是否合法。
(6)添加节点
struct device *device_create(struct class *class, struct device *parent(设备的父设备指针,传NULL), dev_t devt, void *drvdata(驱动需要的额外参数,这里传NULL), const char *fmt(节点名字), ...);
(7)各销毁函数
void device_destroy(struct class *class, dev_t devt);
void cdev_del(struct cdev *p);
void class_destroy(struct class *cls)
①eg:led实现编写标准字符设备驱动程序。
以上我们编写的是标准字符设备驱动程序,linux内核api接口提供了一种混杂设备驱动程序框架,可以大幅度降低编写字符设备驱动程序复杂性。
其特点:是最简单的字符设备驱动。所有的misc 设备驱动的主设备号都为10,不同的设备使用不同的从设备号。misc 设备会自动创建cdev,不需要手动创建。
(1)注册混杂设备:
int misc_register(struct miscdevice * misc);
注:struct miscdevice结构体中我们主要关注3个成员:
1. minor:子设备号,由于主设备号都是10,子设备号必须指定而且不能冲突, linux/miscdevice.h中定义了几个子设备号,如果需要动态获取,就用MISC_DYNAMIC_MINOR;
2. name:将来在/dev下的设备名;
3. fops:指向文件操作结构体变量的指针。
(2)注销混杂设备:
misc_deregister(&led_misc_device);
(3)注册中断:
int request_irq(unsigned int irq(中断号), irq_handler_t handler(中断服务函数), unsigned long flags(中断处理方式),const char *name(中断名字), void *dev(中断服务函数传参,为设备地址));
中断服务函数:irqreturn_t key_irq_handle(int irq, void *pData);
(4)禁止中断
void disable_irq(unsigned int irq);
(5)注销中断
void free_irq(unsigned int irq, void *dev_id);
②eg:key实现编写混杂设备驱动+linux内核中断
【应用层】
内核中断需要分类、筛选、调度,其响应速度相比与硬件中断大大降低。
命令:用于一次性将文件中的原字改为新字:0,$s/原/新/g