版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、ucos+lwip應(yīng)用心得社區(qū) 經(jīng)過(guò)幾天調(diào)試除掉幾個(gè)bug以后,ucos+lwip在我的44b0+8019開(kāi)發(fā)板上終于跑得比較穩(wěn)定了.一只覺(jué)得lwip是一個(gè)不錯(cuò)的開(kāi)放源碼的tcp/ip 協(xié)議棧,想把自己對(duì)lwip的移植和理解寫(xiě)出來(lái).但是由于最近比較忙,lwip的移植也是利用業(yè)余時(shí)間做的,今天寫(xiě)好了第一部分(lwip的 process model)先貼上來(lái),如果大家有興趣我再接著往下寫(xiě).另外我的移植參看了sk
2、yeye揚(yáng)曄大俠的代碼,大家可以去看看揚(yáng)曄大俠的lwip在ucos上移植的文章和代碼. lwip應(yīng)用心得 lwIP是瑞士計(jì)算機(jī)科學(xué)院(Swedish Institute of Computer Science)的Adam Dunkels等開(kāi)發(fā)的一套用于嵌入式系統(tǒng)的開(kāi)放源代碼TCP/IP協(xié)議棧。Lwip既可以移植到操作系統(tǒng)上,又可以在無(wú)操作系統(tǒng)的情況下獨(dú)立運(yùn)行. &
3、#160; LwIP的特性如下:(1) 支持多網(wǎng)絡(luò)接口下的IP轉(zhuǎn)發(fā)(2) 支持ICMP協(xié)議 (3) 包括實(shí)驗(yàn)性擴(kuò)展的的UDP(用戶數(shù)據(jù)報(bào)協(xié)議)(4) 包括阻塞控制,RTT估算和快速恢復(fù)和快速轉(zhuǎn)發(fā)的TCP(傳輸控制協(xié)
4、議)(5) 提供專門的內(nèi)部回調(diào)接口(Raw API)用于提高應(yīng)用程序性能(6) 可選擇的Berkeley接口API(多線程情況下)(7) 在最新的版本中支持ppp(8) 新版本中增加了的IP fragment的支持.(9) 支持DHCP協(xié)議,動(dòng)態(tài)分配ip地址.現(xiàn)在網(wǎng)上最新的版本是V0.6.4
5、60;1.lwip的進(jìn)程模型(process model) tcp/ip協(xié)議棧的process model一般有幾種方式. 1.tcp/ip協(xié)議的每一層是一個(gè)單獨(dú)進(jìn)程.鏈路層是一個(gè)進(jìn)程,ip層是一個(gè)進(jìn)程,tcp層是一個(gè)進(jìn)程.這樣的好處是網(wǎng)絡(luò)協(xié) 議的每一層都非常清晰,代碼的調(diào)試和理解都非常容易.但是最大的壞處數(shù)據(jù)跨層傳遞時(shí)會(huì)引起上下文切換(c
6、ontext switch). 對(duì)于接收一個(gè)TCP segment要引起3次context switch(從網(wǎng)卡驅(qū)動(dòng)程序到鏈路層進(jìn)程,從鏈路層進(jìn)程到ip層進(jìn)程,從ip層進(jìn)程 到TCP進(jìn)程).通常對(duì)于操作系統(tǒng)來(lái)說(shuō),任務(wù)切換是要浪費(fèi)時(shí)間的.過(guò)頻的context swich是不可取的. 2.另外一種方式是TCP/IP協(xié)議棧
7、在操作系統(tǒng)內(nèi)核當(dāng)中.應(yīng)用程序通過(guò)操作系統(tǒng)的系統(tǒng)調(diào)用(system call)和協(xié)議棧來(lái)進(jìn)行通訊. 這樣TCP/IP的協(xié)議棧就限定于特定的操作系統(tǒng)內(nèi)核了.如windows就是這種方式. 3.lwip的process model:所有tcp/ip協(xié)議棧都在一個(gè)進(jìn)程當(dāng)中,這樣tcp/ip協(xié)議棧就和操作系統(tǒng)內(nèi)核分開(kāi)了.而應(yīng)用層程序既可以
8、; 是單獨(dú)的進(jìn)程也可以駐留在tcp/ip進(jìn)程中.如果應(yīng)用程序是單獨(dú)的進(jìn)程可以通過(guò)操作系統(tǒng)的郵箱,消息隊(duì)列等和tcp/ip進(jìn)程進(jìn)行通訊. 如果應(yīng)用層程序駐留tcp/ip進(jìn)程中,那應(yīng)用層程序就利用內(nèi)部回調(diào)函數(shù)口(Raw API)和tcp/ip協(xié)議棧通訊.對(duì)于ucos來(lái)說(shuō)進(jìn)程就是一個(gè)系統(tǒng)任務(wù).lwip的process model請(qǐng)參看下圖.在圖中可以看到整個(gè)tcp/ip協(xié)議棧都在同一個(gè)任務(wù)(tcpip_thread)中.應(yīng)用層程序既可以是獨(dú)立的任務(wù)(
9、如圖中的tftp_thread,tcpecho_thread),也可以在tcpip_thread中(如圖左上角)中利用內(nèi)部回調(diào)函數(shù)口(Raw API)和tcp/ip協(xié)議棧通訊 2 Port Lwip to uCos 在這個(gè)項(xiàng)目中我用的硬件平臺(tái)是s3c44b0x+rtl8019.ucos在44b0上的移植在網(wǎng)上有很多大俠非常詳盡的講解和移植代碼.我就不敢羅嗦了.需要說(shuō)明的一點(diǎn)是lwip會(huì)為每個(gè)網(wǎng)絡(luò)連接動(dòng)態(tài)分配一些信號(hào)量(semaphone)和消
10、息隊(duì)列(Message Queue),當(dāng)連接斷開(kāi)時(shí)會(huì)刪掉這些semaphone和Queue.而Ucos-2.0不支持semaphone和Queue的刪除,所以要選擇一些較高版本的ucos.我用的是ucos-2.51. 2.1 Lwip的操作系統(tǒng)封裝層(operating system.emulation layer) Lwip為了適應(yīng)不同的操作系統(tǒng),在代碼中沒(méi)有使用和某一個(gè)操作系統(tǒng)相關(guān)的系統(tǒng)調(diào)用和數(shù)據(jù)結(jié)構(gòu).而是在lwip和操作系統(tǒng)之間增加了一個(gè)操作系統(tǒng)封裝
11、層.操作系統(tǒng)封裝層為操作系統(tǒng)服務(wù)(定時(shí),進(jìn)程同步,消息傳遞)提供了一個(gè)統(tǒng)一的接口.在lwip中進(jìn)程同步使用semaphone和消息傳遞采用”mbox”(其實(shí)在ucos的實(shí)現(xiàn)中我們使用的是Message Queue來(lái)實(shí)現(xiàn)lwip中的”mbox”,下面大家可以看到這一點(diǎn))Operating system emulation layer的原代碼在/lwip/src/core/sys.c中.而和具體的操作系統(tǒng)相關(guān)的代碼在./lwip/src/arch/sys_arch.c中.操作系統(tǒng)封裝層的主要函數(shù)如下:void sys_init(void)/系統(tǒng)初始化sys_thread_t sys_thread_
12、new(void (* function)(void *arg), void *arg,int prio)/創(chuàng)建一個(gè)新進(jìn)程 sys_mbox_t sys_mbox_new(void)/創(chuàng)建一個(gè)郵箱 void sys_mbox_free(sys_mbox_t mbox)/釋放并刪除一個(gè)郵箱 void sys_mbox_post(sys_mbox_t mbox, void *data) /發(fā)送一個(gè)消息到郵箱 void sys_mbox_fetch(sys_mbox_t
13、 mbox, void *msg)/等待郵箱中的消息 sys_sem_t sys_sem_new(u8_t count)/創(chuàng)建一個(gè)信號(hào)量void sys_sem_free(sys_sem_t sem)/釋放并刪除一個(gè)信號(hào)量void sys_sem_signal(sys_sem_t sem)/發(fā)送一個(gè)信號(hào)量void sys_sem_wait(sys_sem_t sem)/等待一個(gè)信號(hào)量 void sys_timeout(u32_t msecs, sys_timeout_handler h, void *arg)/設(shè)置一個(gè)超時(shí)事件
14、void sys_untimeout(sys_timeout_handler h, void *arg)/刪除一個(gè)超時(shí)事件 關(guān)于操作系統(tǒng)封裝層的信息可以閱讀lwip的doc目錄下面的sys_arch.txt.文件.2.2 Lwip在ucos上的移植.2.2.1 系統(tǒng)初始化 sys_int必須在tcpip協(xié)議棧任務(wù)tcpip_thread創(chuàng)建前被調(diào)用. #define MAX_QUEUES 20#define MAX_QUEU
15、E_ENTRIES 20typedef struct OS_EVENT* pQ;/ucos中指向事件控制塊的指針 void* pvQEntriesMAX_QUEUE_ENTRIES;/消息隊(duì)列/MAX_QUEUE_ENTRIES消息隊(duì)列中最多消息數(shù) TQ_DESCR, *PQ_DESCR;typedef PQ_DESCR
16、;sys_mbox_t;/可見(jiàn)lwip中的mbox其實(shí)是ucos的消息隊(duì)列static char pcQueueMemoryPoolMAX_QUEUES * sizeof(TQ_DESCR) ; void sys_init(void) u8_t i; s8_t ucErr; pQueueMem =
17、 OSMemCreate( (void*)pcQueueMemoryPool, MAX_QUEUES, sizeof(TQ_DESCR), &ucErr );/為消息隊(duì)列創(chuàng)建內(nèi)存分區(qū) /init lwip task prio offset curr_prio_offset = 0; /init lwip_timeouts for every lwip task /初始化lwip定時(shí)事件表,具體實(shí)現(xiàn)參考下面
18、章節(jié) for(i=0;i<LWIP_TASK_MAX;i+) lwip_timeoutsi.next = NULL; 2.2.2 創(chuàng)建一個(gè)和tcp/ip相關(guān)新進(jìn)程:lwip中的進(jìn)程就是ucos中的任務(wù),創(chuàng)建一個(gè)新進(jìn)程的代碼如下:#define LWIP_STK_SIZE 10*1024/和tcp/ip相關(guān)任務(wù)的堆棧大小.可以根據(jù)情況自/
19、己設(shè)置,44b0開(kāi)發(fā)板上有8M的sdram,所以設(shè)大/一點(diǎn)也沒(méi)有關(guān)系:)/max number of lwip tasks#define LWIP_TASK_MAX 5 /和tcp/ip相關(guān)的任務(wù)最多數(shù)目/first prio of lwip tasks#define LWIP_START_PRIO 5 /和tcp/ip相關(guān)任務(wù)的起始優(yōu)先級(jí),在本例中優(yōu)先級(jí)可/以從(5-9).注意tcpip_thread在所有tcp/ip相關(guān)進(jìn)程中/應(yīng)該是優(yōu)先級(jí)最高的.在本例中就是優(yōu)先級(jí)5 /如果用戶需要?jiǎng)?chuàng)建和tcp/ip無(wú)關(guān)任務(wù),
20、如uart任務(wù)等,/不要使用5-9的優(yōu)先級(jí) OS_STK LWIP_TASK_STKLWIP_TASK_MAXLWIP_STK_SIZE;/和tcp/ip相關(guān)進(jìn)程/的堆棧區(qū) u8_t curr_prio_offset ; sys_thread_t sys_thread_new(void (* function)(void *arg), void *arg,int prio) if(curr_prio_offset
21、 < LWIP_TASK_MAX) OSTaskCreate(function,(void*)0x1111, &LWIP_TASK_STKcurr_prio_offsetLWIP_STK_SIZE-1,LWIP_START_PRIO+curr_prio_offset ); curr_prio_offset+; return 1; else / PR
22、INT(" lwip task prio out of range ! error! "); 從代碼中可以看出tcpip_thread應(yīng)該是最先創(chuàng)建的. 2.2.3 Lwip中的定時(shí)事件 在tcp/ip協(xié)議中很多時(shí)候都要用到定時(shí),定時(shí)的實(shí)現(xiàn)也是tcp/ip協(xié)議棧中一個(gè)重要的部分.lwip中定時(shí)事件的數(shù)據(jù)結(jié)構(gòu)如下. struct sys_timeout struct sys_timeout *next;/指向下一個(gè)定時(shí)結(jié)構(gòu) u3
23、2_t time;/定時(shí)時(shí)間 sys_timeout_handler h;/定時(shí)時(shí)間到后執(zhí)行的函數(shù) void *arg;/定時(shí)時(shí)間到后執(zhí)行函數(shù)的參數(shù).;struct sys_timeouts struct sys_timeout *next;struct sys_timeouts lwip_timeoutsLWIP_TASK_MAX;Lwip中的定時(shí)事件表的結(jié)構(gòu)如下圖,每個(gè)和tcp/ip相關(guān)的任務(wù)的一系列定時(shí)事件組成一個(gè)單向鏈表.每個(gè)鏈表的起始指針存在lwip_timeouts的對(duì)應(yīng)表項(xiàng)中.
24、 函數(shù)sys_arch_timeouts返回對(duì)應(yīng)于當(dāng)前任務(wù)的指向定時(shí)事件鏈表的起始指針.該指針存在lwip_timeoutsMAX_LWIP_TASKS中.struct sys_timeouts null_timeouts;struct sys_timeouts * sys_arch_timeouts(void) u8_t curr_prio; s16_t err,offset;OS_T
25、CB curr_task_pcb; null_timeouts.next = NULL; /獲取當(dāng)前任務(wù)的優(yōu)先級(jí) err = OSTaskQuery(OS_PRIO_SELF,&curr_task_pcb); curr_prio = curr_task_pcb.OSTCBPrio; offset = curr_prio - LWIP_START_PRIO; /判斷當(dāng)前任務(wù)優(yōu)先級(jí)是不是tcp/ip相關(guān)任務(wù),優(yōu)先級(jí)5-9
26、160;if(offset < 0 | offset >= LWIP_TASK_MAX) return &null_timeouts; return &lwip_timeoutsoffset; 注意:楊曄大俠移植的代碼在本函數(shù)有一個(gè)bug.楊曄大俠的移植把上面函數(shù)中的OS_TCB curr_task_tcb定義成了全局變量,使本函數(shù)成為了一個(gè)不可
27、重入函數(shù).我也是在進(jìn)行如下測(cè)試時(shí)發(fā)現(xiàn)了這個(gè)bug.我的開(kāi)發(fā)板上設(shè)置的ip地址是5.我在windows的dos窗口內(nèi)運(yùn)行 ping 5 l 2000 t,不間斷用長(zhǎng)度為2000的數(shù)據(jù)報(bào)進(jìn)行ping測(cè)試,同時(shí)使用tftp客戶端軟件給5下載一個(gè)十幾兆程序,同時(shí)再使用telnet連接5端口7(echo端口),往該端口寫(xiě)數(shù)測(cè)試echo功能. 在運(yùn)行一段時(shí)間以后,開(kāi)發(fā)板
28、進(jìn)入不再響應(yīng).我當(dāng)時(shí)也是經(jīng)過(guò)長(zhǎng)時(shí)間的分析才發(fā)現(xiàn)是因?yàn)樵诘蛢?yōu)先級(jí)任務(wù)運(yùn)行ys_arch_timeouts()時(shí)被高優(yōu)先級(jí)任務(wù)打斷改寫(xiě)了curr_task_tcb的值,從而使sys_arch_timeouts返回的指針錯(cuò)誤,進(jìn)而導(dǎo)致系統(tǒng)死鎖.函數(shù)sys_timeout給當(dāng)前任務(wù)增加一個(gè)定時(shí)事件:void sys_timeout(u32_t msecs, sys_timeout_handler h, void *arg) struct sys_timeouts *timeouts; struct sys_timeout *timeout, *t;
29、; timeout = memp_malloc(MEMP_SYS_TIMEOUT);/為定時(shí)事件分配內(nèi)存 if (timeout = NULL) return; timeout->next = NULL; timeout->h = h; timeout->arg = arg; timeout->time = msecs; timeouts = sys_arch
30、_timeouts();/返回當(dāng)前任務(wù)定時(shí)事件鏈表起始指針 if (timeouts->next = NULL) /如果鏈表為空直接增加該定時(shí)事件 timeouts->next = timeout; return; /如果鏈表不為空,對(duì)定時(shí)事件進(jìn)行排序.注意定時(shí)事件中的time存儲(chǔ)的是本事件/時(shí)間相對(duì)于前一事件的時(shí)間的差值 if (timeouts->next->time >
31、; msecs) timeouts->next->time -= msecs; timeout->next = timeouts->next; timeouts->next = timeout; else for(t = timeouts->next; t != NULL; t = t->next)
32、0; timeout->time -= t->time; if (t->next = NULL | t->next->time > timeout->time) if (t->next != NULL) t->next->time -= timeout->time; timeout->
33、;next = t->next; t->next = timeout; break; 函數(shù)sys_untimeout從當(dāng)前任務(wù)定時(shí)事件鏈表中刪除一個(gè)定時(shí)事件void sys_untimeout(sys_timeout_handler h, void *arg) struct sys_timeouts *timeouts;
34、; struct sys_timeout *prev_t, *t; timeouts = sys_arch_timeouts();/返回當(dāng)前任務(wù)定時(shí)事件鏈表起始指針 if (timeouts->next = NULL)/如果鏈表為空直接返回 return;
35、; /查找對(duì)應(yīng)定時(shí)事件并從鏈表中刪除. for (t = timeouts->next, prev_t = NULL; t != NULL; prev_t = t, t = t->next) if (t->h = h) && (t->arg = arg)
36、 /* We have a match */ /* Unlink from previous in list */
37、; if (prev_t = NULL) timeouts->next = t->next; else
38、 prev_t->next = t->next; /* If not the last one, add time of this one back to next */ if (t->next != NULL)
39、160; t->next->time += t->time; memp_free(MEMP_SYS_TIMEOUT, t); return;
40、160; return;2.2.3 “mbox”的實(shí)現(xiàn): (1)mbox的創(chuàng)建
41、 sys_mbox_t sys_mbox_new(void) u8_t ucErr; PQ_DESCR pQDesc; /從消息隊(duì)列內(nèi)存分區(qū)中得到一個(gè)內(nèi)存塊
42、 pQDesc = OSMemGet( pQueueMem, &ucErr ); if( ucErr = OS_NO_ERR ) /創(chuàng)建一個(gè)消息隊(duì)列 pQDesc->pQ=OSQCreate(&(pQDesc-&
43、gt;pvQEntries0), MAX_QUEUE_ENTRIES ); if( pQDesc->pQ != NULL ) return pQDesc;
44、; return SYS_MBOX_NULL; (2)發(fā)一條消息給”mbox” const void * const pvNullPointer = 0xffffffff;void sys_mbox_post(sys_mbox_t mbox, void *data) INT8U err;
45、160; if( !data ) data = (void*)&pvNullPointer; err= OSQPost( mbox->pQ, data);在ucos中,如果OSQPost (OS_EVENT *pevent, void *msg)中的msg=NULL 會(huì)返回一條OS_ERR_POST_NULL_PTR錯(cuò)誤.而在lwip中會(huì)調(diào)用sys_mbox_post(mbox,NULL)發(fā)送一條空消息,我們?cè)诒竞瘮?shù)中把NULL變成一個(gè)常量指針0xfff
46、fffff. (3)從”mbox”中讀取一條消息#define SYS_ARCH_TIMEOUT 0xffffffffvoid sys_mbox_fetch(sys_mbox_t mbox, void *msg) u32_t time; struct sys_timeouts *timeouts; struct sys_timeout *tmptimeout; sys_timeout_handler h; void *arg;again:&
47、#160; timeouts = sys_arch_timeouts();/返回當(dāng)前任務(wù)定時(shí)事件鏈表起始指針 if (!timeouts | !timeouts->next) /如果定時(shí)事件鏈表為空 sys_arch_mbox_fetch(mbox, msg, 0);/無(wú)超時(shí)等待消息 else if (timeouts->next->time > 0) /如果超時(shí)事件鏈表不為空,而且第一
48、個(gè)超時(shí)事件的time !=0/帶超時(shí)等待消息隊(duì)列,超時(shí)時(shí)間等于超時(shí)事件鏈表中第一個(gè)超時(shí)事件的time, time = sys_arch_mbox_fetch(mbox, msg, timeouts->next->time); /在后面分析中可以看到sys_arch_mbox_fetch調(diào)用了ucos中的OSQPend系統(tǒng)調(diào)/用從消息隊(duì)列中讀取消息./如果”mbox”消息隊(duì)列不為空,任務(wù)立刻返回,否則任務(wù)進(jìn)入阻塞態(tài)./需要重點(diǎn)說(shuō)明的是sys_arch_mbo
49、x_fetch的返回值time:如果sys_arch_mbox_fetch/因?yàn)槌瑫r(shí)返回,time=SYS_ARCH_TIMEOUT,/如果sys_arch_mbox_fetch因?yàn)槭盏较⒍祷?/time = 收到消息時(shí)刻的時(shí)間-執(zhí)行sys_arch_mbox_fetch時(shí)刻的時(shí)間,單位是毫秒/由于在ucos中任務(wù)調(diào)用OSQPend系統(tǒng)調(diào)用進(jìn)入阻塞態(tài),到收到消息重新開(kāi)始執(zhí)行/這段時(shí)間沒(méi)有記錄下來(lái),所以我們要簡(jiǎn)單修改ucos的源代碼.(后面我們會(huì)看到). else /如果定
50、時(shí)事件鏈表不為空,而且第一個(gè)定時(shí)事件的time =0,表示該事件的定時(shí)/時(shí)間到 time = SYS_ARCH_TIMEOUT; if (time = SYS_ARCH_TIMEOUT) /一個(gè)定時(shí)事件的定時(shí)時(shí)間到 tmptimeout = timeouts->next;
51、160; timeouts->next = tmptimeout->next; h = tmptimeout->h; arg = tmptimeout->arg; memp_free(MEMP_SYS_TIMEOUT, tmptimeout); /從內(nèi)存中釋放該
52、定時(shí)事件,并執(zhí)行該定時(shí)事件中的函數(shù) if (h != NULL) h(arg); /因?yàn)槎〞r(shí)事件中的定時(shí)時(shí)間到或者是因?yàn)閟ys_arch_mbo_fetch超時(shí)到而執(zhí)行到/這里,返回本函數(shù)開(kāi)頭重新等待mbox的消息
53、60;goto again; else /如果sys_arch_mbox_fetch無(wú)超時(shí)收到消息返回/則刷新定時(shí)事件鏈表中定時(shí)事件的time值. if (time <= timeouts->next->time) timeouts->next->time -= time; else
54、;timeouts->next->time = 0; u32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void *data, u32_t timeout) u32_t ucErr; u16_t ucos_timeout; /在 lwip中 ,timeout的單位是ms / 在ucosII ,timeout 的單位是timer tick ucos_timeout = 0; if(timeout != 0) ucos_timeout = (timeout )*( OS_TICKS_PER_SEC/1000); if(ucos_timeout < 1)
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 食品加工行業(yè)安全生產(chǎn)工作總結(jié)
- 2024年標(biāo)準(zhǔn)合同履行確認(rèn)保證合同版B版
- 2024年度大米產(chǎn)業(yè)鏈冷鏈物流合作協(xié)議3篇
- 語(yǔ)文高考押題專題二:語(yǔ)言運(yùn)用
- 新娘父親婚禮致辭
- 法學(xué)課程設(shè)計(jì)模擬法庭
- 放假留校學(xué)生安全責(zé)任保證書(shū)
- 2024年度員工敬業(yè)責(zé)任與職業(yè)發(fā)展通道建設(shè)合同3篇
- 文化藝術(shù)節(jié)活動(dòng)的策劃書(shū)(5篇)
- 護(hù)士個(gè)人工作調(diào)動(dòng)申請(qǐng)書(shū)
- 《爆破理論基礎(chǔ)》課件
- 期末測(cè)試題二(含答案)2024-2025學(xué)年譯林版七年級(jí)英語(yǔ)上冊(cè)
- 中國(guó)成人失眠診斷與治療指南(2023版)解讀
- 小兒咳嗽推拿治療
- 產(chǎn)品質(zhì)量知識(shí)培訓(xùn)課件
- 乳腺旋切手術(shù)
- 醫(yī)護(hù)禮儀課件教學(xué)課件
- 2023年中國(guó)奧特萊斯行業(yè)白皮書(shū)
- 動(dòng)態(tài)血壓課件教學(xué)課件
- 八上必讀名著《紅星照耀中國(guó)》要點(diǎn)梳理與練習(xí)
- 2024年山東省春季招生高三模擬考試語(yǔ)文試題(含答案解析)
評(píng)論
0/150
提交評(píng)論