设为首页 收藏本站
查看: 694|回复: 0

[经验分享] Linux驱动模型解析bus之platform bus

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2017-11-17 23:26:37 | 显示全部楼层 |阅读模式
  这是内核启动之后要调用的驱动模型的开始代码:



drivers/base/init.c
/**
* driver_init - initialize driver model.
*
* Call the driver model init functions to initialize their
* subsystems. Called early from init/main.c.
*/
void __init driver_init(void)
{
/* These are the core pieces */
devices_init(); //  /sys/devices
buses_init(); // /sys/bus
classes_init(); // /sys/class
firmware_init();
hypervisor_init();
/* These are also core pieces, but must come after the
* core core pieces.
*/
platform_bus_init();
system_bus_init();
cpu_dev_init();
memory_dev_init();
}
  且看platform_bus_init



drivers/base/platform.c


struct device platform_bus = {
.bus_id         = "platform",
};



struct bus_type platform_bus_type = {
.name           = "platform",
.dev_attrs      = platform_dev_attrs,
.match          = platform_match,
.uevent         = platform_uevent,
.pm             = PLATFORM_PM_OPS_PTR,
};

int __init platform_bus_init(void)
{
int error;
     /* /sys/devices/platform (this platform is bus_id's value) */
    error = device_register(&platform_bus);
     if (error)
        return error;

      /* /sys/bus/platform (this platform is the value of bus_type's name field) */
      error = bus_register(&platform_bus_type);

     if (error)
         device_unregister(&platform_bus);

     return error;
}
  这里讲述 bus_register(&platform_bus_type):



/**
* struct bus_type_private - structure to hold the private to the driver core portions of the bus_type structure.
*
* @subsys - the struct kset that defines this bus.  This is the main kobject
* @drivers_kset - the list of drivers associated with this bus
* @devices_kset - the list of devices associated with this bus
* @klist_devices - the klist to iterate over the @devices_kset
* @klist_drivers - the klist to iterate over the @drivers_kset
* @bus_notifier - the bus notifier list for anything that cares about things
* on this bus.
* @bus - pointer back to the struct bus_type that this structure is associated
* with.
*
* This structure is the one that is the actual kobject allowing struct
* bus_type to be statically allocated safely.  Nothing outside of the driver
* core should ever touch these fields.
*/
struct bus_type_private {
struct kset subsys;
struct kset *drivers_kset;
struct kset *devices_kset;
struct klist klist_devices;
struct klist klist_drivers;
struct blocking_notifier_head bus_notifier;
unsigned int drivers_autoprobe:1;
struct bus_type *bus;
};


int bus_register(struct bus_type *bus)                                          
{                                                                              
int retval;                                                            
struct bus_type_private *priv;                                          
priv = kzalloc(sizeof(struct bus_type_private), GFP_KERNEL);            
if (!priv)                                                              
return -ENOMEM;                                                
priv->bus = bus;                                                        
bus->p = priv;                                                         
BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier);                       
retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name);         
if (retval)                                                            
goto out;                                                      
priv->subsys.kobj.kset = bus_kset;                                      
priv->subsys.kobj.ktype = &bus_ktype;                                   
priv->drivers_autoprobe = 1;                                            
retval = kset_register(&priv->subsys);                                 
if (retval)                                                            
goto out;                                                      
retval = bus_create_file(bus, &bus_attr_uevent);                        
if (retval)                                                            
goto bus_uevent_fail;                                          
priv->devices_kset = kset_create_and_add("devices", NULL,               
&priv->subsys.kobj);   
if (!priv->devices_kset) {                                             
retval = -ENOMEM;                                               
goto bus_devices_fail;                                          
}                                                                       
priv->drivers_kset = kset_create_and_add("drivers", NULL,               
&priv->subsys.kobj);           
if (!priv->drivers_kset) {                                             
retval = -ENOMEM;                                               
goto bus_drivers_fail;                                          
}                                                                       
klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put);
klist_init(&priv->klist_drivers, NULL, NULL);                           
retval = add_probe_files(bus);                                          
if (retval)                                                            
goto bus_probe_files_fail;                                      
retval = bus_add_attrs(bus);                                            
if (retval)                                                            
goto bus_attrs_fail;                                            
pr_debug("bus: '%s': registered\n", bus->name);                        
return 0;
  struct bus_type_private *priv指向struct bus_type,这里会显示/sys/bus/platform
  retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name);
  priv->subsys.kobj.kset = bus_kset;
  retval = kset_register(&priv->subsys);// subsys is a kset.
  这里显示/sys/bus/platform/devices
  priv->devices_kset = kset_create_and_add("devices", NULL, &priv->subsys.kobj);
  这里显示/sys/bus/platform/drivers
  priv->drivers_kset = kset_create_and_add("drivers", NULL, &priv->subsys.kobj);
  kset_create_and_add--->kset_register



/**                                                                                
* kset_register - initialize and add a kset.                                      
* @k: kset.                                                                       
*/                                                                                
int kset_register(struct kset *k)                                                  
{                                                                                 
int err;                                                                  
if (!k)                                                                    
return -EINVAL;                                                   
kset_init(k); // INIT_LIST_HEAD(&k->kobj->entry); INIT_LIST_HEAD(&k->list);                                                            
err = kobject_add_internal(&k->kobj);                                      
if (err)                                                                  
return err;                                                        
kobject_uevent(&k->kobj, KOBJ_ADD);                                                                                                      
return 0;                                                                  
}


static int kobject_add_internal(struct kobject *kobj)                           
{   
kobj_kset_join(kobj);
error = create_dir(kobj); // /sys/bus/platform
}


/* add the kobject to its kset's list */                                       
static void kobj_kset_join(struct kobject *kobj)                                                                                                
{                                                                              
if (!kobj->kset)                                                        
return;                                                         
kset_get(kobj->kset);                                                   
spin_lock(&kobj->kset->list_lock);                                      
list_add_tail(&kobj->entry, &kobj->kset->list);                        
spin_unlock(&kobj->kset->list_lock);                                    
}

  If a kset is associated with a kobject, then the parent for the kobject can be set to
NULL in the call to kobject_add() and then the kobject's parent will be the kset itself.
  确切的说是kobject's parent赋值为kobject关联的kset's kobjcect

struct kobject {                                                                  
const char              *name;                                             
struct list_head        entry;                                             
struct kobject          *parent;                                          
struct kset             *kset;                                             
struct kobj_type        *ktype;                                            
struct sysfs_dirent     *sd;                                               
struct kref             kref;                                             
unsigned int state_initialized:1;                                          
unsigned int state_in_sysfs:1;                                             
unsigned int state_add_uevent_sent:1;                                                                                                   
unsigned int state_remove_uevent_sent:1;                                   
};


*                                                                              
* A kset defines a group of kobjects.  They can be individually               
* different "types" but overall these kobjects all want to be grouped         
* together and operated on in the same manner.  ksets are used to              
* define the attribute callbacks and other common events that happen to        
* a kobject.                                                                  
*                                                                              
* @list: the list of all kobjects for this kset                                
* @list_lock: a lock for iterating over the kobjects                           
* @kobj: the embedded kobject for this kset (recursion, isn't it fun...)      
* @uevent_ops: the set of uevent operations for this kset.  These are         
* called whenever a kobject has something happen to it so that the kset           
* can add new environment variables, or filter out the uevents if so              
* desired.                                                                        
*/                                                                                
struct kset {                                                                                                                                    
struct list_head list;                                                  
spinlock_t list_lock;                                                      
struct kobject kobj;                                                      
struct kset_uevent_ops *uevent_ops;                                       
};


struct list_head {                                                                                                                              
struct list_head *next, *prev;                                          
};
  从list_add_tail(&kobj->entry, &kobj->kset->list); 调用中,我们一下子就明白了,

bus =&struct bus_type platform_bus_type;
bus->p->->subsys.kobj.kset = bus_kset;// bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL); 创建了bus的kset显示/sys/bus
所以&kobj->kset->list就是bus_kset->list,list_add_tail就是把bus->p->->subsys.kobj.entry加入到bus_kset->list链表中。
bus_kset包含不同bus的subsys的kset,而代表subsys的kset的就是这个kset中的kobject。所以把kobjetct的entry加入到表示kset的kset->list中。
换句话说,struct kset这个集合包含的内容由其嵌入的struct list_head list来表示,这个struct kset自身由其嵌入的struct kobject kobj来表示。
所以这里就是把platform这个kset加入到bus这个kset中。用户空间的视图表示就是/sys/bus/platform。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-408070-1-1.html 上篇帖子: Linux系列—策略路由、ip rule、ip route 下篇帖子: Linux学习-逻辑滚动条管理员 (Logical Volume Manager)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表