版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
簡介作者:hjlin內(nèi)核版本:2.6.29設(shè)備驅(qū)動模型框架是linux驅(qū)動編程的基礎(chǔ)。它通過kobject,kset,ktype等底層數(shù)據(jù)結(jié)構(gòu)將bus_type,device,device_driver等高層數(shù)據(jù)結(jié)構(gòu)組織起來,形成一個層次、分類清晰的驅(qū)動模型。優(yōu)點如下:代碼重用。將對象抽象為總線、驅(qū)動、設(shè)備三種,各司其職。同一總線的多個驅(qū)動使用相同的總線對象。同一驅(qū)動可以關(guān)聯(lián)驅(qū)動多個設(shè)備。通過sysfs文件系統(tǒng),清晰了展示內(nèi)核驅(qū)動模型中的層次關(guān)系。同時sysfs文件系統(tǒng)還提供了方便的同用戶控件交互的接口??蚣躶tructkset.t_opsitructattributestructsysfs_ops-constchar*name-structmodule*owner-mode_tmodeTtv+int(*filter)(structkset*kset,structkobject*kobj)()+constchar*(*name)(structkset*kset,structkobject*kobj)()+int(*uevent)(structkset*kset,structko^&ct*kobj,structkobj_uevent_env*env)()+ssize_t(*show)(structkobject*,structattribute*,char*)()+ssize_t(*store)(structkobject*,-constchar*name-structmodule*owner-mode_tmodeTtvuctkobjectstructkset-structlist_headlist-spinlock_tlist_lock-structkobjectkobj-structkset_uevent_ops*uevent_ops■>-constchar*name-structstructkset-structlist_headlist-spinlock_tlist_lock-structkobjectkobj-structkset_uevent_ops*uevent_ops■>-constchar*name-structlist_headentry-structkobject*parent-structkset*kset-structkobj_type*ktype-structsysfs_dirent*sd-structkrefkref-uintstate_initialized:1-uintstate_in_sysfs:1-uintstate_add_uevent_sent:1-unitstate_remove_uevent_sent:1-uintuevent_suppress:1structkobj_*ype-structsysfs_ops*sysfs_ops-structattribute**default_attrs+void(*release)(structkobject*kobj)()structbus_typestructdevicestructdevice_driver-constchar*name-structbus_attribute*bus_attrs-structdevice_attribute*dev_attrs-structdriver_attribute*drv_attrs-conststructdev_pm_ops*pm-structbus_type_private*p+int(*match)(structdevice*dev,structdevice_driver*drv)()+int(*uevent)(structdevice*dev,structkobj_uevent_env*env)()+int(*probe)(structdevice*dev)()+int(*remove)(structdevice*dev)()+void(*shutdown)(structdevice*dev)()+int(*suspend)(structdevice*dev,pmmessagetstate)()+int(*resume)(structdevice*dev)()-structdevice*parent-structdevice_private*p-structkobjectkobj-charbus_id[BUS_ID_SIZE]-constchar*init_name-structdevice_type*type-structsemaphoresem-structbus_type*bus-structdevice_driver*driver-void*platform_data-structdev_pm_infopower-dev_tdevt-spinlock_tdevres_lock-structlist_headdevres_head-structklist_nodeknode_class-structclass*class-conststructattribute_group**groups+void(*release)(structdevice*dev)()-constchar*name-structbus_type*bus-structmodule*owner-constchar*mod_name-boolsuppress_bind_attrs-conststructattribute_group**groups-conststructdev_pm_ops*pm-structdriver_private*p+int(*probe)(structdevice*dev)()+int(*remove)(structdevice*dev)()+vod(*shutdown)(structdevice*dev)()+int(*suspend)(structdevice*dev,pmmessagetstate)()+int(*resume)(structdevice*dev)()structbus_type_private-structksetsubsys-structkset*drivers_kset-structkset-structksetsubsys-structkset*drivers_kset-structkset*devices_kset-structklistklist_devices-structklistklist_drivers-structblocking_notifier_headbus_notifier-unsignedintdrivers_autoprobe:1-structbus_type*busstructdevice_privateuctdriver_privatestructklistklist_childrenstructklist_nodeknode_parentstructklist_nodekonde_driverstructklist_nodeknode_busvoid*driver_datastructdevice,device-structkobjectkobj-structklistklist_devices-structklist_nodeknode_bus-structmodule_kobject*mkobj-structdevice_driver*driverbus_at!ribule-structattributeattrstructdriver_attribute-structattributeattr+ssize_t(*show)+ssize_t(*show)(structbus_type*bus,char*buf)()+ssize_t(*store)(structbus_type*bus,constchar*buf,size_tcount)()+ssize_t(*show)(structdevice_driver*driver,char*buf)()+ssize_t(*store)(structdevice_driver*driver,constchar*buf,size_tcount)()structdevic?_attribut?-structattributeattr+ssize_t(*show)(structdevice*dev,char*buf)()+ssize_t(*store)(structdevice*dev,constchar*buf,size_tcount)()數(shù)據(jù)結(jié)構(gòu)KobjectKobject是代表驅(qū)動模型中的一個對象??偩€、驅(qū)動、設(shè)備都繼承了它。(在結(jié)構(gòu)體中包含kobject)。每個kobject在sysfs中表現(xiàn)為一個目錄。每個kobject都有一個parentkobject和所屬的kset。Kset就是kobject所屬的kset,通過kset的鏈表可以找到所有屬于它的kobject。這些kobject進(jìn)行uevent操作時,都會調(diào)用所屬的kset的uevent_ops方法。父kobj,用于表示kobject之間或者kobject和kset,kset之間的在sysfs中的目錄結(jié)構(gòu)關(guān)系。如果父kobj不存在,并且所屬的kset存在的話,則父kobj就是設(shè)置為所屬的kset的內(nèi)嵌kobj。因此,注冊設(shè)備、驅(qū)動或者總線的時候如果不指定parentkobj的話,父kobj則會設(shè)置為所屬的kset的kobj。(todo:最好畫圖表示關(guān)系)structkobject(constchar*k_name;structkrefkref;structlist_headentry;〃連入到所屬的kset的liststructkobject*parent;//父kobj,如果沒有父kobj,則使用所屬的kset內(nèi)嵌kobjstructkset*kset;//所屬的kset(如果有的話)structkobj_type*ktype;//所屬的ktype,如果所屬的kset也有ktype,則用kset的ktype。structsysfs_dirent};*sd;Kest通過kset可以將kobject組織成一顆層次樹。structkset(structlist_headlist;//屬于該kset的kobj鏈表spinlock_tlist_lock;structkobjectkobj;〃內(nèi)嵌的kobjectstructkset_uevent__ops*uevent_ops;//uevent方法,對所有該kset下的kobj進(jìn)彳亍uevent操作時的方法。};structkset_uevent_ops(int(*filter)(structkset*kset,structkobject*kobj);constchar*(*name)(structkset*kset,structkobject*kobj);int(*uevent)(structkset*kset,structkobject*kobj,structkobj_uevent_env*env);};kobj_typestructkobj_type(void(*release)(structkobject*kobj);//kobject釋放時調(diào)用structsysfs_ops*sysfs_ops;/臊縱默認(rèn)屬性的讀寫方法structattribute**default_attrs;〃相應(yīng)的kobject(kset)的默認(rèn)屬性。對應(yīng)于sysfs下的文件。};structsysfs_ops(ssize_t(*show)(structkobject*,structattribute*,char*);ssize_t(*store)(structkobject*,structattribute*,constchar*,size_t);J;structattribute(constchar*name;structmodule*owner;mode_t};mode;bus_type代表一個總線。對應(yīng)/sys/bus下的一個目錄。管理相應(yīng)總線下的所有驅(qū)動和設(shè)備。structbus_type(constchar*name;〃總線名稱structbus_attribute*bus_attrs;〃該總線目錄下的屬性文件以及相應(yīng)的訪問方法structdevice_attribute*dev_attrs;〃該總線設(shè)備子目錄下的屬性文件以及相應(yīng)的訪問方法structdriver_attribute*drv_attrs;〃該總線驅(qū)動子目錄下的屬性文件以及相應(yīng)的訪問方法int(*match)(structdevice*dev,structdevice_driver*drv);〃驅(qū)動模型進(jìn)行驅(qū)動和設(shè)備的匹配時調(diào)用int(*uevent)(structdevice*dev,structkobj_uevent_env*env);//ueven「方法int(*probe)(structdevice*dev);//match成功之后會調(diào)用。一般該probe方法內(nèi)部會調(diào)用相應(yīng)的device_driver的probe方法int(*remove)(structdevice*dev);void(*shutdown)(structdevice*dev);int(*suspend)(structdevice*dev,pm_message_tstate);int(*suspend_late)(structdevice*dev,pm_message_tstate);int(*resume_early)(structdevice*dev);int(*resume)(structdevice*dev);structdev_pm_ops*pm;structbus_type_private*p;};structbus_type_private(structksetsubsys;〃總線本身目錄structkset*drivers_kset;〃驅(qū)動目錄structkset*devices_kset;〃設(shè)備目錄structklistklist_devices;structklistklist_drivers;structblocking_notifier_headbus_notifier;unsignedintdrivers_autoprobe:1;structbus_type*bus;};Devicestructdevice(structdevice*parent;〃父設(shè)備structdevice_private*p;structkobjectkobj;charbus_id[BUS_ID_SIZE];constchar*init_name;/*initialnameofthedevice*/structdevice_type*type;structsemaphoresem;/*semaphoretosynchronizecallsto*itsdriver.*/structbus_type*bus;/*typeofbusdeviceison*/structdevice_driver*driver;/*whichdriverhasallocatedthisdevice*/void*platform_data;/*Platformspecificdata,devicecoredoesn'ttouchit*/structdev_pm_infopower;#ifdefCONFIG_NUMAintnuma_node;/*NUMAnodethisdeviceiscloseto*/#endifu64*dma_mask;/*dmamask(ifdma'abledevice)*/u64coherent_dma_mask;/*Likedma_mask,butforalloc_coherentmappingsasnotallhardwaresupports64bitaddressesforconsistentallocationssuchdescriptors.*/structdevice_dma_parameters*dma_parms;
structlist_headdma_pools;/*dmapools(ifdma'ble)*/structdma_coherent_mem*dma_mem;/*internalforcoherentmemoverride*//*archspecificadditions*/structdev_archdataarchdata;dev_tdevt;/*dev_t,createsthesysfs"dev"*/spinlock_tstructlist_headdevres_lock;devres_head;structklist_nodestructclassknode_class;*class;conststructattribute_group**groups;/*optionalgroups*/void(*release)(structdevice*dev);};structdevice_private(structklistklist_children;//子設(shè)備的鏈表structklist_nodeknode_parent;//作為父設(shè)備的字設(shè)備鏈表(klist_children)的一個節(jié)點structklist_nodeknode_driver;//(作為所屬驅(qū)動的設(shè)備鏈表(klist_devices)的一個節(jié)點structklist_nodeknode_bus;//作為所屬總線的設(shè)備鏈表(klist_devices)的一個節(jié)點void*driver_data;structdevice*device;};device_driverstructdevice_driver(constchar*name;structbus_type*bus;structmodule*owner;constchar*mod_name;/*usedforbuilt-inmodules*/int(*probe)(structdevice*dev);int(*remove)(structdevice*dev);void(^shutdown)(structdevice*dev);int(*suspend)(structdevice*dev,pm_message_tstate);int(*resume)(structdevice*dev);structattribute_group**groups;structdev_pm_ops*pm;structdriver_private*p;};structdriver_private(structkobjectkobj;structklistklist_devices;//所驅(qū)動的設(shè)備的鏈表structklist_nodeknode_bus;//作為所屬總線的驅(qū)動鏈表(klist_drivers)的一個節(jié)點structmodule_kobject*mkobj;structdevice_driver*driver;};基礎(chǔ)方法kobject_add_internalstaticintkobject_add_internal(structkobject*kobj)將kobject添加到設(shè)備驅(qū)動模型中。主要設(shè)置父kobj以及將自己添加到所屬的kset的list中,并且在sysfs中創(chuàng)建目錄。父kobj存在否kobject_add_internal()Endkobject_get(kobj->parent)獲取父kobj并增加引用計數(shù)create_dir(kobj)在sysfs中創(chuàng)建kobj相應(yīng)目錄設(shè)置父kobj為所屬的kset的內(nèi)嵌kobj將kobj加入到所屬kset的kobj父kobj存在否kobject_add_internal()Endkobject_get(kobj->parent)獲取父kobj并增加引用計數(shù)create_dir(kobj)在sysfs中創(chuàng)建kobj相應(yīng)目錄設(shè)置父kobj為所屬的kset的內(nèi)嵌kobj將kobj加入到所屬kset的kobj鏈表中Kobj->entry+>kset->listkobject_uevent(structkobject*kobj,enumkobject_actionactiirEnd通過EndNetlink_broadcast(uevent_s
ock,..)發(fā)送出去call_usermodehelper調(diào)用用戶進(jìn)程。一般是/sbin/hotplug,手機(jī)上一般沒有核心方法注冊總線bus_register(structbus_type*bus)注冊一個總線到驅(qū)動模型中。在sysfs中的結(jié)構(gòu)是:/sys/bus/platform/|--devices||--...|--drivers||--.|--drivers_autoprobe|--drivers_probe'--uevent
BUS_ATTR(uevent,S_IWUSR,NULL,bus_uevent_store);屬性的寫方法直接調(diào)用kobject_uevent發(fā)送事件——分配Bus.p的空間bus_type_privateBUS_ATTR(uevent,S_IWUSR,NULL,bus_uevent_store);屬性的寫方法直接調(diào)用kobject_uevent發(fā)送事件——分配Bus.p的空間bus_type_private設(shè)置Bus內(nèi)建的kobject:name等于所屬kset為&bus_ksetKtype等于&busktypeIPus)Bus_register(Structbus_1-*bBus內(nèi)建kobj的所屬kset是bus_kset,bus_kset是一個kset,相對于/sys/Bus-目錄。由于bus的內(nèi)建kobj沒有父kobj。所以Bus_kset將做為它的父kobj,因此內(nèi)建的kobj的,9,目錄為/sys/bus/xxx_busintretval;structbus_type_private*priv;//初始化private數(shù)據(jù)結(jié)構(gòu)priv=kzalloc(sizeof(structbus_type_private),GFP_KERNEL);if(!priv)return-ENOMEM;priv->bus=bus;bus->p=priv;BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier);〃設(shè)置kobject名稱。即/bus/sys/下的目錄名稱retval=kobject_set_name(&priv->subsys.kobj,"%s",bus->name);if(retval)gotoout;priv->subsys.kobj.kset=bus_kset;priv->subsys.kobj.ktype=&bus_ktype;priv->drivers_autoprobe=1;//注冊內(nèi)嵌ksetretval=kset_register(&priv->subsys);if(retval)gotoout;retval=bus_create_file(bus,&bus_attr_uevent);if(retval)gotobus_uevent_fail;〃創(chuàng)建設(shè)備kset并且注冊priv->devices_kset=kset_create_and_add("devices”,NULL,&priv->subsys.kobj);if(!priv->devices_kset)(retval=-ENOMEM;gotobus_devices_fail;}〃創(chuàng)建驅(qū)動kset并且注冊priv->drivers_kset=kset_create_and_add("drivers”,NULL,&priv->subsys.kobj);if(!priv->drivers_kset)(retval=-ENOMEM;gotobus_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)gotobus_probe_files_fail;retval=bus_add_attrs(bus);if(retval)gotobus_attrs_fail;pr_debug("bus:'%s':registered",bus->name);return0;000out:returnretval;}注冊設(shè)備主要有兩個工作,初始化設(shè)備,將設(shè)備掛接到設(shè)備驅(qū)動模型中并且處理uevent事件和自動
匹配設(shè)備驅(qū)動。在platform.c的platform_bus_init方法中使用了device_register(&platform_bus),注冊了一個設(shè)備,該設(shè)備的sys目錄為/sys/devices/platform/。但是一般情況下,內(nèi)核對于不同的總線會提供不同的封裝方法在內(nèi)部調(diào)用device_register來注冊設(shè)備。比如說platform_register_device,并且在platform_register_device方法中設(shè)置了device的父匹配設(shè)備驅(qū)動。在platform.c的platform_bus_init方法中使用了device_register(&platform_bus),注冊了一個設(shè)備,該設(shè)備的sys目錄為/sys/devices/platform/。但是一般情況下,內(nèi)核對于不同的總線會提供不同的封裝方法在內(nèi)部調(diào)用device_register來注冊設(shè)備。比如說platform_register_device,并且在platform_register_device方法中設(shè)置了device的父kobj為platform_bus,導(dǎo)致所有通過的platform_register_device注冊的設(shè)備的目錄都會在/sys/devices/platform/下0在sys文件系統(tǒng)中的結(jié)構(gòu)是:todoDev設(shè)置了所屬kset,但是dev的父kobj一般為被設(shè)置為其他的dev。比如說platform_device_register中會將dev的父kobj設(shè)置為platform_bus(相對于/sys/devices/platform_bus目錄),因此dev在sys中的目錄可能就是/sys/devices/platform_bus/xxx_devicedevice_register(structdevice-*dev)device_initialize()設(shè)置內(nèi)嵌kobj的所屬kset為deviceksetdev_set_name(dev,"%sH,
dev->init_name);設(shè)置內(nèi)嵌kobj的name為devl^Device_create_file(dev,&devt_attr);創(chuàng)建dev屬性文件,讀方法就是輸出相應(yīng)的主次設(shè)備號Kobject_add(&dev->kobj,
dev->kobj.parent,NULL);注冊內(nèi)嵌kobjo這時,已經(jīng)在/sys/devices/xxx/下創(chuàng)建好目錄Device_add_class_symlinks如果有class,創(chuàng)建subsystem軟連接到/sys/class/相應(yīng)目錄End探測總線上驅(qū)動和該設(shè)備進(jìn)
行匹配intdevice_register(structdevice*dev){device_initialize(dev);returndevice_add(dev);}voiddevice_initialize(structdevice*dev){kobj_set_kset_s(dev,devices_subsys);kobject_init(&dev->kobj);klist_init(&dev->klist_children,klist_children_get,klist_children_put);INIT_LIST_HEAD(&dev->dma_pools);INIT_LIST_HEAD(&dev->node);init_MUTEX(&dev->sem);spin_lock_init(&dev->devres_lock);INIT_LIST_HEAD(&dev->devres_head);device_init_wakeup(dev,0);set_dev_node(dev,-1);}intdevice_add(structdevice*dev){structdevice*parent=NULL;structclass_interface*class_intf;interror=-EINVAL;dev=get_device(dev);if(!dev||!strlen(dev->bus_id))gotoError;pr_debug("DEV:registeringdevice:ID='%s'\n",dev->bus_id);parent=get_device(dev->parent);error=setup_parent(dev,parent);if(error)gotoError;/*first,registerwithgenericlayer.*/kobject_set_name(&dev->kobj,"%s",dev->bus_id);error=kobject_add(&dev->kobj);if(error)gotoError;/*notifyplatformofdeviceentry*/if(platform_notify)platform_notify(dev);/*notifyclientsofdeviceentry(newway)*/if(dev->bus)blocking_notifier_call_chain(&dev->bus->bus_notifier,BUS_NOTIFY_ADD_DEVICE,dev);〃創(chuàng)建uevent屬性文件。可以通過該文件發(fā)送事件error=device_create_file(dev,&uevent_attr);if(error)gotoattrError;〃創(chuàng)建dev的屬性文件。if(MAJOR(dev->devt))(error=device_create_file(dev,&devt_attr);if(error)gotoueventattrError;}error=device_add_class_symlinks(dev);if(error)gotoSymlinkError;〃創(chuàng)建所屬class,kobject_type,以及device本身自帶的屬性文件error=device_add_attrs(dev);if(error)gotoAttrsError;〃創(chuàng)建電源管理子目錄powererror=dpm_sysfs_add(dev);if(error)gotoPMError;//將該設(shè)備掛接到電源鏈表下device_pm_add(dev);//將該dev添加到buserror=bus_add_device(dev);if(error)gotoBusError;kobject_uevent(&dev->kobj,KOBJ_ADD);〃發(fā)送一個uevent事件到用戶空間,實現(xiàn)熱插拔bus_attach_device(dev);//自動匹配設(shè)備和驅(qū)動if(parent)klist_add_tail(&dev->knode_parent,&parent->klist_children);if(dev->class)(down(&dev->class->sem);/*tietheclasstothedevice*/list_add_tail(&dev->node,&dev->class->devices);/*notifyanyinterfacesthatthedeviceishere*/list_for_each_entry(class_intf,&dev->class->interfaces,node)if(class_intf->add_dev)class_intf->add_dev(dev,class_intf);up(&dev->class->sem);}Done:put_device(dev);returnerror;BusError:device_pm_remove(dev);dpm_sysfs_remove(dev);PMError:if(dev->bus)blocking_notifier_call_chain(&dev->bus->bus_notifier,BUS_NOTIFY_DEL_DEVICE,dev);device_remove_attrs(dev);AttrsError:device_remove_class_symlinks(dev);SymlinkError:if(MAJOR(dev->devt))device_remove_file(dev,&devt_attr);if(dev->class)(sysfs_remove_link(&dev->kobj,"subsystem");/*Ifthisisnota"fake"compatibledevice,removethe*symlinkfromtheclasstothedevice.*/if(dev->kobj.parent!=&dev->class->subsys.kobj)sysfs_remove_link(&dev->class->subsys.kobj,dev->bus_id);if(parent)(#ifdefCONFIG_SYSFS_DEPRECATEDchar*class_name=make_class_name(dev->class->name,&dev->kobj);if(class_name)sysfs_remove_link(&dev->parent->kobj,class_name);kfree(class_name);#endifsysfs_remove_link(&dev->kobj,"device");}}ueventattrError:device_remove_file(dev,&uevent_attr);attrError:kobject_uevent(&dev->kobj,KOBJ_REMOVE);kobject_del(&dev->kobj);Error:if(parent)put_device(parent);gotoDone;}voidbus_attach_device(structdevice*dev)structbus_type*bus=dev->bus;intret=0;if(bus)(dev->is_registered=1;〃如果總線自動探測設(shè)備,則進(jìn)行設(shè)備驅(qū)動匹配。(可以通過bus下的autoprobe屬性文件查看和修改是否支持自動探測)if(bus->drivers_autoprobe)ret=device_attach(dev);WARN_ON(ret<0);if(ret>=0)klist_add_tail(&dev->knode_bus,&bus->klist_devices);elsedev->is_registered=0;}}intdevice_attach(structdevice*dev){intret=0;down(&dev->sem);if(dev->driver){ret=device_bind_driver(dev);if(ret==0)ret=1;else{dev->driver=NULL;ret=0;}}else{//將設(shè)備和該總線上的所有驅(qū)動進(jìn)行匹配ret=bus_for_each_drv(dev->bus,NULL,dev,__device_attach);}up(&dev->sem);returnret;}staticint__device_attach(structdevice_driver*drv,void*data){structdevice*dev=data;returndriver_probe_device(drv,dev);}intdriver_probe_device(structdevice_driver*drv,structdevice*dev){intret=0;if(!device_is_registered(dev))return-ENODEV;〃首先調(diào)用總線的match方法進(jìn)行匹配if(drv->bus->match&&!drv->bus->match(dev,drv))gotodone;pr_debug("%s:MatchedDevice%swithDriver%s\n",drv->bus->name,dev->bus_id,drv->name);〃調(diào)用總線或者驅(qū)動的probe方法繼續(xù)進(jìn)一步的匹配。ret=really_probe(dev,drv);done:returnret;}注冊驅(qū)動intdriver_register(structdevice_driver*drv)注冊驅(qū)動到設(shè)備驅(qū)動模型,在sysfs創(chuàng)建相應(yīng)的目錄結(jié)構(gòu),以及自動匹配設(shè)備驅(qū)動。一般在內(nèi)核中會包裝在其他的方法中在內(nèi)部調(diào)用driver_register方法。在sysfs中的結(jié)構(gòu)是:/sys/bus/platform/drivers/serial8250/|--bind|--serial8250->../../../../devices/platform/serial8250|--uevent'--unbind/sys/devices/platform/serial8250I--driver->../../../bus/platform/drivers/serial8250driver_register(structdevicedriver*drv)./Drv設(shè)置了所屬kset,但是parentkobj為空。所以parentkobj也會被設(shè)置為所屬kset。創(chuàng)建sys目錄時,會在/sys/bus/xxx_bus/drivers/下面。Kobject_init_and_add注冊內(nèi)建的kobj設(shè)置drvDrv設(shè)置了所屬kset,但是parentkobj為空。所以parentkobj也會被設(shè)置為所屬kset。創(chuàng)建sys目錄時,會在/sys/bus/xxx_bus/drivers/下面。Kobject_init_and_add注冊內(nèi)建的kobj設(shè)置drv內(nèi)建的kobj的所屬
kset為相應(yīng)bus的驅(qū)動kset。Bus->p->driverskset將drv加入到所屬bus的驅(qū)動
鏈表
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 《實驗室消毒滅菌》課件
- 《病媒生物控制》課件
- 單位管理制度合并選集人事管理篇
- 《倉庫管理的認(rèn)識》課件
- 單位管理制度分享合集【人事管理篇】十篇
- 單位管理制度范例匯編【人事管理】十篇
- 做情緒的主人 高一上學(xué)期心理健康教育課
- 2024年農(nóng)業(yè)年終工作總結(jié)
- 2024年協(xié)輔警個人總結(jié)
- 《山東膠州秧歌》課件
- 工程預(yù)結(jié)算課件
- 酒店宴會合同范本
- 貨款互抵三方協(xié)議合同范本
- 七年級道德與法治論文2000字(合集六篇)
- 嚴(yán)重精神障礙患者健康管理服務(wù)規(guī)范
- 風(fēng)險預(yù)測分析及風(fēng)險與機(jī)遇評估分析表
- 高中日語宣講 試聽課件
- 壓力彈簧力度計算器及計算公式
- 新生兒窒息診斷地專家共識
- 2023年重慶市旅游業(yè)統(tǒng)計公報要點
- 器械清洗的資料
評論
0/150
提交評論