总线

Linux设备模型总线、设备和驱动

1.总线

总线使用结构structbus_type描述,这个结构类型定义在include/linux/device.h

51struct bus_type {

52 const char *name;

53 struct bus_attribute *bus_attrs;

54 struct device_attribute *dev_attrs;

55 struct driver_attribute *drv_attrs;

56

57 int (*match)(struct device *dev, struct device_driver *drv);

58 int (*uevent)(struct device *dev, struct kobj_uevent_env*env);

59 int (*probe)(struct device *dev);

60 int (*remove)(struct device *dev);

61 void (*shutdown)(struct device *dev);

62

63 int (*suspend)(struct device *dev, pm_message_t state);

64 int (*resume)(struct device *dev);

65

66 const struct dev_pm_ops *pm;

67

68 struct bus_type_private *p;

69};

使用bus_registerbus_unregister向系统注册和注销一条总线,在看这两个函数之前,先看structbus_type_private结构,这个结构类型定义在drivers/base/base.h

19struct bus_type_private {

20 struct kset subsys;

21 struct kset *drivers_kset;

22 struct kset *devices_kset;

23 struct klist klist_devices;

24 struct klist klist_drivers;

25 struct blocking_notifier_head bus_notifier;

26 unsigned int drivers_autoprobe:1;

27 struct bus_type *bus;

28};

总线有两个链表,一个是设备的链表,一个是驱动的链表,就是这里的klist_devices

klist_drivers。先看总线的注册函数bus_register

871/**

872 * bus_register - register a bus with the system.

873 * @bus: bus.

874 *

875 * Once we have that, we registered the bus with the kobject

876 * infrastructure, then register the children subsystems it has:

877 * the devices and drivers that belong to the bus.

878 */

879int bus_register(struct bus_type *bus)

880{

881 int retval;

882 struct bus_type_private *priv;

883

884 priv = kzalloc(sizeof(struct bus_type_private), GFP_KERNEL);

885 if (!priv)

886 return -ENOMEM;

887

888 priv->bus = bus;

889 bus->p = priv;

890

891 BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier);

892

893 retval = kobject_set_name(&priv->subsys.kobj, "%s",bus->name);

894 if (retval)

895 goto out;

896

897 priv->subsys.kobj.kset = bus_kset;

898 priv->subsys.kobj.ktype = &bus_ktype;

899 priv->drivers_autoprobe = 1;

900

901 retval = kset_register(&priv->subsys);

902 if (retval)

903 goto out;

904

905 retval = bus_create_file(bus, &bus_attr_uevent);

906 if (retval)

907 goto bus_uevent_fail;

908

909 priv->devices_kset = kset_create_and_add("devices",NULL,

910 &priv->subsys.kobj);

911 if (!priv->devices_kset) {

912 retval = -ENOMEM;

913 goto bus_devices_fail;

914 }

915

916 priv->drivers_kset = kset_create_and_add("drivers",NULL,

917 &priv->subsys.kobj);

918 if (!priv->drivers_kset) {

919 retval = -ENOMEM;

920 goto bus_drivers_fail;

921 }

922

923 klist_init(&priv->klist_devices, klist_devices_get,klist_devices_put);

924 klist_init(&priv->klist_drivers, NULL, NULL);

925

926 retval = add_probe_files(bus);

927 if (retval)

928 goto bus_probe_files_fail;

929

930 retval = bus_add_attrs(bus);

931 if (retval)

932 goto bus_attrs_fail;

933

934 pr_debug("bus: '%s': registered\n", bus->name);

935 return 0;

936

937bus_attrs_fail:

938 remove_probe_files(bus);

939bus_probe_files_fail:

940 kset_unregister(bus->p->drivers_kset);

941bus_drivers_fail:

942 kset_unregister(bus->p->devices_kset);

943bus_devices_fail:

944 bus_remove_file(bus, &bus_attr_uevent);

945bus_uevent_fail:

946 kset_unregister(&bus->p->subsys);

947 kfree(bus->p);

948out:

949 bus->p = NULL;

950 return retval;

951}

952EXPORT_SYMBOL_GPL(bus_register);

在这里我们只关注总线注册时初始化了两个链表,一个是设备链表,另一是驱动链表。至于kobject,kset以及sysfs文件系统是如何建立起来的,将在以后介绍。这里只需要理解总线、设备和驱动它们三者的关系,设备是如何绑定一款驱动的。在这里,我想说的是,如果你什么都想弄懂,也许到头来你什么也没有弄懂。

总线注销函数bus_unregister

954/**

955 * bus_unregister - remove a bus from the system

956 * @bus: bus.

957 *

958 * Unregister the child subsystems and the bus itself.

959 * Finally, we call bus_put() to release the refcount

960 */

961void bus_unregister(struct bus_type *bus)

962{

963 pr_debug("bus: '%s': unregistering\n", bus->name);

964 bus_remove_attrs(bus);

965 remove_probe_files(bus);

966 kset_unregister(bus->p->drivers_kset);

967 kset_unregister(bus->p->devices_kset);

968 bus_remove_file(bus, &bus_attr_uevent);

969 kset_unregister(&bus->p->subsys);

970 kfree(bus->p);

971 bus->p = NULL;

972}

973EXPORT_SYMBOL_GPL(bus_unregister);

posted @ 2011-12-22 15:57  移动应用开发  阅读(303)  评论(0编辑  收藏  举报