分类: LINUX
2010-10-31 16:44:33
虽然看了上面一篇转载的《使用/sys/访问系统》对总线,驱动,设备都讲得比较细但还是没有太多的感觉。在此就先把自己今天所学回忆一下。
为了满足新的要求,linux2.6提供了新的设备模型:总线、驱动、设备。基本关系简要的概括如下:
驱动核心可以注册多种类型的总线。
每种总线下面可以挂载许多设备。(通过kset devices)
每种总线下可以用很多设备驱动。(通过包含一个kset drivers)}
每个驱动可以处理一组设备。按照我的理解就是所有的设备都挂载到总线上,当加载驱动时,驱动就支总线上找到自己对应的设备。或者先把驱动加载上,来了一个设备就去总线找驱动。
一:总线
总线是处理器与设备之间通道,在设备模型中,所有的设备都通过总线相连
(1)bus_type.
struct bus_type {
};
在后面的实例当中用到了里面的两个成员
1:const char *name;
2:
这个匹配函数是很关键的东西,这是建立总线上设备与驱动的桥梁,当一个新的设备或驱动被添加到一个总线上时被调用。
(2)总线的操作:
注册:int bus_register(struct bus_type * bus)
注销:void bus_unregister(struct bus_type *bus);
(3)总线属性 bus_attribute
struct bus_attribute {
struct attribute attr;
ssize_t (*show)(struct bus_type *bus, char *buf);
ssize_t (*store)(struct bus_type *bus, const char *buf,
size_t count);
};
BUS_ATTR(name, mode, show, store);
这个宏声明一个结构, 产生它的名子通过前缀字符串 bus_attr_ 到给定的名子.
任何属于一个总线的属性应当明确使用 bus_create_file 来创建:
int bus_create_file(struct bus_type *bus, struct bus_attribute *attr);
属性也可被去除, 使用:
void bus_remove_file(struct bus_type *bus, struct bus_attribute *attr);
lddbus 驱动创建一个简单属性文件, 再次, 包含源码版本号. show 方法和 bus_attribute 结构设置如下:
static ssize_t show_bus_version(struct bus_type *bus, char *buf)
{
return snprintf(buf, PAGE_SIZE, "%s\n", Version);
}
这个总线属性现目前为止我还没有发现它的作用。
(4)总线实例:
其实在这个程序中操作很简单:
1:首先是要准备一个总线bus_type.也就是定义一个bus_type,然后给它填上一些成员。
定义如下:
struct bus_type my_bus_type = {
};
这里就对其两个成员赋值了。一个是名称。另一个则是匹配函数:
static int my_match(struct device *dev, struct device_driver *driver)
{
}
这是匹配的逻辑则是设备的名字与驱动的名字一样。
准备好了总线后就在模块初始化函数中注册:
然后在模块退出函数中注解总线:
总线操作完后还要为总线创建属性文件:
static BUS_ATTR(version, S_IRUGO, show_bus_version, NULL);这句话就定义了一个总线属性文件。BUS_ATTR宏的定义如下:
bus_unregister(&my_bus_type);
#define BUS_ATTR(_name, _mode, _show, _store)
struct bus_attribute bus_attr_##_name = __ATTR(_name, _mode, _show, _store)
show_bus_version定义如下:
static ssize_t show_bus_version(struct bus_type *bus, char *buf)
{
}
定义好之后就是调用 函数创建文件
总线本身也是要对应一个设备的。还要为总线创建设备。
static void my_bus_release(struct device *dev)
{
}
struct device my_bus = {
};
可是这是有疑问,我还没有找到这个总线设备,和刚才的总线的联系。
源代码:
#include
#include
#include
#include
#include
MODULE_AUTHOR("Larry");
MODULE_LICENSE("Dual BSD/GPL");
static char *Version = "$Revision: 1.9 $";
static int my_match(struct device *dev, struct device_driver *driver)
{
}
static void my_bus_release(struct device *dev)
{
}
struct device my_bus = {
};
struct bus_type my_bus_type = {
};
EXPORT_SYMBOL(my_bus);
EXPORT_SYMBOL(my_bus_type);
static ssize_t show_bus_version(struct bus_type *bus, char *buf)
{
}
static BUS_ATTR(version, S_IRUGO, show_bus_version, NULL);
static int __init my_bus_init(void)
{
}
static void my_bus_exit(void)
{
}
module_init(my_bus_init);
module_exit(my_bus_exit);
二:设备:
1:
struct device {
struct device
char
struct bus_type
struct device_driver *driver;
void
///更多字段忽略了
};
注册设备:int device_register(sruct device *dev)
注销设备:void device_unregister(struct device *dev);
2:设备属性:
sysfs 中的设备入口可有属性. 相关的结构是:
struct device_attribute {
struct attribute attr;
ssize_t (*show)(struct device *dev, char *buf);
ssize_t (*store)(struct device *dev, const char *buf,
size_t count);
};
这些属性结构可在编译时建立, 使用这些宏:
DEVICE_ATTR(name, mode, show, store);
结果结构通过前缀 dev_attr_ 到给定名子上来命名. 属性文件的实际管理使用通常的函数对来处理:
int device_create_file(struct device *device, struct device_attribute *entry);
void device_remove_file(struct device *dev, struct device_attribute *attr);
struct bus_type 的 dev_attrs 成员指向一个缺省的属性列表, 这些属性给添加到总线的每个设备创建.
3:创建设备实例:
创建设备和创建总线基本一样这里只贴出程序:
#include
#include
#include
#include
#include
MODULE_AUTHOR("Larry");
MODULE_LICENSE("Dual BSD/GPL");
extern struct device my_bus;
extern struct bus_type my_bus_type;
static void my_dev_release(struct device *dev)
{
}
struct device my_dev = {
};
static ssize_t mydev_show(struct device *dev,struct device_attribute *attr, char *buf)
{
}
static DEVICE_ATTR(dev, S_IRUGO, mydev_show, NULL);
static int __init my_device_init(void)
{
}
static void my_device_exit(void)
{
}
module_init(my_device_init);
module_exit(my_device_exit);
三:设备驱动:
在总线上挂载了设备后就要为其准备驱动程序。
驱动程序的实现与设备的实现类似,代码如下:
#include
#include
#include
#include
#include
MODULE_AUTHOR("Larry");
MODULE_LICENSE("Dual BSD/GPL");
extern struct bus_type my_bus_type;
static int my_probe(struct device *dev)
{
}
static int my_remove(struct device *dev)
{
}
struct device_driver my_driver = {
};
static ssize_t mydriver_show(struct device_driver *driver, char *buf)
{
}
static DRIVER_ATTR(drv, S_IRUGO, mydriver_show, NULL);
static int __init my_driver_init(void)
{
}
static void my_driver_exit(void)
{
}
module_init(my_driver_init);
module_exit(my_driver_exit);
chinaunix网友2010-10-31 19:08:30
很好的, 收藏了 推荐一个博客,提供很多免费软件编程电子书下载: http://free-ebooks.appspot.com