1,直接上code
#include <linux/device.h>
#include <linux/kernel.h> #include <linux/init.h> #include <linux/module.h> #include <linux/stat.h> #include <linux/slab.h> #include <linux/kobject.h> #include <linux/kdev_t.h> //#include "./kf_device.h" #define KFMAJOR 96 //-----\\class moduel static struct class kf_class={ .name = "kf-class", .owner = THIS_MODULE, }; static int kf_class_register(void){ int ret = -1; ret = class_register(&kf_class); //kf_class = class_create(THIS_MODULE,"kfclass"); if(ret < 0){ printk("kf-class register error!\n"); //return kf_class_unregister(&kf_class); } printk("kf-class register ok!\n"); return 0; } static void kf_class_unregister(void){ class_unregister(&kf_class); //class_destroy(&kf_class); } //------\\bus moduel static int kf_bus_type_match(struct device *dev, struct device_driver *drv) { printk("enter %s\n",__func__); return 1; } /*static int kf_bus_type_probe(struct device *dev){ int ret = -1; printk("enter %s\n",__func__); if (dev->driver->probe) ret = dev->driver->probe(dev); return ret; }*/ static void kf_bus_release(struct device *dev){ //need to do printk("%s\n",__func__); } static struct bus_type kf_bus_type = { .name = "kf-bus-type", .match = kf_bus_type_match, // .probe = kf_bus_type_probe, }; static struct device kf_bus = { .init_name = "kf-bus", .release = kf_bus_release, }; static int kf_bus_register(void){ int bus_ret = -1; //kf_bus.class = &kf_class; bus_ret = device_register(&kf_bus); if(bus_ret < 0){ printk("bus device reister error!\n"); } bus_ret = bus_register(&kf_bus_type); if(bus_ret < 0){ printk("bus type reister error!\n"); } printk("kf_bus & kf_bus_type register ok\n"); return bus_ret; } static void kf_bus_unregister(void){ bus_unregister(&kf_bus_type); device_unregister(&kf_bus); } //-----\\device module static void kf_device_release(struct device *dev){ printk("%s\n",__func__); } static struct device kf_device={ .init_name = "kf-device0", .devt = MKDEV(KFMAJOR,1), .release = kf_device_release, }; static int kf_device_register(void){ int ret = -1; //Do not point this class //kf_device.class = &kf_class; kf_device.bus = &kf_bus_type; kf_device.parent = &kf_bus; ret = device_register(&kf_device); if(ret < 0){ printk("kf device reister error!\n"); } printk("kf device reister ok!\n"); return ret; } static void kf_device_unregister(void){ device_unregister(&kf_device); } //------\\driver module /* struct kf_device_driver{ char *name; struct device_driver driver; };*/ static int kf_device_driver_probe(struct device *dev){ printk("enter drive probe\n"); return 0; } static struct device_driver kf_device_driver={ .name = "kf-device-driver", .probe = kf_device_driver_probe, }; static int kf_device_dirver_register(void){ int ret = -1; kf_device_driver.bus = &kf_bus_type; ret = driver_register(&kf_device_driver); printk("kf_device_driver reister ok!\n"); return ret; } static void kf_device_dirver_unregister(void){ driver_unregister(&kf_device_driver); } //-----\\init func static int __init kf_bus_init(void) { int com_ret; printk(">>>kf_bus_init successed!!\n"); com_ret =kf_class_register(); com_ret = kf_bus_register(); com_ret = kf_device_register(); com_ret = kf_device_dirver_register(); if(com_ret < 0){ printk(">>>kf_bus_register error\n"); //kf_bus_unregister(); } return 0; } static void __exit kf_bus_exit(void) { printk(">>>kf_bus_exit successed!!\n"); kf_device_dirver_unregister(); kf_device_unregister(); kf_bus_unregister(); kf_class_unregister(); } module_init(kf_bus_init); module_exit(kf_bus_exit); MODULE_AUTHOR("Koffuxu"); MODULE_LICENSE("GPL"); |
2,现在已经insmod成功了,纵观一下sys文件系统的各个目录。bus的match成功了,会在device下面有软链接
同时,在driver中?也有软链接。
在bus目录:
在device目录:
在class目录:null。因为没有指定相关bus
3,罗嗦一下,uevent模块
两种方式通知用户层,在Android系统中,这两种方式并存着。这里可以就足够写一篇了
int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,char *envp_ext[])
方式一,
/* send netlink message 实际就是socket通信*/
netlink_broadcast_filtered(uevent_sock, skb, 0, 1, GFP_KERNEL,kobj_bcast_filter, kobj);@af_netlink.c
方式二,
/* call uevent_helper, usually only enabled during early boot 调用uevent_helper函数*/
call_usermodehelper(argv[0], argv, env->envp, UMH_WAIT_EXEC);@kmod.c
4,UML读图(图画得不好,既然都画了,那还是贴出来吧)
所有的*_private成员与其引用的struct都是相互引用
5,device如何指定某个class?
切记,不要把device bus和stuct device dev指定在一个class,否则会重复建目录导致dev register失败!
像这样提示错误
6,如果指定了某个class(kf-class)之后,这个device就会从sys/device目录移到/sys/device/virtual/kf-class/下面
这是因为在这个函数中操作的。
device_add_class_symlinks(dev);
device_add_attrs(dev);
7,如果使用MKDEV
.devt = MKDEV(KFMAJOR,1),
8,struct device设备必须要实现release函数,否则rmmond会报错
驱动模型小节已经完成。水平有限,时间仓促,肯定有诸多错误,若影响读者有什么疑问,大家一起讨论学习。
有烟吗?我想抽一根。