




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
字符設(shè)備驅(qū)動第5章字符設(shè)備驅(qū)動計(jì)算機(jī)科學(xué)技術(shù)系李偉民2012年8月字符設(shè)備驅(qū)動提綱Linux字符設(shè)備驅(qū)動結(jié)構(gòu)
-Linux設(shè)備號管理
-一些重要的數(shù)據(jù)結(jié)構(gòu)globalmem設(shè)備驅(qū)動
-globalmem驅(qū)動編寫方法和分析-globalmem設(shè)備驅(qū)動在用戶空間的驗(yàn)證
字符設(shè)備驅(qū)動引言Linux提供3種基本的設(shè)備驅(qū)動接口,包括字符,塊設(shè)備和網(wǎng)絡(luò)設(shè)備驅(qū)動,其中字符設(shè)備是應(yīng)用最廣,和用戶應(yīng)用程序聯(lián)系最直接的驅(qū)動。比起塊設(shè)備或者網(wǎng)絡(luò)驅(qū)動程序更加易于理解。字符設(shè)備驅(qū)動字符設(shè)備開發(fā)的基本步驟字符設(shè)備的特點(diǎn)像字節(jié)流一樣來存取的設(shè)備(如同文件)通過/dev下的文件系統(tǒng)結(jié)點(diǎn)來訪問通常至少需要實(shí)現(xiàn)open,close,read,和write等系統(tǒng)調(diào)用只能順序訪問的數(shù)據(jù)通道,不能前后移動訪問指針。特例:比如framebuffer設(shè)備就是這樣的設(shè)備,應(yīng)用程序可以使用mmap或lseek訪問圖像的各個(gè)區(qū)域。字符設(shè)備驅(qū)動字符設(shè)備開發(fā)的基本步驟確定主設(shè)備號和次設(shè)備號實(shí)現(xiàn)字符驅(qū)動程序?qū)崿F(xiàn)file_operations結(jié)構(gòu)體實(shí)現(xiàn)初始化函數(shù),注冊字符設(shè)備實(shí)現(xiàn)銷毀函數(shù),釋放字符設(shè)備創(chuàng)建設(shè)備文件節(jié)點(diǎn)字符設(shè)備驅(qū)動主設(shè)備號與次設(shè)備號主設(shè)備號與次設(shè)備號主設(shè)備號:主設(shè)備號是內(nèi)核識別一個(gè)設(shè)備的標(biāo)識。整數(shù)(占12bits),范圍從0到4095,通常使用1到255??梢酝ㄟ^/proc/devices文件來查看驅(qū)動系統(tǒng)設(shè)備的主設(shè)備號。次設(shè)備號:次設(shè)備號由內(nèi)核使用,用于正確確定設(shè)備文件所指的設(shè)備,驅(qū)動程序遍歷設(shè)備時(shí),每發(fā)現(xiàn)一個(gè)它能驅(qū)動的設(shè)備,就創(chuàng)建一個(gè)設(shè)備對象,并為其分配一個(gè)次設(shè)備號以區(qū)分不同的設(shè)備。這樣當(dāng)應(yīng)用程序訪問設(shè)備節(jié)點(diǎn)時(shí)驅(qū)動程序就可以根據(jù)次設(shè)備號知道它所訪問的設(shè)備了。整數(shù)(占20bits),范圍從0到1048575,一般使用0到255。字符設(shè)備驅(qū)動主設(shè)備號與次設(shè)備號ls-l/devcrw-r1rootroot1,1Jan100:00memcrw-r1rootroot1,2Jan100:00kmemcrw-rw-rw-1rootroot1,3Jan100:00nullcrw-r1rootroot1,4Jan100:00portcrw-rw-rw-1rootroot1,5Jan100:00zerocrw-rw-rw-1rootroot1,7Jan100:00fullcrw-r--r--1rootroot1,8Jan100:00randomcrw-r--r--1rootroot1,9Jan100:00urandomcrw-rw-rw-1rootroot5,0Jan100:00ttycrw1rootroot5,1Jan100:00consolecrw-rw-rw-1rootroot5,2Jan100:00ptmxdrwxr-xr-x1rootroot0Jan100:00ptydrwxr-xr-x2rootroot0Jan100:00ptsdrwxr-xr-x1rootroot0Jan100:00rddrwxr-xr-x1rootroot0Jan100:00mtddrwxr-xr-x1rootroot0Jan100:00mtdblockcrw1rootroot4,64Jan100:15ttyS0crw1rootroot4,65Jan100:00ttyS1crw1rootroot4,66Jan100:00ttyS2crw1rootroot4,67Jan100:00ttyS3crw1rootroot4,68Jan100:00ttyS4drwxr-xr-x1rootroot0Jan100:00miscc:字符設(shè)備b:塊設(shè)備主設(shè)備號次設(shè)備號字符設(shè)備驅(qū)動設(shè)備編號的內(nèi)部表達(dá)dev_t類型(32位):用來保存設(shè)備編號(包括主設(shè)備號(12位)和次設(shè)備號(20位))。從dev_t獲得主設(shè)備號和次設(shè)備號
:MAJOR(dev_t);
MINOR(dev_t)。將主設(shè)備號和次設(shè)備號轉(zhuǎn)換成dev_t類型:MKDEV(intmajor,intminor)字符設(shè)備驅(qū)動主設(shè)備號與次設(shè)備號分配主設(shè)備號手工分配:找一個(gè)內(nèi)核沒有使用過的主設(shè)備號來使用動態(tài)分配:我們通常不知道設(shè)備將要使用哪些主設(shè)備號#include<linux/fs.h>intregister_chrdev_region(dev_tfirst,unsignedintcount,char*name);要分配的設(shè)備編號范圍的起始值,次設(shè)備號經(jīng)常為0所請求的連續(xù)設(shè)備編號的個(gè)數(shù)和該編號范圍關(guān)聯(lián)的設(shè)備名稱,它將出現(xiàn)在/proc/devices和sysfs中#include<linux/fs.h>intalloc_chrdev_resion(dev_t*dev,unsignedintfirstminor,
unsignedintcount,char*name);輸出的設(shè)備號要使用的被請求的第一個(gè)次設(shè)備號字符設(shè)備驅(qū)動主設(shè)備號與次設(shè)備號釋放設(shè)備號voidunregister_chrdev_region(dev_tfirst,unsignedintcount);通常在模塊的清除函數(shù)中調(diào)用。字符設(shè)備驅(qū)動Linux字符設(shè)備驅(qū)動結(jié)構(gòu)cdev結(jié)構(gòu)體Linux2.6內(nèi)核中,使用cdev結(jié)構(gòu)體描述一個(gè)字符設(shè)備structcdev{ structkobjectkobj;/*內(nèi)嵌的kobject對象*/ structmodule*owner;/*所屬模塊*/ structfile_operations*ops;/*文件操作結(jié)構(gòu)體*/ structlist_headlist; dev_tdev;/*設(shè)備號*/ unsignedintcount;};字符設(shè)備驅(qū)動Linux字符設(shè)備驅(qū)動結(jié)構(gòu)操作cdev的函數(shù)voidcdev_init(structcdev*,structfile_operations*);structcdev*cdev_alloc(void);intcdev_add(structcdev*,dev_t,unsigned);voidcdev_del(structcdev*);用于初始化cdev的成員,并建立cdev和file_operations之間的連接函數(shù)用于動態(tài)申請一個(gè)cdev內(nèi)存分別向系統(tǒng)刪除一個(gè)cdev,完成字符設(shè)備的注銷,通常在模塊的卸載函數(shù)中調(diào)用分別向系統(tǒng)添加一個(gè)cdev,完成字符設(shè)備的注冊,通常在模塊加載函數(shù)中調(diào)用字符設(shè)備驅(qū)動Linux字符設(shè)備驅(qū)動結(jié)構(gòu)file_operations結(jié)構(gòu)體字符驅(qū)動和內(nèi)核的接口,在include/linux/fs.h中定義,它定義了維系在設(shè)備驅(qū)動上的操作函數(shù)。在進(jìn)程PCB中,每個(gè)打開文件,包括設(shè)備文件(內(nèi)部用一個(gè)structfile結(jié)構(gòu)來代表,稍后我們會看到)與它自身的函數(shù)集合相關(guān)連,它通過包含一個(gè)稱為f_op的指向一個(gè)file_operations結(jié)構(gòu)成員指針建立關(guān)系字符驅(qū)動只要實(shí)現(xiàn)一個(gè)file_operations結(jié)構(gòu)體,并注冊到內(nèi)核中,內(nèi)核就有了操作此設(shè)備的能力用戶通過系統(tǒng)調(diào)用open,read,write等在這個(gè)結(jié)構(gòu)中有相應(yīng)的方法對應(yīng)字符設(shè)備驅(qū)動Linux字符設(shè)備驅(qū)動結(jié)構(gòu)file_operations結(jié)構(gòu)體的主要成員structmodule*owner:它是一個(gè)指向擁有這個(gè)結(jié)構(gòu)的模塊的指針,它被簡單初始化為THIS_MODULE,一個(gè)在<linux/module.h>中定義的宏。loff_t(*llseek)(structfile*,loff_t,int):
llseek方法用作改變文件中的當(dāng)前讀/寫位置,并且新位置作為(正的)返回值。ssize_t(*read)(structfile*,char__user*,size_t,loff_t*):用來從設(shè)備中獲取數(shù)據(jù)。ssize_t(*aio_read)(structkiocb*,char__user*,size_t,loff_t):初始化一個(gè)異步讀--可能在函數(shù)返回前不結(jié)束的讀操作.字符設(shè)備驅(qū)動Linux字符設(shè)備驅(qū)動結(jié)構(gòu)file_operations結(jié)構(gòu)體的主要成員ssize_t(*write)(structfile*,constchar__user*,size_t,loff_t*):發(fā)送數(shù)據(jù)給設(shè)備.如果NULL,-EINVAL,如果非負(fù),返回值代表成功寫的字節(jié)數(shù)。ssize_t(*aio_write)(structkiocb*,constchar__user*,size_t,loff_t*):初始化設(shè)備上的一個(gè)異步寫。
int(*readdir)(structfile*,void*,filldir_t):對于設(shè)備文件這個(gè)成員應(yīng)當(dāng)為NULL;它用來讀取目錄,并且僅對文件系統(tǒng)有用unsignedint(*poll)(structfile*,structpoll_table_struct*):poll方法是3個(gè)系統(tǒng)調(diào)用的后端:poll,epoll,和select,都用作查詢對一個(gè)或多個(gè)文件描述符的讀或?qū)懯欠駮枞址O(shè)備驅(qū)動Linux字符設(shè)備驅(qū)動結(jié)構(gòu)file_operations結(jié)構(gòu)體的主要成員
int(*ioctl)(structinode*,structfile*,unsignedint,unsignedlong):ioctl系統(tǒng)調(diào)用提供了發(fā)出設(shè)備特定命令的方法(例如格式化軟盤的一個(gè)磁道,這不是讀也不是寫)。int(*mmap)(structfile*,structvm_area_struct*):mmap用來請求將設(shè)備內(nèi)存映射到進(jìn)程的地址空間.如果這個(gè)方法是NULL,mmap系統(tǒng)調(diào)用返回–ENODEV。int(*open)(structinode*,structfile*):盡管這常常是對設(shè)備文件進(jìn)行的第一個(gè)操作,不要求驅(qū)動聲明一個(gè)對應(yīng)的方法.如果這個(gè)項(xiàng)是NULL,設(shè)備打開一直成功,但是你的驅(qū)動不會得到通知.int(*flush)(structfile*):flush操作在進(jìn)程關(guān)閉它的設(shè)備文件描述符的拷貝時(shí)調(diào)用,它應(yīng)當(dāng)執(zhí)行(并且等待)設(shè)備的任何未完成的操作.如果flush為NULL,內(nèi)核簡單地忽略用戶應(yīng)用程序的請求.字符設(shè)備驅(qū)動Linux字符設(shè)備驅(qū)動結(jié)構(gòu)file_operations結(jié)構(gòu)體的主要成員int(*release)(structinode*,structfile*):在文件結(jié)構(gòu)被釋放時(shí)用該操作。int(*fsync)(structfile*,structdentry*,int):這個(gè)方法是fsync系統(tǒng)調(diào)用的后端,用戶調(diào)用來刷新任何掛著的數(shù)據(jù)。int(*fasync)(int,structfile*,int):這個(gè)操作用來通知設(shè)備它的FASYNC標(biāo)志的改變int(*lock)(structfile*,int,structfile_lock*):lock方法用來實(shí)現(xiàn)文件加鎖ssize_t(*sendfile)(structfile*,loff_t*,size_tread_actor_t,void*):sendpage是sendfile的另一半;它由內(nèi)核調(diào)用來發(fā)送數(shù)據(jù),一次一頁,到對應(yīng)的文件.設(shè)備驅(qū)動上不實(shí)現(xiàn)sendpage字符設(shè)備驅(qū)動Linux字符設(shè)備驅(qū)動結(jié)構(gòu)file_operations結(jié)構(gòu)體的主要成員int(*release)(structinode*,structfile*):在文件結(jié)構(gòu)被釋放時(shí)用該操作。int(*fsync)(structfile*,structdentry*,int):這個(gè)方法是fsync系統(tǒng)調(diào)用的后端,用戶調(diào)用來刷新任何掛著的數(shù)據(jù)。int(*fasync)(int,structfile*,int):這個(gè)操作用來通知設(shè)備它的FASYNC標(biāo)志的改變int(*lock)(structfile*,int,structfile_lock*):lock方法用來實(shí)現(xiàn)文件加鎖ssize_t(*sendfile)(structfile*,loff_t*,size_tread_actor_t,void*):sendpage是sendfile的另一半;它由內(nèi)核調(diào)用來發(fā)送數(shù)據(jù),一次一頁,到對應(yīng)的文件.設(shè)備驅(qū)動上不實(shí)現(xiàn)sendpage字符設(shè)備驅(qū)動Linux字符設(shè)備驅(qū)動結(jié)構(gòu)file結(jié)構(gòu)體file結(jié)構(gòu)與用戶空間程序中的FILE沒有任何關(guān)聯(lián),F(xiàn)ILE在C庫中定義且不會出現(xiàn)在內(nèi)核代碼中,structfile是一個(gè)內(nèi)核結(jié)構(gòu),不會出現(xiàn)在用戶程序。file結(jié)構(gòu)代表一個(gè)打開的文件(不限定于設(shè)備驅(qū)動程序)。它由內(nèi)核在open時(shí)創(chuàng)建,并傳遞給在該文件上進(jìn)行操作的所有函數(shù),直到close函數(shù)。在文件的所有實(shí)例都被關(guān)閉之后,內(nèi)核會釋放。指向structfile的指針通常被稱為filp。字符設(shè)備驅(qū)動Linux字符設(shè)備驅(qū)動結(jié)構(gòu)file結(jié)構(gòu)體的主要成員mode_tf_mode:文件模式,它通過FMODE_READ和FMODE_WRITE來標(biāo)識文件是否可讀或可寫(或可讀寫)。loff_tf_pos:初始化當(dāng)前讀寫位置。驅(qū)動可以讀這個(gè)值,如果它需要知道文件中的當(dāng)前位置,但是正常地不應(yīng)該改變它;讀和寫會使用它們接收到的最后那個(gè)指針參數(shù)來更新一個(gè)位置,代替直接作用于filp->f_pos。
unsignedintf_flags:這些是文件標(biāo)志,例如O_RDONLY,O_NONBLOCK,和O_SYNC。驅(qū)動應(yīng)當(dāng)檢查O_NONBLOCK標(biāo)志來看是否是請求非阻塞操作;其他標(biāo)志很少使用。字符設(shè)備驅(qū)動Linux字符設(shè)備驅(qū)動結(jié)構(gòu)file結(jié)構(gòu)體的主要成員structfile_operations*f_op:和文件關(guān)聯(lián)的操作.內(nèi)核安排指針作為它的open實(shí)現(xiàn)的一部分,接著讀取它當(dāng)它需要分派任何的操作時(shí).filp->f_op中的值從不由內(nèi)核保存為后面的引用;這意味著你可改變你的文件關(guān)聯(lián)的文件操作,在你返回調(diào)用者之后新方法會起作用。void*private_data:open系統(tǒng)調(diào)用設(shè)置這個(gè)指針為NULL,在為驅(qū)動調(diào)用open方法之前.你可自由使用這個(gè)成員或者忽略它;你可以使用這個(gè)成員來指向分配的數(shù)據(jù),但是接著你必須記住在內(nèi)核銷毀文件結(jié)構(gòu)之前,在release方法中釋放那個(gè)內(nèi)存。
structdentry*f_dentry:關(guān)聯(lián)到文件的目錄入口(dentry)結(jié)構(gòu)。
字符設(shè)備驅(qū)動Linux字符設(shè)備驅(qū)動結(jié)構(gòu)inode結(jié)構(gòu)體inode結(jié)構(gòu)由內(nèi)核在內(nèi)部用來表示文件.因此,它和代表打開文件描述符的文件結(jié)構(gòu)是不同的.可能有代表單個(gè)文件的多個(gè)打開描述符的許多文件結(jié)構(gòu),但是它們都指向一個(gè)單個(gè)inode結(jié)構(gòu).inode結(jié)構(gòu)包含大量關(guān)于文件的信息.作為一個(gè)通用的規(guī)則,這個(gè)結(jié)構(gòu)只有2個(gè)成員對于編寫驅(qū)動代碼有用:dev_ti_rdev:對表示設(shè)備文件的inode結(jié)構(gòu),這個(gè)成員包含實(shí)際的設(shè)備編號structcdev*i_cdev:代表字符設(shè)備;當(dāng)節(jié)點(diǎn)指的是一個(gè)字符設(shè)備文件時(shí),這個(gè)成員包含一個(gè)指針,指向這個(gè)結(jié)構(gòu)。從一個(gè)inode中獲取主次編號:unsignedintiminor(structinode*inode);unsignedintimajor(structinode*inode);字符設(shè)備驅(qū)動Linux字符設(shè)備驅(qū)動結(jié)構(gòu)注冊設(shè)備,在模塊或驅(qū)動初始化時(shí)調(diào)用Linux2.4及之前:Linux2.6:intregister_chrdev(unsignedintmajor,constchar*name, structfile_operations*fops)voidcdev_init(structcdev*,structfile_operations*);intcdev_add(structcdev*,dev_t,unsigned);在運(yùn)行時(shí)獲取一個(gè)獨(dú)立的cdev結(jié)構(gòu)該設(shè)備關(guān)聯(lián)的設(shè)備編號的數(shù)量驅(qū)動程序沒有完全準(zhǔn)備好處理設(shè)備上的操作,不能調(diào)用cdev_add字符設(shè)備驅(qū)動Linux字符設(shè)備驅(qū)動結(jié)構(gòu)注銷設(shè)備,在模塊或驅(qū)動卸載時(shí)調(diào)用Linux2.4及之前:Linux2.6:intunregister_chrdev(unsignedintmajor, constchar*name);voidcdev_del(structcdev*);字符設(shè)備驅(qū)動Linux字符設(shè)備驅(qū)動結(jié)構(gòu)//設(shè)備驅(qū)動模塊加載函數(shù)staticint__initxxx_init(void){ ... cdev_init(&xxx_dev.cdev,&xxx_fops);//初始化cdev xxx_dev.cdev.owner=THIS_MODULE; //獲取字符設(shè)備號 if(xxx_major) { register_chrdev_region(xxx_dev_no,1,DEV_NAME); } else { alloc_chrdev_region(&xxx_dev_no,0,1,DEV_NAME); } ret=cdev_add(&xxx_dev.cdev,xxx_dev_no,1);//注冊設(shè)備 ...}字符設(shè)備驅(qū)動Linux字符設(shè)備驅(qū)動結(jié)構(gòu)/*設(shè)備驅(qū)動模塊卸載函數(shù)*/staticvoid__exitxxx_exit(void){ unregister_chrdev_region(xxx_dev_no,1);//釋放占用的設(shè)備號
cdev_del(&xxx_dev.cdev);//注銷設(shè)備 ...}字符設(shè)備驅(qū)動Linux字符設(shè)備驅(qū)動結(jié)構(gòu)設(shè)備的打開open應(yīng)當(dāng)進(jìn)行下面的工作:1)檢查設(shè)備特定的錯(cuò)誤(例如設(shè)備沒準(zhǔn)備好,或者類似的硬件錯(cuò)誤
2)如果它第一次打開,初始化設(shè)備
3)如果需要,更新f_op指針,模塊計(jì)數(shù)加1 4)分配并填充要放進(jìn)filp->private_data的任何數(shù)據(jù)結(jié)構(gòu)。
5)識別次設(shè)備號
6)如果有中斷操作,申請中斷處理程序。intopen(structinode*inode,structfile*filp);字符設(shè)備驅(qū)動Linux字符設(shè)備驅(qū)動結(jié)構(gòu)設(shè)備的關(guān)閉release方法在應(yīng)用程序調(diào)用close()系統(tǒng)調(diào)用時(shí)被調(diào)用,它的角色是open的反面. 1)釋放open分配在filp->private_data中的任何東西
2)在最后的close關(guān)閉設(shè)備,模塊計(jì)數(shù)減1
3)如果申請了中斷,則釋放中斷處理程序.intrelease(structinode*inode,structfile*filp);字符設(shè)備驅(qū)動Linux字符設(shè)備驅(qū)動結(jié)構(gòu)read和writessize_tread(structfile*filp,char__user*buff,size_tcount,loff_t*offp);ssize_twrite(structfile*filp,constchar__user*buff,size_tcount,loff_t*offp);指向用戶空間的緩沖區(qū),這個(gè)緩沖區(qū)或者保存將寫入的數(shù)據(jù),或者是一個(gè)存放新讀入數(shù)據(jù)的空緩沖區(qū)。用戶在文件中存取操作的位置buff參數(shù)是用戶空間指針,內(nèi)核代碼不能直接引用其中的內(nèi)容。字符設(shè)備驅(qū)動Linux字符設(shè)備驅(qū)動結(jié)構(gòu)用戶空間與內(nèi)核空間的數(shù)據(jù)拷貝不能簡單的用指針操作或者memcpy來進(jìn)行數(shù)據(jù)拷貝,要用內(nèi)核函數(shù)如果要復(fù)制的內(nèi)存是簡單類型,如char、int、long等,用put_user()和get_user()unsignedlongcopy_from_user(void*to,constvoid__user*from,unsignedlongcount);unsignedlongcopy_to_user(void__user*to,constvoid*from,unsignedlongcount);字符設(shè)備驅(qū)動Linux字符設(shè)備驅(qū)動結(jié)構(gòu)讀設(shè)備模板ssize_t
xxx_read(structfile*filp,char__user*buf,
size_tcount,loff_t*f_pos){ ...
copy_to_user(buf,...,...); ...}寫設(shè)備模板
ssize_t
xxx_write(structfile*filp,constchar__user*buf,
size_tcount,loff_t*f_pos){ ...
copy_from_user(...,buf,...); ...}字符設(shè)備驅(qū)動Linux字符設(shè)備驅(qū)動結(jié)構(gòu)ioctl函數(shù)ioctl函數(shù)主要完成以下兩個(gè)功能:
1)為設(shè)備驅(qū)動程序執(zhí)行“命令”提供了一個(gè)特有的入口點(diǎn)
2)用來設(shè)置或者讀取設(shè)備的屬性信息
intioctl(structinode*inode,structfile*filp, unsignedintcmd,unsignedlongarg);事先定義的IO控制命令代碼arg為對應(yīng)于cmd命令的參數(shù)字符設(shè)備驅(qū)動Linux字符設(shè)備驅(qū)動結(jié)構(gòu)cmd參數(shù)的定義不推薦用0x1,0x2,0x3之類的值,會導(dǎo)致不同的設(shè)備驅(qū)動擁有相同的命令號。Linux對ioctl()的cmd參數(shù)有特殊的定義
設(shè)備類型(type)
序列號(number)方向(direction)
數(shù)據(jù)尺寸(size)
8bit
8bit
2bit13/14bit字符設(shè)備驅(qū)動Linux字符設(shè)備驅(qū)動結(jié)構(gòu)cmd參數(shù)的定義內(nèi)核還定義了以下四個(gè)宏來輔助生成命令:IO(type,nr)用于構(gòu)造無參數(shù)的命令編號;_IOR(type,nr,datatype)用于構(gòu)造從驅(qū)動程序中讀取數(shù)據(jù)的命令編號
溫馨提示
- 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)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- DB31/T 478.17-2014主要工業(yè)產(chǎn)品用水定額及其計(jì)算方法第17部分:倉儲
- DB31/T 1373-2022海三棱藨草種群生態(tài)修復(fù)技術(shù)規(guī)程
- DB31/T 1190.2-2019蔬菜病蟲害綠色防控技術(shù)規(guī)范第2部分:殺蟲燈
- 2025房屋租賃合同范本全面版
- 設(shè)計(jì)溝通與表達(dá)技巧考核試卷
- 2024年垃圾前端收轉(zhuǎn)裝備項(xiàng)目投資申請報(bào)告代可行性研究報(bào)告
- 2024年紙品清潔資金申請報(bào)告代可行性研究報(bào)告
- 網(wǎng)絡(luò)安全考試技巧與試題
- 老舊小區(qū)電梯加裝與安全檢測服務(wù)協(xié)議
- 智能家居暖通系統(tǒng)定制設(shè)計(jì)與施工協(xié)議
- 標(biāo)本的運(yùn)送流程課件
- 汽車租賃公司汽車租賃管理制度匯編
- 脊髓損傷康復(fù)講義
- 布草洗滌服務(wù)方案完整版
- 氣體安全知識培訓(xùn)(72張)課件
- 共線向量與共面向量全面版課件
- JJG(晉) 22-2021 車用甲醇燃料加注機(jī)檢定規(guī)程
- 湘美版小學(xué)四年級美術(shù)下冊知識點(diǎn)
- 大連市住宅小區(qū)物業(yè)收費(fèi)等級標(biāo)準(zhǔn)
- 包裝自動線課程設(shè)計(jì)含全套資料
- 長輸管道施工
評論
0/150
提交評論