6/26/2011 8:04:07 PM

 


6/26/2011 8:04:07 PM


新设备的添加

当一个新设备被加进来时,总线类型对象的drivers被遍历查找一个驱动程序支持该设备。查找时,设备ID必须匹配驱动程序支持的一个设备ID,比较设备ID的方法及格式是总线特定的。如果match函数发现匹配驱动程序时,结构device的成员driver成员会指向该驱动程序,同时,driver的probe回调函数被调用来验证是否支持硬件以及它是不是在工作状态。

依赖于probe函数的调用成功,设备注册到它所属的设备类。设备驱动程序仅属于一个设备类,并被设置在结构driver的成员devclass里。

结构bus_attribute是总线属性的描述结构,用于在文件系统sysfs中显示或修改总线属性,该结构列出如下:

struct bus_attribute {
 struct attribute attr;
 ssize_t (*show)(struct bus_type *, char * buf);
 ssize_t (*store)(struct bus_type *, const char * buf, size_t count);
};
使用下面两个声明可以声明一个总线属性:

static BUS_ATTR(debug,0644,show_debug,store_debug);
static bus_attribute bus_attr_debug;
使用下面两个函数可以从sysfs文件系统的bus目录下加入或移去总线属性。

int bus_create_file(struct bus_type *, struct bus_attribute *);
void bus_remove_file(struct bus_type *, struct bus_attribute *);

总线属性以及添加和移除

函数buses_init用于总线初始化,它在文件系统sysfs的/sys目录下加入bus子目录,对应生成名为bus的kobject对象和kset对象。

函数buses_init列出如下(在drivers/base/bus.c中):

static struct kset *bus_kset;
int __init buses_init(void)
{
    /*动态创建kset对象,并加入uevent事件操作函数集实例bus_uevent_ops,发出uevent事件。然后,将该对象加入到kobject体系和文件系统sysfs中*/
 bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL);
 if (!bus_kset)
  return -ENOMEM;
 return 0;
}
static struct kset_uevent_ops bus_uevent_ops = {
 .filter = bus_uevent_filter,  /*过滤掉非总线类型事件*/
};
static struct kobj_type bus_ktype = {
 .sysfs_ops = &bus_sysfs_ops,
};
 
static struct sysfs_ops bus_sysfs_ops = {
 .show = bus_attr_show,   /*调用内核对象属性的显示函数show*/
 .store = bus_attr_store, /*调用内核对象属性的存储函数store*/
};

总线初试化  在sys下创建bus节点


编写驱动程序时,一般最先初始化总线驱动程序。当总线驱动程序初始化时,它调用函数bus_register注册一个总线类型对象到kobject体系中,该对象包含了总线的各种功能函数指针。接着该函数注册它的子系统,如属于总线的设备和驱动程序。

例如:运行函数bus_register后,USB总线在/sys/bus中的内容显示如下:

^-^$ tree -L 1 /sys/bus/usb
/sys/bus/usb
|-- devices                        #设备目录
|-- drivers                        #驱动程序目录
|-- drivers_autoprobe              #属性文件,可显示,可存储
|-- drivers_probe                  #属性文件,只有存储
`-- uevent                         #属性文件,只有存储
2 directories, 3 files
 
^-^$ ls –l /sys/bus/usb
total 0
drwxr-xr-x 2 root root    0 2008-09-23 17:23 devices
drwxr-xr-x 8 root root    0 2008-09-23 17:23 drivers
-rw-r--r-- 1 root root 4096 2008-09-23 17:34 drivers_autoprobe
--w------- 1 root root 4096 2008-09-23 17:34 drivers_probe
--w------- 1 root root 4096 2008-09-23 18:10 uevent
 
^-^$ cat /sys/bus/usb/drivers_autoprobe
1
struct notifier_block {
 int (*notifier_call)(struct notifier_block *, unsigned long, void *);
 struct notifier_block *next;
 int priority;
};

一个通知链

struct blocking_notifier_head {
 struct rw_semaphore rwsem;
 struct notifier_block *head;
};

通知链上有自己的信号锁

struct blocking_notifier_head {
 struct rw_semaphore rwsem;
 struct notifier_block *head;
};

#define BLOCKING_INIT_NOTIFIER_HEAD(name) do { /
  init_rwsem(&(name)->rwsem); /
  (name)->head = NULL;  /
 } while (0)
 
初试化了这个通知队列

struct kset {
 struct subsystem * subsys;
 struct kobj_type * ktype;
 struct list_head list;
 spinlock_t  list_lock;
 struct kobject  kobj;
 struct kset_uevent_ops * uevent_ops;
};

kset有自己的kobject

将总线名设置到kset的名字中

函数bus_create_file用于为一个总线对象创建属性文件,每个属性文件对应一个总线属性结构,该结构中含有文件操作函数的指针。该函数列出如下:

int bus_create_file(struct bus_type *bus, struct bus_attribute *attr)
{
 int error;
 if (bus_get(bus)) {
  error = sysfs_create_file(&bus->p->subsys.kobj, &attr->attr);
  bus_put(bus);
 } else
  error = -EINVAL;
 return error;
}
为总线对象创建属性

struct klist {
 spinlock_t  k_lock;
 struct list_head k_list;
 void   (*get)(struct klist_node *);
 void   (*put)(struct klist_node *);
};


函数klist_init 初始化一个结构klist实例,该链表用于链接kset容纳的内核对象,通过该内核对象可以找到它对象的设备结构。其列出如下:

void klist_init(struct klist *k, void (*get)(struct klist_node *),
  void (*put)(struct klist_node *))
{
 INIT_LIST_HEAD(&k->k_list);
 spin_lock_init(&k->k_lock);
 k->get = get;    /*函数get用于将引用计数加1*/
 k->put = put;    /*函数put用于将引用计数减1*/
}

初试化klist 实例

函数add_probe_files用于在sysfs中创建属性文件drivers_probe和drivers_autoprobe,其列出如下:

static int add_probe_files(struct bus_type *bus)
{
 int retval;
    /*创建属性文件drivers_probe*/
 retval = bus_create_file(bus, &bus_attr_drivers_probe);
 if (retval)
  goto out;
    /*创建属性文件drivers_autoprobe*/
 retval = bus_create_file(bus, &bus_attr_drivers_autoprobe);
 if (retval)
  bus_remove_file(bus, &bus_attr_drivers_probe);
out:
 return retval;
}

添加驱动探测和驱动自动探测


下面的宏声明了总线属性实例drivers_probe和drivers_autoprobe:

/* 宏定义格式为:BUS_ATTR(属性文件名,操作模式,显示函数,存储函数) */
static BUS_ATTR(drivers_probe, S_IWUSR, NULL, store_drivers_probe);
static BUS_ATTR(drivers_autoprobe, S_IWUSR | S_IRUGO,
  show_drivers_autoprobe, store_drivers_autoprobe);
  
  总线属性
  
  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值