Linux设备驱动模型(1)

在Linux内核的说明文档里有一些关于驱动模型的说明文件,首先解读一下第一个文件bus.txt:

struct bus_type {
       char               * name;
 
       structsubsystem    subsys;
       structkset             drivers;
       structkset             devices;
 
       structbus_attribute * bus_attrs;
       structdevice_attribute    * dev_attrs;
       structdriver_attribute    * drv_attrs;
 
       int           (*match)(struct device * dev, structdevice_driver * drv);
       int           (*hotplug) (struct device *dev, char**envp,
                                int num_envp, char *buffer, intbuffer_size);
       int           (*suspend)(struct device * dev,pm_message_t state);
       int           (*resume)(struct device * dev);
};

内核里的所有总线结构包括PCI,USB等都应该定义这个bus_type,name一定要定义,回调函数match可选择性定义。例如:

struct bus_type pci_bus_type = {

      .name       = "pci",

      .match      = pci_bus_match,

};

        回调函数的目的是决定所有挂载在该总线的设备device和驱动driver的匹配关系。device和driver的匹配根据他们的ID,在2.6.32内核以前可根据device的bus_id和driver的name是否匹配来判断驱动和设备的匹配关系,但后来的struct device结构里没有bus_id这个参数了,纠结啊。

当驱动注册到总线的时候,会遍历所有挂载在该总线的设备,看是否有匹配的device和driver。

/*************************************************************************************************************************

*************************************************************************************************************************

*************************************************************************************************************************/

现贴出一段代码关于总线的注册。

#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/string.h>
 
MODULE_AUTHOR("Xie");
MODULE_LICENSE("Dual BSD/GPL");
 
static char *Version = "$Revision: 1.0$";
 
static int my_match(struct device *dev,struct device_driver *driver)
{
       return!strncmp(dev->bus_id, driver->name, strlen(driver->name));
//在以后的内核版本,没有bus_id了。这个回调函数怎么写,可参照内核里的总线注册。
}
/*****************************************************
bus_type结构的填充,定义注册的总线的名字和回调函数。
******************************************************/
struct bus_type my_bus_type = {           
       .name= "my_bus",
       .match= my_match,
};
 
//当查看该属性文件时会执行这个函数
static ssize_t show_bus_version(structbus_type *bus, char *buf)
{
       returnsnprintf(buf, PAGE_SIZE, "%s\n", Version);
}
 
static BUS_ATTR(version, S_IRUGO,show_bus_version, NULL);
 
/********************************************************************
设置总线属性有两个步骤:
1、创建并初始化bus_attribute结构,使用宏BUS_ATTR
BUS_ATTR(_name, _mode, _show, _store)
该宏会定义一个名叫bus_attr__name(红色部分是固定的)的bus_attibute的结构,并且成员name设置为_name,文件权限mode设置为_mode,两个函数调用分别用show和store。
2、将bus_attibute添加到指定的总线上,使用以下调用:
      int bus_create_file(structbus_type *bus, struct bus_attribute *attr)
该函数失败时返回错误号。
一旦调用该函数,会就在指定bus总线的目录下新建一个名叫_name的文件,权限为_mode,当访问和修改该文件是会分别调用show和store函数调用。
 
*********************************************************************/
 
static int __init my_bus_init(void)
{
       intret;
       
      //总线的注册,这个函数会在/sys/bus/目录下创建相应的总线目录
       ret= bus_register(&my_bus_type);
       if(ret)
              returnret;
             
        
       if(bus_create_file(&my_bus_type, &bus_attr_version))
              printk(KERN_NOTICE"Fail to create version attribute!\n");
             
       returnret;
}
 
static void my_bus_exit(void)
{
       bus_unregister(&my_bus_type);
}
 
module_init(my_bus_init);
module_exit(my_bus_exit);




猜你喜欢

转载自blog.csdn.net/xieshangjian/article/details/9735193
今日推荐