网站建设待遇,windows 2003 iis 多网站,wordpress主题 missoften,网站建设企业推荐设备驱动模型
面试的时候#xff0c;有面试官会问#xff0c;什么是Linux 设备驱动模型#xff1f;你要怎么回答#xff1f;
这个问题#xff0c;突然这么一问#xff0c;可能你会愣住不知道怎么回答#xff0c;因为Linux 设备驱动模型是一个比较整体的概念#xff0…设备驱动模型
面试的时候有面试官会问什么是Linux 设备驱动模型你要怎么回答
这个问题突然这么一问可能你会愣住不知道怎么回答因为Linux 设备驱动模型是一个比较整体的概念Linux 内核一半的代码都是设备驱动怎么管理设备驱动怎么抽象怎么简化驱动开发的工作这就是设备驱动模型要干的事情
其实你不懂也没关系你反问下面试官你是如何理解设备驱动模型的虽然面试失败了但是你学到东西了啊岗位那么多下一家可能就是你人生的巅峰呢。
Linux 设备驱动模型说到这个部分就不得不提几个重要的东西BUS(总线)Class类Device(设备)Driver(驱动)。
Bus总线 Linux 把总线设计成一个道路所有的设备都都必须挂载在总线上面你可以理解为所有的车子都必须开在高速路上要不然就不遵守规则了。
Class分类 在Linux设备模型中Class的概念非常类似面向对象程序设计中的Class类它主要是集合具有相似功能或属性的设备这样就可以抽象出一套可以在多个设备之间共用的数据结构和接口函数。块设备字符设备网络设备这些可以理解为大类。
Device设备 抽象系统中所有的硬件设备描述它的名字、属性、从属的Bus、从属的Class等信息我们正常些驱动还会写上这个设备的一些硬件资源中断口复位口I2C地址等等。
Device Driver驱动 Linux设备模型用Driver抽象硬件设备的驱动程序它包含设备初始化、电源管理相关的接口实现。而Linux内核中的驱动开发基本都围绕该抽象进行实现所规定的接口函数如果有3个一样的设备可以使用同一个驱动。 资料直通车Linux内核源码技术学习路线视频教程内核源码 学习直通车Linux内核源码内存调优文件系统进程管理设备驱动/网络协议栈 kobject 是什么
kobject 就是一个结构体而已别看只是一个结构体这个结构体可以说是串联了设备驱动里面的所有东西设备驱动模型都是靠这个来穿针引线的嗯我觉得用穿针引线这个词语非常好非常妙。每个kobject对应/sys/目录下面的一个目录name指定的就是这个目录的名字。
struct kobject {const char *name;struct list_head entry;struct kobject *parent;struct kset *kset;struct kobj_type *ktype;struct kernfs_node *sd; /* sysfs directory entry */struct kref kref;
#ifdef CONFIG_DEBUG_KOBJECT_RELEASEstruct delayed_work release;
#endifunsigned int state_initialized:1;unsigned int state_in_sysfs:1;unsigned int state_add_uevent_sent:1;unsigned int state_remove_uevent_sent:1;unsigned int uevent_suppress:1;
};
既然kobject是对应/sys/下面的一个目录那么kset是什么呢好吧kset也就只是一个结构体而已这个结构体里面引用了kobject这个应该是C语言的巧妙之处使用这样的方式实现继承的关系我包含里的类型使用起来就是kobject是我的基类通过这个基类我再创造出一个新的类这个类的名字就是kset类那个是C的说法在C里面就是一个结构体了。仅此而已。
struct kset {struct list_head list; struct kobject kobj; struct kset_uevent_ops *uevent_ops;spinlock_t list_lock;};
既然我们知道 kobject是一个目录那么kset是kobject的高级体那么kset也就是一个目录这个目录的名字也就是kobject来指定的而且kset 里面有一个链表可以看出来kset就是一个类别的kobject的集合比如bus目录下面就全部是bus相关的i2c是一个Busplatform也是一个bus等等。 container_of宏
之前写过文章说明这个宏的作用分析了实现的过程实际上就是一个如果我们知道一个结构体成员变量可以通过这个结构体成员变量获取这个结构体的指针。
container_of宏解析
#ifndef container_of
#define container_of(ptr, type, member) ({ \const typeof(((type *)0)-member) * __mptr (ptr); \(type *)((char *)__mptr - offsetof(type, member)); })
#endif 实例分析
#include linux/device.h
#include linux/module.h
#include linux/kernel.h
#include linux/init.h
#include linux/string.h
#include linux/sysfs.h
#include linux/stat.hMODULE_AUTHOR(peiqi);
MODULE_LICENSE(Dual BSD/GPL);/*对应于kobject的目录下的一个文件,Name成员就是文件名*/
struct attribute test_attr { .name kobj_test_config, .mode S_IRWXUGO,
};static struct attribute *def_attrs[] { test_attr, NULL,
};/*当读文件时执行的操作*/
ssize_t kobj_test_show(struct kobject *kobject, struct attribute *attr,char *buf)
{ printk(kobj_test_show\n); printk(attrname:%s.\n, attr-name); sprintf(buf,:%s\n,attr-name); return strlen(attr-name)2;
}/*当写文件时执行的操作*/
ssize_t kobj_test_store(struct kobject *kobject,struct attribute *attr,const char *buf, size_t count)
{ printk(kobj_test_store\n); printk(write: %s\n,buf); return count;
}
//kobject对象的操作
struct sysfs_ops obj_test_sysops
{ .show kobj_test_show, .store kobj_test_store,
};/*release方法释放该kobject对象*/
void obj_test_release(struct kobject *kobject)
{ printk(obj_test_release: release .\n);
}/*定义kobject对象的一些属性及对应的操作*/
struct kobj_type ktype
{ .release obj_test_release, .sysfs_opsobj_test_sysops, .default_attrsdef_attrs,
};struct kobject kobj;//声明对象static int kobj_test_init(void)
{ printk(kobj_test_init.\n); kobject_init_and_add(kobj,ktype,NULL,kobject_test_1);//初始化kobject对象kobj,并将其注册到linux系统 return 0;
}static void kobj_test_exit(void)
{ printk(kobj_test_exit.\n); kobject_del(kobj);
}module_init(kobj_test_init);
module_exit(kobj_test_exit);
Makefile:
ifneq ($(KERNELRELEASE),)
$(warning ------------------------001)
obj-m : kobject.o
else
PWD : $(shell pwd)
KVER : $(shell uname -r)
KDIR : /lib/modules/$(KVER)/build
$(warning ------------------------002)
all:$(MAKE) -C $(KDIR) M$(PWD) modules$(warning ------------------------003)
clean:rm -rf .*.cmd *.o *.*~ *.order *.symvers *.mod.c *.ko .tmp_versions
endif 设备驱动使用kobject
看下面这个图片我们看到设备驱动使用kobject 的流程 /*** bus_add_driver - Add a driver to the bus.* drv: driver.*/
int bus_add_driver(struct device_driver *drv)
{struct bus_type *bus;struct driver_private *priv;int error 0;/* 通过driver指针获取bus指针 */bus bus_get(drv-bus);if (!bus)return -EINVAL;pr_debug(bus: %s: add driver %s\n, bus-name, drv-name);/* 申请内存 */priv kzalloc(sizeof(*priv), GFP_KERNEL);if (!priv) {error -ENOMEM;goto out_put_bus;}klist_init(priv-klist_devices, NULL, NULL);priv-driver drv;drv-p priv;priv-kobj.kset bus-p-drivers_kset;error kobject_init_and_add(priv-kobj, driver_ktype, NULL,%s, drv-name);if (error)goto out_unregister;klist_add_tail(priv-knode_bus, bus-p-klist_drivers);if (drv-bus-p-drivers_autoprobe) {if (driver_allows_async_probing(drv)) {pr_debug(bus: %s: probing driver %s asynchronously\n,drv-bus-name, drv-name);async_schedule(driver_attach_async, drv);} else {error driver_attach(drv);if (error)goto out_unregister;}}module_add_driver(drv-owner, drv);error driver_create_file(drv, driver_attr_uevent);if (error) {printk(KERN_ERR %s: uevent attr (%s) failed\n,__func__, drv-name);}error driver_add_groups(drv, bus-drv_groups);if (error) {/* How the hell do we get out of this pickle? Give up */printk(KERN_ERR %s: driver_create_groups(%s) failed\n,__func__, drv-name);}if (!drv-suppress_bind_attrs) {error add_bind_files(drv);if (error) {/* Ditto */printk(KERN_ERR %s: add_bind_files(%s) failed\n,__func__, drv-name);}}return 0;out_unregister:kobject_put(priv-kobj);kfree(drv-p);drv-p NULL;
out_put_bus:bus_put(bus);return error;
}