• Linux设备管理(三)_总线设备的挂接


    扒完了字符设备,我们来看看平台总线设备,平台总线是Linux中的一种虚拟总线,我们知道,总线+设备+驱动是Linux驱动模型的三大组件,设计这样的模型就是将驱动代码和设备信息相分离,对于稍微复杂一点的驱动,都要使用这种结构,我在"Linux设备管理(一)_kobject, kset,kobj_type分析"一文中提到过将一个设备或驱动挂载到总线就是将这个设备或驱动的kobject挂接到相应的总线kset下的设备kset或驱动kset中,本文就扒一扒内核中注册一个平台设备的源码,验证一下这个说法。整体的调用关系是:platform_device_register()->platform_device_add()->device_add()->kobject_add()

    platform_device_register()

    在平台设备编程模型中,我们将我们数据封装到一个platform_device结构中后,就可以将设备对象注册到平台总线上

    platform_device_register()
    --461--> device_initialize()初始化平台设备的父类device结构
    --463--> platform_device_add(pdev)将设备挂接到总线设备链表,即注册

    //drivers/base/platform.c
    
      37 struct device platform_bus = {
      38         .init_name      = "platform",
      39 };
    
     459 int platform_device_register(struct platform_device *pdev)  
     460 {
     461         device_initialize(&pdev->dev);		
     462         arch_setup_pdev_archdata(pdev);
     463         return platform_device_add(pdev);
     464 }
    

    device_initialize()主要是对平台设备的父类device结构进行一些初始化工作

    device_initialize()
    --702-->dev->kobj.kset = devices_kset;使用全局的devices_kset对象初始化设备的kset
    --703-->kobject_init(&dev->kobj, &device_ktype);使用全局的device_ktype对象初始化设备的kobj对应的kobj_type
    --704-->INIT_LIST_HEAD(&dev->dma_pools);初始化设备list_head结构,用于后序的链接

    //drivers/base/core.c
     700 void device_initialize(struct device *dev)   
     701 {
     702         dev->kobj.kset = devices_kset;
     703         kobject_init(&dev->kobj, &device_ktype);
     704         INIT_LIST_HEAD(&dev->dma_pools);
    	     ...
     714 }
    

    platform_device_add()

    这个函数才开始真正把平台设备对象挂接到平台总线上

    platform_device_add()
    --353-->使新的设备的kobject->parent指向全局的平台设备kobject对象
    --355-->使设备的总线类型指针指向平台总线对象
    --403-->将设备挂接到相应的总线

    //drivers/base/platform.c
     345 int platform_device_add(struct platform_device *pdev)
     346 {
     347         int i, ret;
    	     ...
     352         if (!pdev->dev.parent)
     353                 pdev->dev.parent = &platform_bus;			//挂到平台总线
     354 
     355         pdev->dev.bus = &platform_bus_type;
    	     ...                                                      
     403         ret = device_add(&pdev->dev);
     404         if (ret == 0)
     405                 return ret;
    	     ...
     421 }
    

    device_add()

    之前的工作已经准备好了一个平台设备对象,接下来的工作就是将这个设备挂接到总线上,注册任务就算完成了。

    device_add()
    --1074-->将设备的kobj挂接到之前填充好的parent的链表中,即平台总线的链表。

    //drivers/base/platform.c
    1025 int device_add(struct device *dev)
    1026 {
    1027         struct device *parent = NULL;
    1028         struct kobject *kobj;
    1029         struct class_interface *class_intf;
    1030         int error = -EINVAL;
    1031                                     
    1032         dev = get_device(dev);
    	     ...
    1071 
    1072         /* first, register with generic layer. */
    1073         /* we require the name to be set before, and pass NULL */
    1074         error = kobject_add(&dev->kobj, dev->kobj.parent, NULL);
    	     ...
    1138 done:
    1139         put_device(dev);
    1140         return error;
    
  • 相关阅读:
    数据汇总计算和分析的反思
    排名算法计算
    仿Spring读取配置文件实现方案
    xml 配置文件规范 校验
    批量插入数据(基于Mybatis的实现-Oracle)
    shallow copy 和 deep copy 的示例
    引用对象的使用和易产生bug的示例
    codis安装手册
    Redis安装手册
    map和list遍历基础
  • 原文地址:https://www.cnblogs.com/xiaojiang1025/p/6201290.html
Copyright © 2020-2023  润新知