![linux進(jìn)程和線程編程_第1頁](http://file4.renrendoc.com/view/491980b81f526b6e337351f0beac6b47/491980b81f526b6e337351f0beac6b471.gif)
![linux進(jìn)程和線程編程_第2頁](http://file4.renrendoc.com/view/491980b81f526b6e337351f0beac6b47/491980b81f526b6e337351f0beac6b472.gif)
![linux進(jìn)程和線程編程_第3頁](http://file4.renrendoc.com/view/491980b81f526b6e337351f0beac6b47/491980b81f526b6e337351f0beac6b473.gif)
![linux進(jìn)程和線程編程_第4頁](http://file4.renrendoc.com/view/491980b81f526b6e337351f0beac6b47/491980b81f526b6e337351f0beac6b474.gif)
![linux進(jìn)程和線程編程_第5頁](http://file4.renrendoc.com/view/491980b81f526b6e337351f0beac6b47/491980b81f526b6e337351f0beac6b475.gif)
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
Linux進(jìn)程和線程編程1、Linux中的進(jìn)程相關(guān)概念2、Linux中的進(jìn)程的創(chuàng)建3、Linux中的進(jìn)程的管理和守護(hù)進(jìn)程6.1進(jìn)程的概述時(shí)間和空間是計(jì)算機(jī)的兩個(gè)概念,操作系統(tǒng)將者兩個(gè)概念實(shí)現(xiàn)為文件和進(jìn)程。進(jìn)程是一個(gè)可以獨(dú)立的可有OS調(diào)度的活動(dòng)。進(jìn)程是一個(gè)抽象實(shí)體,當(dāng)它執(zhí)行的時(shí)候需要OS分配資源。進(jìn)程是一個(gè)正在執(zhí)行的程序。進(jìn)程是一個(gè)程序的一次執(zhí)行。進(jìn)程是一個(gè)具有一定獨(dú)立功能的程序關(guān)于某個(gè)數(shù)據(jù)集合的一次運(yùn)行活動(dòng)。它是操作系統(tǒng)動(dòng)態(tài)執(zhí)行的基本單元,在傳統(tǒng)的操作系統(tǒng)中,進(jìn)程既是基本的分配單元,也是基本的執(zhí)行單元6.1進(jìn)程的概述進(jìn)程的概念主要有兩點(diǎn):第一,進(jìn)程是一個(gè)實(shí)體。每一個(gè)進(jìn)程都有它自己的地址空間,一般情況下,包括文本區(qū)域(textregion)、數(shù)據(jù)區(qū)域(dataregion)和堆棧(stackregion)。文本區(qū)域存儲(chǔ)處理器執(zhí)行的代碼;數(shù)據(jù)區(qū)域存儲(chǔ)變量和進(jìn)程執(zhí)行期間使用的動(dòng)態(tài)分配的內(nèi)存;堆棧區(qū)域存儲(chǔ)著活動(dòng)過程調(diào)用的指令和本地變量。第二,進(jìn)程是一個(gè)“執(zhí)行中的程序”。程序是一個(gè)沒有生命的實(shí)體,只有處理器賦予程序生命時(shí),它才能成為一個(gè)活動(dòng)的實(shí)體,我們稱其為進(jìn)程。進(jìn)程是操作系統(tǒng)中最基本、重要的概念。是多道程序系統(tǒng)出現(xiàn)后,為了刻畫系統(tǒng)內(nèi)部出現(xiàn)的動(dòng)態(tài)情況,描述系統(tǒng)內(nèi)部各道程序的活動(dòng)規(guī)律引進(jìn)的一個(gè)概念,所有多道程序設(shè)計(jì)操作系統(tǒng)都建立在進(jìn)程的基礎(chǔ)上。原因原因原因原因操作系統(tǒng)引入進(jìn)程的概念的原因:從理論角度看,是對(duì)正在運(yùn)行的程序過程的抽象;從實(shí)現(xiàn)角度看,是一種數(shù)據(jù)結(jié)構(gòu),目的在于清晰地刻劃動(dòng)態(tài)系統(tǒng)的內(nèi)在規(guī)律,有效管理和調(diào)度進(jìn)入計(jì)算機(jī)系統(tǒng)主存儲(chǔ)器運(yùn)行的程序。6.1.1進(jìn)程的描述進(jìn)程的種類交互進(jìn)程:由一個(gè)Shell啟動(dòng)的進(jìn)程,交互進(jìn)程既可以在前臺(tái)運(yùn)行,也可以在后臺(tái)運(yùn)行。
批處理進(jìn)程:這種進(jìn)程和終端沒有聯(lián)系,是一個(gè)進(jìn)程序列。監(jiān)控進(jìn)程:也稱守護(hù)進(jìn)程,Linux系統(tǒng)啟動(dòng)是啟動(dòng)的進(jìn)程,并在后臺(tái)運(yùn)行。進(jìn)程不但包括程序指令和數(shù)據(jù),還包括程序計(jì)數(shù)器和CPU的所有寄存器及其存儲(chǔ)臨時(shí)數(shù)據(jù)的進(jìn)程堆棧。Linux是一個(gè)多進(jìn)程OS,其他進(jìn)程必須等到當(dāng)前正在執(zhí)行的進(jìn)程交出CPU的控制權(quán)后才能被內(nèi)核調(diào)度執(zhí)行。當(dāng)正在運(yùn)行的進(jìn)程等待其他系統(tǒng)資源時(shí),linux內(nèi)核獲得CPU的控制權(quán),并將CPU分配給其他正在等待的進(jìn)程,內(nèi)核中的調(diào)度算法決定將CPU分配給那個(gè)進(jìn)程。內(nèi)存是計(jì)算機(jī)的敏感資源,熟練掌握對(duì)內(nèi)存的操作是一個(gè)程序員的必備素質(zhì)。數(shù)據(jù)的內(nèi)部存儲(chǔ)方式:大小端法在c中,不同的數(shù)據(jù)類型占用的空間是不同的,例如char類型占用1個(gè)字節(jié),而int占用4個(gè)字節(jié)高785634低12345612786.1.1進(jìn)程的描述-進(jìn)程內(nèi)存管理-數(shù)據(jù)內(nèi)部存儲(chǔ)時(shí)間和空間是計(jì)算機(jī)的兩個(gè)基本的概念,操作系統(tǒng)將這兩個(gè)概念實(shí)現(xiàn)未進(jìn)程和文件,。進(jìn)程ID是一個(gè)進(jìn)程的基本屬性,其作用類似與人的身份證號(hào),根據(jù)進(jìn)程ID用戶可以精確的定位一個(gè)進(jìn)程,一個(gè)標(biāo)識(shí)符對(duì)應(yīng)于一個(gè)進(jìn)程,,多個(gè)進(jìn)程標(biāo)識(shí)符可以對(duì)應(yīng)于一個(gè)程序。進(jìn)程標(biāo)識(shí)符的類型是pit_t,他是一個(gè)無符號(hào)整數(shù)。進(jìn)程標(biāo)識(shí)符1進(jìn)程標(biāo)識(shí)符2進(jìn)程標(biāo)識(shí)符3進(jìn)程1進(jìn)程2進(jìn)程3程序2程序16.1.1進(jìn)程的描述-進(jìn)程標(biāo)識(shí)符進(jìn)程ID使用PS查看當(dāng)前進(jìn)程ps-u[用戶名]
第一列是進(jìn)程id最后一列是對(duì)應(yīng)的程序名稱6.1.1進(jìn)程的描述-進(jìn)程標(biāo)識(shí)符進(jìn)程IDLinux操作系統(tǒng)包括三種不同類型的進(jìn)程,每種進(jìn)程都有自己的特點(diǎn)和屬性。交互進(jìn)程——由一個(gè)shell啟動(dòng)的進(jìn)程。交互進(jìn)程既可以在前臺(tái)運(yùn)行,也可以在后臺(tái)運(yùn)行(人機(jī)交互)。批處理進(jìn)程——這種進(jìn)程和終端沒有聯(lián)系,是一個(gè)進(jìn)程序列(多個(gè)進(jìn)程)。監(jiān)控進(jìn)程(也稱守護(hù)進(jìn)程)——Linux系統(tǒng)啟動(dòng)時(shí)啟動(dòng)的進(jìn)程,并在后臺(tái)運(yùn)行。6.1.1進(jìn)程的描述-Linux進(jìn)程分類運(yùn)行狀態(tài):此時(shí)進(jìn)程或者正在運(yùn)行或者準(zhǔn)備運(yùn)行等待狀態(tài):此時(shí)進(jìn)程在等待一個(gè)事件的發(fā)生或者某種系統(tǒng)資源停止?fàn)顟B(tài):此時(shí)進(jìn)程已經(jīng)被終止死亡狀態(tài):這是一個(gè)停止的進(jìn)程,但是在進(jìn)程向量數(shù)組中占有一個(gè)task_struct結(jié)構(gòu)R(TASK_RUNNING),可執(zhí)行狀態(tài)S(TASK_INTERRUPTIBLE),可中斷的睡眠狀態(tài)。D(TASK_UNINTERRUPTIBLE),不可中斷的睡眠狀態(tài)。s進(jìn)程的領(lǐng)導(dǎo)者+前臺(tái)進(jìn)程6.2.1Linux進(jìn)程運(yùn)行狀態(tài)每一個(gè)進(jìn)程有6個(gè)重要的ID,分別是進(jìn)程ID、父進(jìn)程ID、有效用戶ID、有小組ID、實(shí)際用戶ID和實(shí)際組ID。這六個(gè)ID保存在內(nèi)核中的數(shù)據(jù)結(jié)構(gòu)中,有些時(shí)候用戶程序需要用到這些ID。例如在/proc文件系統(tǒng)下每個(gè)進(jìn)程有一個(gè)目錄,里面存放進(jìn)程的相關(guān)信息,當(dāng)進(jìn)程要讀取這些文件時(shí),應(yīng)該先得到當(dāng)前進(jìn)程的ID才能確定進(jìn)入那一個(gè)進(jìn)程相關(guān)的子目錄,由于這些ID存儲(chǔ)在內(nèi)核之中,因此linux提供一組專門的接口函數(shù)訪問這些ID值。Linux環(huán)境下使用getpid和getppid函數(shù)獲得進(jìn)程和父進(jìn)程的ID,其函數(shù)原型如下:#include<unistd.h>Pid_tgetpid(void)pid_tgetppid(void)函數(shù)成功返回進(jìn)程的id,失敗返回-1,6.2.1Linux進(jìn)程標(biāo)識(shí)符Linux環(huán)境下使用getuid和geteuid函數(shù)獲得進(jìn)程用戶ID,其函數(shù)原型如下:#include<unistd.h>uid_tgetuid(void)uid_tgeteuid(void)函數(shù)成功返回進(jìn)程的用戶id,失敗返回-1.Linux環(huán)境下使用getgid和getegid函數(shù)獲得進(jìn)程用戶組ID,其函數(shù)原型如下:#include<unistd.h>gid_tgetgid(void)gid_tgetegid(void)函數(shù)成功返回進(jìn)程的用戶id,失敗返回-1,Pid_t類型參看/usr/include/bits/types.h實(shí)際就是int類型6.2.1Linux進(jìn)程標(biāo)識(shí)符每6.2.1Linux進(jìn)程標(biāo)識(shí)符啟動(dòng)進(jìn)程和調(diào)度進(jìn)程1手動(dòng)啟動(dòng):用戶直接輸入shell命令后回車直接啟動(dòng)進(jìn)程前臺(tái)啟動(dòng):用戶輸入一個(gè)shell命令后按回車就啟動(dòng)給一個(gè)前臺(tái)進(jìn)程后臺(tái)啟動(dòng):在shell命令后加入一個(gè)“&”符號(hào)再按回車鍵就可以啟動(dòng)一個(gè)后臺(tái)作業(yè)。6.2.2Linux進(jìn)程標(biāo)識(shí)符啟動(dòng)進(jìn)程的前后臺(tái)切換1bg命令(background)格式bg[作業(yè)號(hào)]功能:將前臺(tái)作業(yè)切換到后臺(tái)運(yùn)行,若沒有指定的作業(yè)則將當(dāng)前作業(yè)切換到后臺(tái)例如使用vi編輯文件f1然后用ctrl+Z組合掛起vi再切換到后臺(tái)6.2.2Linux進(jìn)程進(jìn)程前后臺(tái)切換3.Fg掛起程序作用:fg命令使一個(gè)被掛起的進(jìn)程在前臺(tái)執(zhí)行。格式:fg-[job-spec][job-spec]:后臺(tái)任務(wù)號(hào)碼。說明:fg命令和bg命令是相對(duì)應(yīng)的。如果想查看后臺(tái)程序運(yùn)行情況,可以使用fg命令把它調(diào)回前臺(tái)查看。bg命令可以使多個(gè)進(jìn)程放到后臺(tái)中執(zhí)行。6.2.2Linux進(jìn)程進(jìn)程命令作用:ps命令主要查看系統(tǒng)中進(jìn)程的狀態(tài)。格式:ps[選項(xiàng)]主要選項(xiàng)如下。-A:顯示系統(tǒng)中所有進(jìn)程的信息。-e:顯示所有進(jìn)程的信息。-f:顯示進(jìn)程的所有信息。-l:以長格式顯示進(jìn)程信息。-r:只顯示正在運(yùn)行的進(jìn)程。-u:顯示面向用戶的格式(包括用戶名、CPU及內(nèi)存使用情況等信息)。-x:顯示所有非控制終端上的進(jìn)程信息。-p:顯示由進(jìn)程ID指定的進(jìn)程的信息。-t:顯示指定終端上的進(jìn)程的信息。6.2.2Linux進(jìn)程進(jìn)程命令-ps說明:要對(duì)進(jìn)程進(jìn)行監(jiān)測(cè)和控制,首先要了解當(dāng)前進(jìn)程的情況,也就是需要查看當(dāng)前進(jìn)程。ps命令就是最基本、也是非常強(qiáng)大的進(jìn)程查看命令。根據(jù)顯示的信息可以確定哪個(gè)進(jìn)程正在運(yùn)行、哪個(gè)進(jìn)程被掛起、進(jìn)程已運(yùn)行了多久、進(jìn)程正在使用的資源、進(jìn)程的相對(duì)優(yōu)先級(jí),以及進(jìn)程的標(biāo)志號(hào)(PID)。所有這些信息對(duì)用戶都很有用,對(duì)于系統(tǒng)管理員來說更為重要。使用"ps-aux"命令可以獲得終端上所有用戶的有關(guān)進(jìn)程的所有信息,下面結(jié)合圖4-8講解進(jìn)程的基本信息6.2.2Linux進(jìn)程進(jìn)程命令-psUSER表示啟動(dòng)進(jìn)程用戶。PID表示進(jìn)程標(biāo)志號(hào)。%CPU表示運(yùn)行該進(jìn)程占用CPU的時(shí)間與該進(jìn)程總的運(yùn)行時(shí)間的比例。%MEM表示該進(jìn)程占用內(nèi)存和總內(nèi)存的比例。VSZ表示占用的虛擬內(nèi)存大小,以KB為單位。RSS為進(jìn)程占用的物理內(nèi)存值,以KB為單位。TTY表示該進(jìn)程建立時(shí)所對(duì)應(yīng)的終端,"?"表示該進(jìn)程不占用終端。STAT表示進(jìn)程的運(yùn)行狀態(tài),包括以下幾種代碼:D,不可中斷的睡眠;R,就緒(在可運(yùn)行隊(duì)列中);S,睡眠;T,被跟蹤或停止;Z,終止(僵死)的進(jìn)程,Z不存在,但暫時(shí)無法消除;W,沒有足夠的內(nèi)存分頁可分配;<高優(yōu)先序的進(jìn)程;N,低優(yōu)先序的進(jìn)程;L,有內(nèi)存分頁分配并鎖在內(nèi)存體內(nèi)(實(shí)時(shí)系統(tǒng)或I/O)。START為進(jìn)程開始時(shí)間。TIME為執(zhí)行的時(shí)間。COMMAND是對(duì)應(yīng)的命令名。6.2.2Linux進(jìn)程進(jìn)程命令-pstop命令顯示進(jìn)程top命令用來顯示系統(tǒng)當(dāng)前的進(jìn)程狀況。格式:top[選項(xiàng)]主要選項(xiàng)如下。d:指定更新的間隔,以秒計(jì)算。q:沒有任何延遲的更新。如果使用者有超級(jí)用戶,則top命令將會(huì)以最高的優(yōu)先序執(zhí)行。c:顯示進(jìn)程完整的路徑與名稱。S:累積模式,會(huì)將已完成或消失的子進(jìn)程的CPU時(shí)間累積起來。s:安全模式。i:不顯示任何閑置(Idle)或無用(Zombie)的進(jìn)程。n:顯示更新的次數(shù),完成后將會(huì)退出top。6.2.2Linux進(jìn)程進(jìn)程命令-topnice命令改變權(quán)限優(yōu)先級(jí)作用:nice命令可以改變程序執(zhí)行的優(yōu)先權(quán)等級(jí)。格式:nice[-n<優(yōu)先等級(jí)>][--help][--version][命令]主要選項(xiàng)如下。-n<優(yōu)先等級(jí)>或-<優(yōu)先等級(jí)>或--adjustment=<優(yōu)先等級(jí)>:設(shè)置欲執(zhí)行的命令的優(yōu)先權(quán)等級(jí)。等級(jí)的范圍從-20~19,其中-20為最高,19為最低。--help:在線幫助。說明:應(yīng)用程序優(yōu)先權(quán)值的范圍從-20~19,數(shù)字越小,優(yōu)先權(quán)就越高。一般情況下,普通應(yīng)用程序的優(yōu)先權(quán)值(CPU使用權(quán)值)都是0,如果讓常用程序擁有較高的優(yōu)先權(quán)等級(jí),自然啟動(dòng)和運(yùn)行速度都會(huì)快些。需要注意的是普通用戶只能在0~19之間調(diào)整應(yīng)用程序的優(yōu)先權(quán)值,只有超級(jí)用戶有權(quán)調(diào)整更高的優(yōu)先權(quán)值(從-20~19)。例如:nice–n1ls>1.txt6.2.2Linux進(jìn)程進(jìn)程命令-nicerenice命令修改優(yōu)先級(jí)作用:renice命令允許用戶修改一個(gè)正在運(yùn)行的進(jìn)程的優(yōu)先權(quán)。格式:renicepriority[[-p]pids][[-g]pgrps][[-u]users]主要選項(xiàng)如下。priority:優(yōu)先等級(jí)-ppids:改變?cè)摮绦虻膬?yōu)先權(quán)等級(jí),此參數(shù)為預(yù)設(shè)值。-gpgrps:使用程序群組名稱,修改所有隸屬于該程序群組的程序的優(yōu)先權(quán)。-uuser:指定用戶名稱,修改所有隸屬于該用戶的程序的優(yōu)先權(quán)。說明:renice命令可重新調(diào)整正在執(zhí)行的程序的優(yōu)先權(quán)等級(jí)。默認(rèn)是以程序識(shí)別碼指定程序,調(diào)整其優(yōu)先權(quán),也可以指定程序群組或用戶名稱調(diào)整優(yōu)先權(quán)等級(jí),并修改所有隸屬于該程序群組或用戶的程序的優(yōu)先權(quán)。等級(jí)范圍從-20~19,只有超級(jí)用戶可以改變其他用戶程序的優(yōu)先權(quán)和設(shè)置負(fù)數(shù)等級(jí)。普通用戶只能對(duì)自己所有的進(jìn)程使用renice命令。應(yīng)用實(shí)例如下:將進(jìn)程PID為987及32的進(jìn)程與進(jìn)程擁有者為daemon及root的優(yōu)先級(jí)別號(hào)加1:#renice+1987–udaemonroot–p326.2.2Linux進(jìn)程進(jìn)程命令-Renicesleep命令暫停進(jìn)程作用:sleep命令的功能是使進(jìn)程暫停執(zhí)行一段時(shí)間。格式:sleepnumber[選項(xiàng)]主要選項(xiàng)如下。number:時(shí)間長度,后面可接s、m、h或d。s:以秒為單位。m:以分鐘為單位。h:以小時(shí)為單位。d:以天為單位。說明:如果沒有指定時(shí)間,以秒為單位。此命令大多用于shell程序設(shè)計(jì)中,使兩條命令執(zhí)行之間停頓指定的時(shí)間。應(yīng)用實(shí)例如下。下面的命令使進(jìn)程先暫停60秒,然后查看哪個(gè)用戶登錄到系統(tǒng)中:#sleep60;who6.2.2Linux進(jìn)程進(jìn)程命令-sleepkill命令殺掉進(jìn)程作用:kill命令終止一個(gè)進(jìn)程。格式:kill[-ssignal|-p][-a]pid…kill-l[signal]主要選項(xiàng)如下。-s:指定發(fā)送的信號(hào)。-p:模擬發(fā)送信號(hào)。-l:指定信號(hào)的名稱列表。pid:要終止的進(jìn)程的ID號(hào)。signal:表示信號(hào)。6.2.2Linux進(jìn)程進(jìn)程命令-kill說明:kill可將指定的信息送至程序。預(yù)設(shè)的信息為SIGTERM(15),可將指定程序終止。若仍無法終止該程序,可使用SIGKILL(9)信息嘗試強(qiáng)制刪除程序。kill命令的工作原理是,向Linux系統(tǒng)的內(nèi)核發(fā)送一個(gè)系統(tǒng)操作信號(hào)和某個(gè)程序的進(jìn)程標(biāo)志號(hào),然后系統(tǒng)內(nèi)核就可以對(duì)進(jìn)程標(biāo)志號(hào)指定的進(jìn)程進(jìn)行操作。當(dāng)需要中斷一個(gè)前臺(tái)進(jìn)程的時(shí)候,通常使用Ctrl+C組合鍵;但是對(duì)于一個(gè)后臺(tái)進(jìn)程,就不是一個(gè)組合鍵所能解決的了,這時(shí)就必須使用kill命令。應(yīng)用實(shí)例如下。命令執(zhí)行過程如果出錯(cuò),用戶可用"kill"來結(jié)束任務(wù)。對(duì)于在后臺(tái)運(yùn)行的進(jìn)程,可以使用kill命令終止:$kill-s918276.2.2Linux進(jìn)程進(jìn)程命令-kill1.a(chǎn)t命令:定時(shí)運(yùn)行命令作用:at命令在指定時(shí)刻執(zhí)行指定的命令序列。#at2:05tomorrowat>/home/mj/airplane>/home/mj/air-safeat>Ctrl+D2crontab命令作用:crontab命令用于安裝、刪除或者列出用于驅(qū)動(dòng)cron后臺(tái)進(jìn)程的任務(wù)表。然后,該配置由cron守護(hù)進(jìn)程在設(shè)定的時(shí)間執(zhí)行。格式:crontab[-uuser]文件6.2.2Linux進(jìn)程進(jìn)程命令-atfork()–創(chuàng)建一個(gè)新進(jìn)程Wake()喚醒一個(gè)進(jìn)程Schedule()進(jìn)程調(diào)度函數(shù)Exit()退出進(jìn)程6.3.1Linux進(jìn)程進(jìn)程函數(shù)運(yùn)行態(tài)擁有CPU進(jìn)就緒態(tài)不可中斷進(jìn)就緒態(tài)可中斷僵尸態(tài)停止態(tài)fork()wake()資源到位或者收到信號(hào)wake()資源到位schedute()進(jìn)程調(diào)度sleep_uninterruptible()深度睡眠等待資源Sleep_interruptible()淺度睡眠等待資源exit()收到SIG_KILL或者SIGCONT_wake()6.3.2Linux進(jìn)程狀態(tài)睡眠進(jìn)程可以被程序再次的喚醒,而僵死進(jìn)程不會(huì)被任何程序喚醒,只能通過命令kill掉深度睡眠和淺度睡眠進(jìn)程得到它需要的資源被喚醒,通過schedule()進(jìn)入執(zhí)行態(tài),深度睡眠的進(jìn)程不能被信號(hào)或者定時(shí)中斷喚醒,只有它申請(qǐng)的資源又有效是才能被喚醒。Linux中,僅等待CPU時(shí)間的進(jìn)程稱為就緒進(jìn)程,它們被放置在一個(gè)運(yùn)行隊(duì)列中,一個(gè)就緒進(jìn)程的狀態(tài)標(biāo)志位為TASK_RUNNING。一旦一個(gè)運(yùn)行中的進(jìn)程時(shí)間片用完,Linux內(nèi)核的調(diào)度器會(huì)剝奪這個(gè)進(jìn)程對(duì)CPU的控制權(quán),并且從運(yùn)行隊(duì)列中選擇一個(gè)合適的進(jìn)程投入運(yùn)行。
當(dāng)然,一個(gè)進(jìn)程也可以主動(dòng)釋放CPU的控制權(quán)。函數(shù)schedule()是一個(gè)調(diào)度函數(shù),它可以被一個(gè)進(jìn)程主動(dòng)調(diào)用,從而調(diào)度其它進(jìn)程占用CPU。一旦這個(gè)主動(dòng)放棄CPU的進(jìn)程被重新調(diào)度占用CPU,那么它將從上次停止執(zhí)行的位置開始執(zhí)行,也就是說它將從調(diào)用schedule()的下一行代碼處開始執(zhí)行。
有時(shí)候,進(jìn)程需要等待直到某個(gè)特定的事件發(fā)生,例如設(shè)備初始化完成、I/O操作完成或定時(shí)器到時(shí)等。在這種情況下,進(jìn)程則必須從運(yùn)行隊(duì)列移出,加入到一個(gè)等待隊(duì)列中,這個(gè)時(shí)候進(jìn)程就進(jìn)入了睡眠狀態(tài)。6.3.2Linux進(jìn)程狀態(tài)Linux中,僅等待CPU時(shí)間的進(jìn)程稱為就緒進(jìn)程,它們被放置在一個(gè)運(yùn)行隊(duì)列中,一個(gè)就緒進(jìn)程的狀態(tài)標(biāo)志位為TASK_RUNNING。一旦一個(gè)運(yùn)行中的進(jìn)程時(shí)間片用完,Linux內(nèi)核的調(diào)度器會(huì)剝奪這個(gè)進(jìn)程對(duì)CPU的控制權(quán),并且從運(yùn)行隊(duì)列中選擇一個(gè)合適的進(jìn)程投入運(yùn)行。
當(dāng)然,一個(gè)進(jìn)程也可以主動(dòng)釋放CPU的控制權(quán)。函數(shù)schedule()是一個(gè)調(diào)度函數(shù),它可以被一個(gè)進(jìn)程主動(dòng)調(diào)用,從而調(diào)度其它進(jìn)程占用CPU。一旦這個(gè)主動(dòng)放棄CPU的進(jìn)程被重新調(diào)度占用CPU,那么它將從上次停止執(zhí)行的位置開始執(zhí)行,也就是說它將從調(diào)用schedule()的下一行代碼處開始執(zhí)行。
有時(shí)候,進(jìn)程需要等待直到某個(gè)特定的事件發(fā)生,例如設(shè)備初始化完成、I/O操作完成或定時(shí)器到時(shí)等。在這種情況下,進(jìn)程則必須從運(yùn)行隊(duì)列移出,加入到一個(gè)等待隊(duì)列中,這個(gè)時(shí)候進(jìn)程就進(jìn)入了睡眠狀態(tài)。6.3.2Linux進(jìn)程狀態(tài)父子進(jìn)程:除了PID號(hào)為0號(hào)進(jìn)程以外的其他進(jìn)程都是有其他進(jìn)程創(chuàng)建的,創(chuàng)建進(jìn)程的進(jìn)程是父進(jìn)程,被創(chuàng)建的進(jìn)程稱為子進(jìn)程。進(jìn)程是系統(tǒng)中執(zhí)行的基本單位,liunx系統(tǒng)允許任何而一個(gè)用戶創(chuàng)建一個(gè)子進(jìn)程。創(chuàng)建之后,子進(jìn)程存在系統(tǒng)之中,并且獨(dú)立于父進(jìn)程。該子進(jìn)程可以接受系統(tǒng)調(diào)度,可以分配得到系統(tǒng)資源,系統(tǒng)可以檢測(cè)到他的存在,并且賦予他的父進(jìn)程同樣的權(quán)利。Linux使用fork函數(shù)創(chuàng)建一個(gè)新的進(jìn)程,其函數(shù)原型如下:#include<unistd.h>Pid_tfork(void)6.4.1Linux進(jìn)程系統(tǒng)調(diào)用-創(chuàng)建進(jìn)程Fork函數(shù)不需要參數(shù),返回值是一個(gè)進(jìn)程ID,返回值分為3種。對(duì)于父進(jìn)程,fork函數(shù)返回新創(chuàng)建子進(jìn)程的ID對(duì)于子進(jìn)程,fork函數(shù)返回0如果出錯(cuò)則返回-1Fork函數(shù)會(huì)創(chuàng)建一個(gè)新的進(jìn)程,并從內(nèi)核中未此進(jìn)程得到一個(gè)新的ID,之后未這個(gè)新進(jìn)程分配內(nèi)存空間,并將父進(jìn)程的進(jìn)程空間代碼的內(nèi)容復(fù)制到子進(jìn)程的進(jìn)程空間中,包括父進(jìn)程的數(shù)據(jù)段和堆棧段,并且和父進(jìn)程共享代碼段。這時(shí)系統(tǒng)各種又多了一個(gè)進(jìn)程,這個(gè)進(jìn)程和父進(jìn)程一模一樣,兩個(gè)進(jìn)程都要接受系統(tǒng)的調(diào)度。6.4.1Linux進(jìn)程系統(tǒng)調(diào)用-創(chuàng)建進(jìn)程fork函數(shù)6.4.1Linux進(jìn)程系統(tǒng)調(diào)用-創(chuàng)建進(jìn)程fork函數(shù)子進(jìn)程完全復(fù)制了父進(jìn)程的地址空間代內(nèi)容,包括對(duì)戰(zhàn)段和數(shù)據(jù)庫的內(nèi)容,子進(jìn)程并沒有復(fù)制代碼段,而是和父進(jìn)程公用代碼段。Fork函數(shù)的出錯(cuò)情況:Fork有兩種情況返回-1系統(tǒng)中已有太多的進(jìn)程存在了調(diào)用fork函數(shù)的用戶進(jìn)程太多了一般情況下系統(tǒng)會(huì)對(duì)進(jìn)程數(shù)目進(jìn)行限制,如果操作系統(tǒng)對(duì)其不加限制,則用戶可以利用這一漏洞攻擊系統(tǒng)父進(jìn)程的數(shù)據(jù)段父進(jìn)程的代碼段系統(tǒng)中的其他數(shù)據(jù)子進(jìn)程的數(shù)據(jù)段子進(jìn)程的代碼段指向父進(jìn)程的代碼段6.4.1Linux進(jìn)程系統(tǒng)調(diào)用-創(chuàng)建進(jìn)程fork函數(shù)由于fork函數(shù)完整的拷貝了父進(jìn)程的整個(gè)地址空間,因此,執(zhí)行速度比較慢,為了加快fork的執(zhí)行速度,在有些liunx中使用vfork函數(shù)。Vfork函數(shù)產(chǎn)生的子進(jìn)程和父進(jìn)程完全共享地址空間,包括代碼段、數(shù)據(jù)段和堆棧段,子進(jìn)程對(duì)這些共享資源所做的修改,可以影響到父進(jìn)程Vfork函數(shù)產(chǎn)生的子進(jìn)程一定比父進(jìn)程先運(yùn)行,也就是說父進(jìn)程調(diào)用了vfork函數(shù)后會(huì)等待子進(jìn)程運(yùn)行后再運(yùn)行。Vfork函數(shù)創(chuàng)建新的進(jìn)程,但他不產(chǎn)生父進(jìn)程的副本,他通過允許父子進(jìn)程可訪問相同物理內(nèi)存從而為裝了對(duì)進(jìn)程地址的真實(shí)拷貝,當(dāng)子進(jìn)程需要改變內(nèi)存中的數(shù)據(jù)時(shí)才會(huì)拷貝父進(jìn)程。這就是著名的“寫操作時(shí)拷貝”copy-on-write技術(shù)6.4.1Linux進(jìn)程系統(tǒng)調(diào)用-創(chuàng)建進(jìn)程vfork函數(shù)上面講了進(jìn)程的fork函數(shù),很多人有疑問既然所有的進(jìn)程都是fork創(chuàng)建的,那么linux所有的進(jìn)程不就幾乎全部一樣嗎,而且就我們的常識(shí)而言,當(dāng)我們執(zhí)行一個(gè)程序時(shí),新產(chǎn)生的進(jìn)程內(nèi)容就因該是程序的內(nèi)容才對(duì)。Linux環(huán)境使用exec函數(shù)執(zhí)行一個(gè)新程序,該函數(shù)在文件系統(tǒng)中搜索指定的路徑文件,并將該文件內(nèi)容復(fù)制到調(diào)用的exec函數(shù)地址空間,取代原來的進(jìn)程內(nèi)容。Exec函數(shù)提供了一個(gè)在進(jìn)程中啟動(dòng)另一個(gè)程序的方法他可以根據(jù)指定的文件名和目錄找到可執(zhí)行代碼,并用它來取代原調(diào)用進(jìn)程的數(shù)據(jù)段代碼段和堆棧段,在執(zhí)行之后,遠(yuǎn)調(diào)用進(jìn)程的內(nèi)容中除了進(jìn)程號(hào)以外,其他全部被新的進(jìn)程替換了。可執(zhí)行文件可以是二進(jìn)制文件也可以是liunx下的腳本文件。6.4.2Linux進(jìn)程系統(tǒng)調(diào)用-exec函數(shù)在什么情況下使用exec函數(shù)當(dāng)有進(jìn)程認(rèn)為自己不能再為系統(tǒng)和用戶作出任何新貢獻(xiàn)了,就可以調(diào)用任何exec函數(shù)族,讓自己以新的面貌重生。如果一個(gè)進(jìn)程想執(zhí)行另一程序,它就可以調(diào)用fork函數(shù)新建一個(gè)進(jìn)程,然后執(zhí)行任何一個(gè)exec函數(shù),這樣看起來就像通過執(zhí)行應(yīng)用程序而產(chǎn)生了一個(gè)新進(jìn)程一樣。6.4.2Linux進(jìn)程系統(tǒng)調(diào)用-exec函數(shù)所需頭文件#include<unistd.h>intexecl(constchar*path,constchar*arg,...);intexeclp(constchar*file,constchar*arg,...);intexecle(constchar*path,constchar*arg,...,char*constenvp[]);intexecv(constchar*path,char*constargv[]);intexecvp(constchar*file,char*constargv[]);intexecve(constchar*path,char*constargv[],char*constenvp[]);其中只有execve是真正意義上的系統(tǒng)調(diào)用,其它都是在此基礎(chǔ)上經(jīng)過包裝的庫函數(shù)。exec函數(shù)族的函數(shù)執(zhí)行成功后不會(huì)返回,因?yàn)檎{(diào)用進(jìn)程的實(shí)體,包括代碼段,數(shù)據(jù)段和堆棧等都已經(jīng)被新的內(nèi)容取代,只留下進(jìn)程ID等一些表面上的信息仍保持原樣,頗有些神似"三十六計(jì)"中的"金蟬脫殼"。看上去還是舊的軀殼,卻已經(jīng)注入了新的靈魂。只有調(diào)用失敗了,它們才會(huì)返回一個(gè)-1,從原程序的調(diào)用點(diǎn)接著往下執(zhí)行。6.4.2Linux進(jìn)程系統(tǒng)調(diào)用-exec函數(shù)Execl的第一個(gè)參數(shù)是包含路勁的可執(zhí)行文件,后面是參數(shù)列表,列表的第一個(gè)為命令path,接著為參數(shù)列表,最后必須以null結(jié)束。Execlp的第一個(gè)參數(shù)可以使用絕對(duì)路徑或者是相對(duì)路徑Excele最后包含指向一個(gè)自定義環(huán)境變量列表的指針,此列表必須以null結(jié)束。Execv,v表示path后面接受的是一個(gè)向量,即指向一個(gè)參數(shù)列表的指針,注意這個(gè)列表的最后一項(xiàng)必須是nullExecvepath后面的接受一個(gè)參數(shù)列表向量,并可以指定一個(gè)環(huán)境變量列表向量Execvp,第一個(gè)參數(shù)可以使用相對(duì)或者絕對(duì)路徑,v表示后面接受一個(gè)參數(shù)列表向量。6.4.2Linux進(jìn)程系統(tǒng)調(diào)用-exec函數(shù)對(duì)于l表示list,說明執(zhí)行程序的命令參數(shù)以列表的方式提供,并且用null結(jié)束。參數(shù)的個(gè)數(shù)沒有限制。如下:Char*arg0,Char*arg1,Char*arg2,nullV表示所有的參數(shù)以指針數(shù)組方式給出,其語法為*constargv[],這個(gè)數(shù)組的每一行是一個(gè)命令參數(shù)。E表示傳遞給新程序的環(huán)境變量列表,這個(gè)列表是一個(gè)數(shù)組,數(shù)組的每一行表示一個(gè)環(huán)境變量,如果沒有顯示的說明環(huán)境變量則新程序繼承父進(jìn)程的環(huán)境變量。P表示第一參數(shù)不是完整的路徑名,這是就要從環(huán)境變量中讀取環(huán)境變量參數(shù)組合成一個(gè)完整的路徑名。那么exec函數(shù)就會(huì)匹配bin/filename、usr/bin/filename直到找到一個(gè)正確路徑,就將該文件加載到內(nèi)存執(zhí)行,如果該文件不存在則,exec函數(shù)出錯(cuò)。6.4.2Linux進(jìn)程系統(tǒng)調(diào)用-exec函數(shù)Exec函數(shù)調(diào)用hello程序使用exec函數(shù)調(diào)用當(dāng)前目錄下的hello程序Exec函數(shù)調(diào)用ps–ef命令Exec函數(shù)調(diào)用hello程序帶參數(shù)的程序執(zhí)行./helloc1helloworldLinux進(jìn)程標(biāo)識(shí)符#include<unistd.h>
intmain(intargc,char*argv[])
{
char*envp[]={"PATH=/tmp","USER=lei","STATUS=testing",NULL};
char*argv_execv[]={"echo","excutedbyexecv",NULL};
char*argv_execvp[]={"echo","executedbyexecvp",NULL};
char*argv_execve[]={"env",NULL};
if(fork()==0){
if(execl("/bin/echo","echo","executedbyexecl",NULL)<0)
perror("Erronexecl");
}
if(fork()==0){
if(execlp("echo","echo","executedbyexeclp",NULL)<0)
perror("Erronexeclp");
}
if(fork()==0){
if(execle("/usr/bin/env","env",NULL,envp)<0)
perror("Erronexecle");
}
if(fork()==0){
if(execv("/bin/echo",argv_execv)<0)
perror("Erronexecv");
}
if(fork()==0){
if(execvp("echo",argv_execvp)<0)
perror("Erronexecvp");
}
if(fork()==0){
if(execve("/usr/bin/env",argv_execve,envp)<0)
perror("Erronexecve");
}
}Exec函數(shù)注意事項(xiàng)在使用exec函數(shù)時(shí)一定要加上錯(cuò)誤判斷語句最常見的錯(cuò)誤有找不到制定的文件或者路徑在使用argv和envp時(shí)忘記用NULL結(jié)束沒有對(duì)應(yīng)可執(zhí)行文件的運(yùn)行權(quán)限退出進(jìn)程exit函數(shù)當(dāng)一個(gè)進(jìn)程需要退出時(shí),需要調(diào)用退出函數(shù)這個(gè)退出函數(shù)會(huì)深入到內(nèi)核注銷掉進(jìn)程的內(nèi)核數(shù)據(jù)結(jié)構(gòu),并且釋放進(jìn)程資源。Linux環(huán)境下使用exit函數(shù)退出進(jìn)程,其函數(shù)原型如下#include<stdlib.h>Voidexit(intstatus)intstatus表示退出狀態(tài),這一狀態(tài)是一個(gè)整形值,在shell中可以查看這個(gè)值。使用echo$?C程序中的return語句被翻譯成exit語句如return1-exit(1)exit和_exit區(qū)別Exit是一個(gè)標(biāo)準(zhǔn)的庫函數(shù),其內(nèi)部封裝了linux的系統(tǒng)調(diào)用函數(shù)_exit,兩者的主要區(qū)別在于exit函數(shù)會(huì)在用戶空間做一些善后工作,如清理用戶的I/O緩沖區(qū),將其內(nèi)容寫入磁盤文件,之后在釋放用戶進(jìn)程的地址空間,而_exit函數(shù)直接進(jìn)入內(nèi)核釋放用戶的地址空間,所有用戶空間的緩沖區(qū)內(nèi)容都將丟失。在liunx標(biāo)準(zhǔn)函數(shù)庫中,有一套稱為“高級(jí)I/O”的函數(shù),我們熟知的printf()fopen()fread()fwrite()都在此列,他們被稱為緩沖IO函數(shù),其特征是每次對(duì)應(yīng)打開文件都會(huì)在內(nèi)存中有一片緩沖區(qū),每次度文件時(shí)會(huì)讀取若干條記錄,這樣下次讀文件就可以直接從緩沖去區(qū)中讀取,每次寫文件件時(shí)也是先寫到緩沖區(qū),等滿足一定條件在將緩沖區(qū)中的數(shù)據(jù)一次性寫入文件,這樣可以大大提到文件的讀寫速度。但是當(dāng)我們使用_exit函數(shù)時(shí)就會(huì)產(chǎn)生問題,因?yàn)楦暮瘮?shù)直到內(nèi)核接釋放進(jìn)程,就會(huì)產(chǎn)生緩沖區(qū)數(shù)據(jù)丟失的情況。exit和_exit區(qū)別進(jìn)程運(yùn)行調(diào)用退出函數(shù)清理I/O緩沖區(qū)調(diào)用exit系統(tǒng)調(diào)用進(jìn)程終止運(yùn)行_exit()exit()_exit函數(shù)直接清除進(jìn)程的內(nèi)存空間,并銷毀其在內(nèi)核中的各種數(shù)據(jù)結(jié)構(gòu),exit函數(shù)在調(diào)用exit系統(tǒng)調(diào)用之前要檢查文件的打開情況,吧文件的緩沖區(qū)中的內(nèi)容回寫到文件,對(duì)應(yīng)與圖中“清理緩沖區(qū)”一項(xiàng)exit和_exit區(qū)別說明:在一個(gè)進(jìn)程調(diào)用了exit之后,該進(jìn)程并不會(huì)馬上完全小時(shí),而是留下一個(gè)稱為僵尸進(jìn)程(Zombie)的數(shù)據(jù)結(jié)構(gòu)。僵尸進(jìn)程是一種非常特殊的進(jìn)程,它幾乎已經(jīng)放棄了所有的內(nèi)存空間,沒有任何可執(zhí)行代碼,也不能被調(diào)度,僅僅在進(jìn)程列表中保留一個(gè)位置,記載該進(jìn)程的退出狀態(tài)等信息供其它進(jìn)程收集,除此之外,僵尸進(jìn)程不再占有任何內(nèi)存空間。僵尸進(jìn)程每個(gè)進(jìn)程都有一個(gè)父進(jìn)程,當(dāng)進(jìn)程退出時(shí),其退出狀態(tài)可以被父進(jìn)程得到,父進(jìn)程調(diào)用wait函數(shù)取得子進(jìn)程的退出狀態(tài)信息。這些退出狀態(tài)信息保存在內(nèi)核中,占用很少一塊內(nèi)存空間,當(dāng)子進(jìn)程退出時(shí),這些信息仍然被保存在內(nèi)核中,子進(jìn)程的進(jìn)程ID也同樣保存在系統(tǒng)進(jìn)程里列表中,這是的進(jìn)程稱為僵尸進(jìn)程。僵尸進(jìn)程幾乎放棄了所有的資源,包括地址空間,僵尸進(jìn)程不能執(zhí)行,因此不能被系統(tǒng)調(diào)度,也不會(huì)占用cpu時(shí)間,僵尸進(jìn)程占用的資源是微乎其微的,僵尸進(jìn)程會(huì)一直存在于系統(tǒng)中直到其父進(jìn)程得到其結(jié)束狀態(tài)信息??雌饋斫┦M(jìn)程好像對(duì)系統(tǒng)沒有什么影響,但是僵尸進(jìn)程會(huì)占用進(jìn)程pid號(hào),在liunx中嚴(yán)格限制了進(jìn)程的數(shù)量,僵尸進(jìn)程達(dá)到一定數(shù)量后就不能再創(chuàng)建新的進(jìn)程。因此當(dāng)父進(jìn)程使用fork函數(shù)創(chuàng)建進(jìn)程而不調(diào)用wait函數(shù)時(shí)一個(gè)個(gè)僵尸進(jìn)程就產(chǎn)生了。創(chuàng)建一個(gè)僵尸進(jìn)程僵尸進(jìn)程上面的例子在shell中編譯gcczombile.c–ozombile執(zhí)行./zombile打開另一個(gè)終端輸入ps–ax父進(jìn)程休眠時(shí)子進(jìn)程的僵尸狀態(tài)Wait函數(shù)Linux下使用wait函數(shù)得到進(jìn)程結(jié)束狀態(tài)信息,其函數(shù)原型如下:#include<sys/wait.h>Pid_twait(int*status)調(diào)用wait函數(shù)的進(jìn)程會(huì)阻塞,直到該進(jìn)程的任意一個(gè)子進(jìn)程結(jié)束,wait函數(shù)會(huì)取得結(jié)束進(jìn)程的信息并返回該子進(jìn)程的pid,子進(jìn)程的結(jié)束信息保存在參數(shù)statloc所指向的內(nèi)存空間中,如果該進(jìn)程沒有子進(jìn)程則立即出錯(cuò)返回,返回-1,如果在調(diào)用wait函數(shù)時(shí)已經(jīng)有若干個(gè)子進(jìn)程結(jié)束運(yùn)行了,則wait函數(shù)立即返回,但是具體取得哪一個(gè)子進(jìn)程的信
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 個(gè)人借款合同民間
- 2025年鄭州道路運(yùn)輸從業(yè)資格證模擬考試年新版
- 2025年宜春道路貨運(yùn)運(yùn)輸從業(yè)資格證模擬考試
- 小學(xué)二年級(jí)數(shù)學(xué)上冊(cè)口算
- 2025年河南貨運(yùn)從業(yè)資格證模擬考試題及答案大全
- 2025年河南貨運(yùn)從業(yè)資格證模擬考試0題及答案解析
- 聽評(píng)課記錄完整40篇數(shù)學(xué)
- Unit 4 Fun with numbers Lesson 2 Speed up(說課稿)-2024-2025學(xué)年外研版(三起)(2024)三年級(jí)上冊(cè)
- 2024-2025學(xué)年七年級(jí)生物下冊(cè)第二章人體的營養(yǎng)第三節(jié)合理營養(yǎng)與食品安全教案新版新人教版
- 2024-2025學(xué)年高中政治課時(shí)分層作業(yè)7世界的物質(zhì)性含解析新人教版必修4
- 白酒銷售經(jīng)理述職報(bào)告
- 消防技術(shù)負(fù)責(zé)人任命書
- 六年級(jí)英語上冊(cè)綜合測(cè)試卷(一)附答案
- 部編小學(xué)語文(6年級(jí)下冊(cè)第6單元)作業(yè)設(shè)計(jì)
- 餐飲服務(wù)與管理(高職)PPT完整全套教學(xué)課件
- 2023年菏澤醫(yī)學(xué)??茖W(xué)校單招綜合素質(zhì)模擬試題及答案解析
- 常見食物的嘌呤含量表匯總
- 人教版數(shù)學(xué)八年級(jí)下冊(cè)同步練習(xí)(含答案)
- SB/T 10752-2012馬鈴薯雪花全粉
- 2023年湖南高速鐵路職業(yè)技術(shù)學(xué)院高職單招(英語)試題庫含答案解析
- 積累運(yùn)用表示動(dòng)作的詞語課件
評(píng)論
0/150
提交評(píng)論