版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、簡介作者: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)還提 供了方便的同用戶控件交互的接口??蚣躶truct kset.t_opsitruct attributestru
2、ct sysfs_ops-const char *name-struct module *owner-mode_t modeTtv+int (*filter) (struct kset *kset, struct kobject *kobj)()+const char *(*name) (struct kset *kset, struct kobject *kobj)()+int (*uevent) (struct kset *kset, struct ko&ct *kobj, struct kobj_uevent_env *env)()+ssize_t (*show) (struct kob
3、ject *, struct attribute *, char *)()+ssize_t (*store) (struct kobject *, stfpct attribute *, const char *, size_t)()uct kobjectstruct kset-struct list_head list-spinlock_t list_lock-struct kobject kobj-struct kset_uevent_ops *uevent_ops-const char *name-struct list_head entry-struct kobject *parent
4、-struct kset *kset-struct kobj_type *ktype-struct sysfs_dirent *sd-struct kref kref-uint state_initialized:1-uint state_in_sysfs:1-uint state_add_uevent_sent:1-unit state_remove_uevent_sent:1-uint uevent_suppress:1struct kobj_*ype-struct sysfs_ops *sysfs_ops-struct attribute *default_attrs+void (*re
5、lease) (struct kobject *kobj)()struct bus_typestruct devicestruct device_driver-const char *name-struct bus_attribute *bus_attrs-struct device_attribute *dev_attrs-struct driver_attribute *drv_attrs-const struct dev_pm_ops *pm-struct bus_type_private *p+int (*match) (struct device *dev, struct devic
6、e_driver *drv)()+int (*uevent) (struct device *dev, struct kobj_uevent_env *env)()+int (*probe) (struct device *dev)()+int (*remove) (struct device *dev)()+void (*shutdown) (struct device *dev)()+int (*suspend) (struct device *dev, pm message t state)()+int (*resume) (struct device *dev)()-struct de
7、vice *parent-struct device_private *p-struct kobject kobj-char bus_idBUS_ID_SIZE-const char *init_name-struct device_type *type-struct semaphore sem-struct bus_type *bus-struct device_driver *driver-void *platform_data-struct dev_pm_info power-dev_t devt-spinlock_t devres_lock-struct list_head devre
8、s_head-struct klist_node knode_class-struct class *class-const struct attribute_group *groups+void (*release) (struct device *dev)()-const char *name-struct bus_type *bus-struct module *owner-const char *mod_name-bool suppress_bind_attrs-const struct attribute_group *groups-const struct dev_pm_ops *
9、pm-struct driver_private *p+int (*probe) (struct device *dev)()+int (*remove) (struct device *dev)()+vod (*shutdown) (struct device *dev)()+int (*suspend) (struct device *dev, pm message t state)()+int (*resume) (struct device *dev)()struct bus_type_private-struct kset subsys-struct kset *drivers_ks
10、et-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 *busstruct device_privateuct driver_privatestruct klist klist_childrenstruct klist_node knode_parent struct klist_node konde_
11、driver struct klist_node knode_bus void *driver_datastruct device ,device-struct kobject kobj-struct klist klist_devices-struct klist_node knode_bus-struct module_kobject *mkobj-struct device_driver *driverbus_at!ribule-struct attribute attrstruct driver_attribute-struct attribute attr+ssize_t (*sho
12、w) (struct bus_type *bus, char *buf)()+ssize_t (*store) (struct bus_type *bus, const char *buf, size_t count)()+ssize_t (*show) (struct device_driver *driver, char *buf)()+ssize_t (*store) (struct device_driver *driver, const char *buf, size_t count)()struct devic_attribut-struct attribute attr +ssi
13、ze_t (*show) (struct device *dev, char *buf)()+ssize_t (*store) (struct device *dev, const char *buf, size_t count)()數(shù)據(jù)結(jié)構(gòu)KobjectKobject是代表驅(qū)動模型中的一個對象??偩€、驅(qū)動、設(shè)備都繼承了它。(在結(jié)構(gòu)體中包含 kobject)。每個kobject在sysfs中表現(xiàn)為一個目錄。每個kobject都有一個parent kobject和所屬的kset。Kset就是kobject所屬的kset,通過kset 的鏈表可以找到所有屬于它的kobject。這些kobject進
14、行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ū)動或者總線的時候如果不指定parent kobj的 話,父kobj則會設(shè)置為所屬的kset的kobj。(todo:最好畫圖表示關(guān)系)struct kobject (const char* k_name;struct krefkref;struct list_headentry;連入到所屬的
15、kset的liststruct kobject* parent; /父kobj,如果沒有父kobj,則使用所屬的kset內(nèi)嵌kobjstruct kset* kset; /所屬的kset (如果有的話)struct kobj_type* ktype; /所屬的ktype,如果所屬的kset也有ktype,則用kset的ktype。struct sysfs_dirent ;* sd;Kest通過kset可以將kobject組織成一顆層次樹。struct kset (struct list_headlist; /屬于該kset的kobj鏈表spinlock_tlist_lock;struct ko
16、bjectkobj; 內(nèi)嵌的 kobjectstruct kset_uevent_ops *uevent_ops; /uevent 方法,對所有該 kset 下的 kobj 進彳亍 uevent操作時的方法。;struct kset_uevent_ops (int (*filter)(struct kset *kset, struct kobject *kobj);const char *(*name)(struct kset *kset, struct kobject *kobj);int (*uevent)(struct kset *kset, struct kobject *kobj,
17、struct kobj_uevent_env *env);kobj_typestruct kobj_type (void (*release)(struct kobject *kobj); /kobject 釋放時調(diào)用struct sysfs_ops *sysfs_ops; /臊縱默認屬性的讀寫方法struct attribute *default_attrs; 相應(yīng)的 kobject (kset)的默認屬性。對應(yīng)于 sysfs 下的文 件。;struct sysfs_ops (ssize_t (*show)(struct kobject *, struct attribute *,char
18、*);ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t);J;struct attribute (const char*name;struct module*owner;mode_t ;mode;bus_type代表一個總線。對應(yīng)/sys/bus下的一個目錄。管理相應(yīng)總線下的所有驅(qū)動和設(shè)備。struct bus_type (const char *name;總線名稱struct bus_attribute *bus_attrs;該總線目錄下的屬性文件以及相應(yīng)的訪問方法struct device_a
19、ttribute *dev_attrs; 該總線設(shè)備子目錄下的屬性文件以及相應(yīng)的訪問方 法struct driver_attribute *drv_attrs; 該總線驅(qū)動子目錄下的屬性文件以及相應(yīng)的訪問方 法int (*match)(struct device *dev, struct device_driver *drv); 驅(qū)動模型進行驅(qū)動和設(shè)備的匹 配時調(diào)用int (*uevent)(struct device *dev, struct kobj_uevent_env *env); /ueven方法int (*probe)(struct device *dev); /match成功之后
20、會調(diào)用。一般該probe方法內(nèi)部會調(diào)用 相應(yīng)的device_driver的probe方法int (*remove)(struct device *dev);void (*shutdown)(struct device *dev);int (*suspend)(struct device *dev, pm_message_t state);int (*suspend_late)(struct device *dev, pm_message_t state);int (*resume_early)(struct device *dev);int (*resume)(struct device *d
21、ev);struct dev_pm_ops *pm;struct bus_type_private *p;struct bus_type_private (struct kset subsys; 總線本身目錄struct kset *drivers_kset; 驅(qū)動目錄struct kset *devices_kset; 設(shè)備目錄struct klist klist_devices;struct klist klist_drivers;struct blocking_notifier_head bus_notifier;unsigned int drivers_autoprobe:1;stru
22、ct bus_type *bus;Devicestruct device (struct device *parent; 父設(shè)備struct device_private *p;struct kobject kobj;char bus_idBUS_ID_SIZE;const char*init_name; /* initial name of the device */struct device_type *type;struct semaphore sem;/* semaphore to synchronize calls to* its driver.*/struct bus_type *
23、bus;/* type of bus device is on */struct device_driver *driver; /* which driver has allocated thisdevice */void *platform_data; /* Platform specific data, device core doesnt touch it */struct dev_pm_info power;#ifdef CONFIG_NUMA int numa_node; /* NUMA node this device is close to */ #endifu64 *dma_m
24、ask; /* dma mask (if dmaable device) */ u64 coherent_dma_mask;/* Like dma_mask, but for alloc_coherent mappings as not all hardware supports 64 bit addresses for consistent allocations such descriptors. */struct device_dma_parameters *dma_parms;struct list_head dma_pools; /* dma pools (if dmable) */
25、struct dma_coherent_mem *dma_mem; /* internal for coherent mem override */* arch specific additions */struct dev_archdata archdata;dev_tdevt;/* dev_t, creates the sysfs dev */spinlock_t struct list_headdevres_lock;devres_head;struct klist_nodestruct classknode_class;*class;const struct attribute_gro
26、up *groups; /* optional groups */void (*release)(struct device *dev);struct device_private (struct klist klist_children; /子設(shè)備的鏈表struct klist_node knode_parent; /作為父設(shè)備的字設(shè)備鏈表(klist_children)的一個節(jié)點 struct klist_node knode_driver; /(作為所屬驅(qū)動的設(shè)備鏈表(klist_devices)的一個節(jié)點 struct klist_node knode_bus; /作為所屬總線的設(shè)備鏈
27、表(klist_devices)的一個節(jié)點 void *driver_data;struct device *device;device_driverstruct device_driver (const char*name;struct bus_type*bus;struct module*owner;const char*mod_name; /* used for built-in modules */int (*probe) (struct device *dev);int (*remove) (struct device *dev);void (shutdown) (struct de
28、vice *dev);int (*suspend) (struct device *dev, pm_message_t state);int (*resume) (struct device *dev);struct attribute_group *groups;struct dev_pm_ops *pm;struct driver_private *p;;struct driver_private (struct kobject kobj;struct klist klist_devices; /所驅(qū)動的設(shè)備的鏈表struct klist_node knode_bus; /作為所屬總線的驅(qū)
29、動鏈表(klist_drivers)的一個節(jié)點 struct module_kobject *mkobj;struct device_driver *driver;基礎(chǔ)方法kobject_add_internalstatic int kobject_add_internal(struct kobject *kobj)將kobject添加到設(shè)備驅(qū)動模型中。主要設(shè)置父kobj以及將自己添加到所屬的kset的list中, 并且在sysfs中創(chuàng)建目錄。父kobj存在否kobject_add_internal()Endkobject_get(kobj-parent)獲取父kobj并增加引用計數(shù)creat
30、e_dir(kobj) 在sysfs中創(chuàng)建kobj相應(yīng)目錄設(shè)置父kobj為所屬的kset的 內(nèi)嵌kobj將kobj加入到所屬kset的 kobj鏈表中 Kobj-entry + kset-listkobject_ueventint kobject_uevent(struct kobject *kobj, enum kobject_action action) send an uevent to userspacekobject_uevent( struct kobject *kobj, enum kobject_action actii rEnd通過Netlink_broadcast(ueve
31、nt_sock,.)發(fā)送出去call_usermodehelper 調(diào)用用戶進程。一般是/sbin/hotplug,手機上一般沒有核心方法注冊總線bus_register(struct bus_type *bus)注冊一個總線到驅(qū)動模型中。在sysfs中的結(jié)構(gòu)是:/sys/bus/platform/|- devices|-.|- drivers|- .|- drivers_autoprobe|- drivers_probe-ueventBUS_ATTR(uevent, S_IWUSR, NULL, bus_uevent_store);屬性的寫方法直接調(diào)用kobject_uevent發(fā)送事件分配
32、Bus.p的空間 bus_type_private設(shè)置Bus內(nèi)建的kobject: name 等于 所屬 kset 為 &bus_kset Ktype等于&bus ktypeIPus)Bus_register(Struct bus_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_busint bus_register(struct bus
33、_type *bus)int retval;struct bus_type_private *priv;/初始化private數(shù)據(jù)結(jié)構(gòu)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);設(shè)置kobject名稱。即/bus/sys/下的目錄名稱retval = kobject_set_name(&priv-subsys.kobj,
34、 %s, bus-name); if (retval)goto out;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)goto out;retval = bus_create_file(bus, &bus_attr_uevent);if (retval)goto bus_uevent_fail;創(chuàng)建設(shè)備kset并且注冊priv-devic
35、es_kset = kset_create_and_add(devices”, NULL, &priv-subsys.kobj);if (!priv-devices_kset) ( retval = -ENOMEM; goto bus_devices_fail;創(chuàng)建驅(qū)動kset并且注冊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
36、-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, bus-name);return 0;0 0 0out:return retval;注冊設(shè)備
37、主要有兩個工作,初始化設(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的父kobj為platfor
38、m_bus,導致所有通 過的 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(s
39、truct device-*dev)device_initialize() 設(shè)置內(nèi)嵌kobj的所屬kset為 device ksetdev_set_name(dev, %sH,dev-init_name);設(shè)置內(nèi)嵌kobj的name為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
40、 如果有class,創(chuàng)建subsystem 軟連接到/sys/class/相應(yīng)目 錄EndBus_probe_device探測總線上驅(qū)動和該設(shè)備進行匹配int device_register(struct device *dev)device_initialize(dev);return device_add(dev);void device_initialize(struct device *dev)kobj_set_kset_s(dev, devices_subsys);kobject_init(&dev-kobj);klist_init(&dev-klist_children, klis
41、t_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);int device_add(struct device *dev)struct device *parent = NULL;struct c
42、lass_interface *class_intf;int error = -EINVAL;dev = get_device(dev);if (!dev | !strlen(dev-bus_id) goto Error;pr_debug(DEV: registering device: ID = %sn, dev-bus_id);parent = get_device(dev-parent);error = setup_parent(dev, parent);if (error)goto Error;/* first, register with generic layer. */kobje
43、ct_set_name(&dev-kobj, %s, dev-bus_id);error = kobject_add(&dev-kobj);if (error)goto Error;/* notify platform of device entry */if (platform_notify) platform_notify(dev);/* notify clients of device entry (new way) */if (dev-bus)blocking_notifier_call_chain(&dev-bus-bus_notifier, BUS_NOTIFY_ADD_DEVIC
44、E, dev);創(chuàng)建uevent屬性文件。可以通過該文件發(fā)送事件 error = device_create_file(dev, &uevent_attr);if (error)goto attrError;創(chuàng)建dev的屬性文件。if (MAJOR(dev-devt) (error = device_create_file(dev, &devt_attr);if (error)goto ueventattrError;error = device_add_class_symlinks(dev);if (error)goto SymlinkError;創(chuàng)建所屬class, kobject_typ
45、e,以及device本身自帶的屬性文件error = device_add_attrs(dev);if (error)goto AttrsError;創(chuàng)建電源管理子目錄powererror = dpm_sysfs_add(dev);if (error)goto PMError;/將該設(shè)備掛接到電源鏈表下device_pm_add(dev);/將該dev添加到buserror = bus_add_device(dev);if (error)goto BusError;kobject_uevent(&dev-kobj, KOBJ_ADD); 發(fā)送一個 uevent 事件到用戶空間,實現(xiàn)熱插 拔bu
46、s_attach_device(dev); /自動匹配設(shè)備和驅(qū)動if (parent)klist_add_tail(&dev-knode_parent, &parent-klist_children);if (dev-class) (down(&dev-class-sem);/* tie the class to the device */list_add_tail(&dev-node, &dev-class-devices);/* notify any interfaces that the device is here */list_for_each_entry(class_intf, &
47、dev-class-interfaces, node)if (class_intf-add_dev)class_intf-add_dev(dev, class_intf);up(&dev-class-sem);Done:put_device(dev);return error;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_r
48、emove_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);/* If this is not a fake compatible device, remove the* symlink from the class to the device. */if (dev-kobj.paren
49、t != &dev-class-subsys.kobj) sysfs_remove_link(&dev-class-subsys.kobj, dev-bus_id);if (parent) (#ifdef CONFIG_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-ko
50、bj, 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);goto Done;void bus_attach_device(struct device * dev)struct bus_type *bus = dev-bus;int ret = 0;if (bus) (dev-is_registered =
51、1;如果總線自動探測設(shè)備,則進行設(shè)備驅(qū)動匹配。(可以通過bus下的autoprobe屬 性文件查看和修改是否支持自動探測)if (bus-drivers_autoprobe)ret = device_attach(dev);WARN_ON(ret = 0)klist_add_tail(&dev-knode_bus, &bus-klist_devices);elsedev-is_registered = 0;int device_attach(struct device * dev)int ret = 0;down(&dev-sem);if (dev-driver) ret = device_b
52、ind_driver(dev);if (ret = 0)ret = 1;else dev-driver = NULL;ret = 0; else /將設(shè)備和該總線上的所有驅(qū)動進行匹配ret = bus_for_each_drv(dev-bus, NULL, dev, _device_attach);up(&dev-sem);return ret;static int _device_attach(struct device_driver * drv, void * data)struct device * dev = data;return driver_probe_device(drv, d
53、ev);int driver_probe_device(struct device_driver * drv, struct device * dev)int ret = 0;if (!device_is_registered(dev)return -ENODEV;首先調(diào)用總線的match方法進行匹配if (drv-bus-match & !drv-bus-match(dev, drv) goto done;pr_debug(%s: Matched Device %s with Driver %sn, drv-bus-name, dev-bus_id, drv-name);調(diào)用總線或者驅(qū)動的p
54、robe方法繼續(xù)進一步的匹配。ret = really_probe(dev, drv);done:return ret;注冊驅(qū)動int driver_register(struct device_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|-
55、uevent-unbind/sys/devices/platform/serial8250I- driver - ./././bus/platform/drivers/serial8250driver_register(struct device driver *drv) ./Drv 設(shè)置了所屬 kset,但是 parent kobj 為空。所以parent kobj也會被設(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-drivers kset將drv加入到所屬bus的驅(qū)動鏈表中所屬的bus是否自動套probeBus_
溫馨提示
- 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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五年度生態(tài)農(nóng)業(yè)科技園承包經(jīng)營合同范本3篇
- 2025年度綠色能源儲藏室建設(shè)與維護合同3篇
- 二零二五版城市綜合體建設(shè)項目建筑垃圾清運及環(huán)保處理合同3篇
- 2025年度體育場館租賃與賽事組織合同3篇
- 二零二五年高性能保溫施工合同補充條款及驗收標準3篇
- 2025年水電暖安裝與節(jié)能改造項目總承包合同3篇
- 2025年度醫(yī)院窗簾定制及消毒防菌合同3篇
- 2025年度智能化倉庫場地租賃服務(wù)合同范本3篇
- 2025年度拍賣物品售后服務(wù)反饋合同范本
- 2025年度智能租賃平臺廠房租賃居間協(xié)議3篇
- 2024-2030年中國電子郵箱行業(yè)市場運營模式及投資前景預(yù)測報告
- 基礎(chǔ)設(shè)施零星維修 投標方案(技術(shù)方案)
- 人力資源 -人效評估指導手冊
- 大疆80分鐘在線測評題
- 2024屆廣東省廣州市高三上學期調(diào)研測試英語試題及答案
- 中煤平朔集團有限公司招聘筆試題庫2024
- 2023年成都市青白江區(qū)村(社區(qū))“兩委”后備人才考試真題
- 不付租金解除合同通知書
- 區(qū)域合作伙伴合作協(xié)議書范本
- 中學數(shù)學教學設(shè)計全套教學課件
- 環(huán)衛(wèi)公司年終工作總結(jié)
評論
0/150
提交評論