第六章Linux內(nèi)核-進(jìn)程_第1頁(yè)
第六章Linux內(nèi)核-進(jìn)程_第2頁(yè)
第六章Linux內(nèi)核-進(jìn)程_第3頁(yè)
第六章Linux內(nèi)核-進(jìn)程_第4頁(yè)
第六章Linux內(nèi)核-進(jìn)程_第5頁(yè)
已閱讀5頁(yè),還剩164頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第六章Linux內(nèi)核--進(jìn)程第一頁(yè),共169頁(yè)。6.1通用內(nèi)核職責(zé)總體來(lái)說(shuō),內(nèi)核負(fù)責(zé)抽象與管理一臺(tái)機(jī)器的硬件資源以及這些資源在執(zhí)行程序之間的共享。內(nèi)核必須支持進(jìn)程、文件和其他資源,以使它們能夠通過(guò)傳統(tǒng)UNIX系統(tǒng)調(diào)用來(lái)進(jìn)行管理。第二頁(yè),共169頁(yè)。6.1.1資源抽象資源抽象:是指創(chuàng)造軟件(通常情況)來(lái)簡(jiǎn)化必須應(yīng)用于硬件的操作以使該硬件能恰當(dāng)?shù)毓ぷ?。例如,一個(gè)設(shè)備驅(qū)動(dòng)程序就是一個(gè)軟件資源抽象。計(jì)算機(jī)部件被抽象為進(jìn)程和資源。進(jìn)程管理:操作系統(tǒng)中的所有執(zhí)行進(jìn)程抽象的所有方面稱為進(jìn)程管理。資源管理:是創(chuàng)建資源抽象以及在進(jìn)程執(zhí)行時(shí)為它們分配和回收系統(tǒng)資源的過(guò)程。UNIX試圖將除CPU和可執(zhí)行內(nèi)存之外的每一種資源都視為一個(gè)文件。第三頁(yè),共169頁(yè)。6.1.2共享資源進(jìn)程可以請(qǐng)求、使用并且釋放資源。當(dāng)一個(gè)進(jìn)程請(qǐng)求資源時(shí),它通常需要對(duì)該資源的獨(dú)占使用。對(duì)一個(gè)資源的獨(dú)占作用意味著當(dāng)一個(gè)資源被分配給一個(gè)進(jìn)程時(shí),沒(méi)有其他進(jìn)程能夠訪問(wèn)這個(gè)資源。資源管理有兩個(gè)關(guān)鍵的方面:對(duì)獲得資源的競(jìng)爭(zhēng)和對(duì)獨(dú)占使用的確保。

第四頁(yè),共169頁(yè)。資源管理程序示意圖進(jìn)程P資源管理程序已分配可用資源X請(qǐng)求K個(gè)單元獲得K個(gè)單元釋放K個(gè)單元分配K個(gè)單元圖6-1資源管理程序示意圖第五頁(yè),共169頁(yè)。資源的獨(dú)占使用進(jìn)程對(duì)CPU的獨(dú)占使用--通過(guò)確保其他進(jìn)程無(wú)法打斷一個(gè)進(jìn)程的執(zhí)行(除非那些其他進(jìn)程比當(dāng)前運(yùn)行的進(jìn)程更重要)內(nèi)存的獨(dú)占使用--是通過(guò)硬件內(nèi)存保護(hù)機(jī)制來(lái)保證的。這些機(jī)制禁止CPU訪問(wèn)那些沒(méi)有分配給當(dāng)前使用CPU的進(jìn)程的內(nèi)存。設(shè)備的獨(dú)占使用是通過(guò)以下方式來(lái)完成的:禁止CPU對(duì)一個(gè)設(shè)備執(zhí)行I/O指令,除非是為已分配該設(shè)備的進(jìn)程而執(zhí)行。第六頁(yè),共169頁(yè)。管態(tài)與用戶態(tài)管態(tài)(supervisormode):內(nèi)核執(zhí)行時(shí)CPU處于管態(tài),也稱為內(nèi)核態(tài)(kernelmode)用戶態(tài)(usermode):所有其他操作系統(tǒng)部件執(zhí)行時(shí)CPU處于用戶態(tài)通過(guò)CPU模式位區(qū)別當(dāng)CPU處于管態(tài)時(shí),被認(rèn)為正在執(zhí)行信任軟件,硬件將會(huì)執(zhí)行在其指令表中的任何指令并且可以訪問(wèn)任何內(nèi)存地址。當(dāng)CPU處于用戶態(tài)時(shí),它被認(rèn)為在執(zhí)行非信任軟件,硬件將無(wú)法執(zhí)行特權(quán)指令(privilegedinstruction)(例如I/O指令),并且只能訪問(wèn)對(duì)當(dāng)前使用CPU的進(jìn)程所分配的內(nèi)存。第七頁(yè),共169頁(yè)。6.1.3操作系統(tǒng)的功能劃分進(jìn)程與資源管理存儲(chǔ)管理設(shè)備管理文件管理第八頁(yè),共169頁(yè)。6.2內(nèi)核的組織結(jié)構(gòu)單內(nèi)核結(jié)構(gòu)一個(gè)模塊是一個(gè)獨(dú)立的軟件單元設(shè)備驅(qū)動(dòng)程序模塊設(shè)備驅(qū)動(dòng)程序接口模塊接口圖6-2內(nèi)核、設(shè)備驅(qū)動(dòng)程序和模塊Linux內(nèi)核第九頁(yè),共169頁(yè)。6.2.1中斷中斷是一個(gè)產(chǎn)生自外部部件(例如,設(shè)備)并由CPU硬件捕獲的電子信號(hào),它使CPU開始執(zhí)行一個(gè)程序序列,而該程序序列與中斷發(fā)生時(shí)CPU正在執(zhí)行的程序無(wú)關(guān)。第十頁(yè),共169頁(yè)。6.2.2使用內(nèi)核服務(wù)用戶程序?qū)?nèi)核看作一個(gè)大的抽象數(shù)據(jù)類型(ADT)(類似于一個(gè)對(duì)象),它保持狀態(tài)并在其公共接口——系統(tǒng)調(diào)用接口上具有大量函數(shù)。內(nèi)核軟件不具有任何內(nèi)部執(zhí)行線程或進(jìn)程,它只是一組保持狀態(tài)的函數(shù)和數(shù)據(jù)結(jié)構(gòu)的集合。任何使用內(nèi)核服務(wù)的進(jìn)程——這種進(jìn)程是一個(gè)活動(dòng)實(shí)體——通過(guò)(在邏輯上)使用一個(gè)對(duì)POSIX的過(guò)程調(diào)用來(lái)產(chǎn)生內(nèi)核請(qǐng)求。即一個(gè)在內(nèi)核之外執(zhí)行的進(jìn)程當(dāng)它產(chǎn)生系統(tǒng)調(diào)用時(shí)開始執(zhí)行內(nèi)核代碼。

第十一頁(yè),共169頁(yè)。內(nèi)核作為ADT用戶空間程序調(diào)用系統(tǒng)公共POSIX..1系統(tǒng)調(diào)用接口內(nèi)核圖6-4內(nèi)核作為ADT私有實(shí)現(xiàn)第十二頁(yè),共169頁(yè)。管態(tài)與用戶態(tài)之間的切換陷阱指令(trapinstruction)是一條用于將CPU轉(zhuǎn)移到一個(gè)預(yù)定地址(有時(shí)作為一個(gè)指令操作數(shù)的函數(shù))并將其自身切換為管態(tài)的指令。

陷阱指令并不是一條特權(quán)指令,因此任何程序都可以執(zhí)行一條陷阱指令。轉(zhuǎn)移指令的目的地址是由一組地址預(yù)先決定的,它們存放在配置為指向內(nèi)核代碼的管理空間中。

第十三頁(yè),共169頁(yè)。陷阱指令操作陷阱信任代碼-------------------------------------------------------123模式轉(zhuǎn)移表用戶態(tài)管態(tài)圖6-5陷阱指令操作S第十四頁(yè),共169頁(yè)。完成一個(gè)系統(tǒng)調(diào)用所需執(zhí)行操作1.對(duì)于系統(tǒng)調(diào)用F,stub(代碼存根)過(guò)程用于調(diào)用F(該stub也稱為F)。2.stub被鏈接到(用戶空間)正調(diào)用的程序。3.當(dāng)一個(gè)進(jìn)程在運(yùn)行期執(zhí)行對(duì)F的調(diào)用,控制被轉(zhuǎn)換到stub過(guò)程而不是直接轉(zhuǎn)換到內(nèi)核。4.stub過(guò)程確認(rèn)傳遞到內(nèi)核過(guò)程的參數(shù)值。另外,在原則上它可以驗(yàn)證調(diào)用stub過(guò)程的進(jìn)程。5.stub過(guò)程執(zhí)行一條陷阱指令轉(zhuǎn)換CPU到管態(tài),然后它(通過(guò)一張包含內(nèi)核函數(shù)入口點(diǎn)的內(nèi)核表間接)轉(zhuǎn)移到目的內(nèi)核函數(shù)的入口點(diǎn)。

第十五頁(yè),共169頁(yè)。6.2.3串行執(zhí)行通常內(nèi)核函數(shù)執(zhí)行時(shí)處于臨界區(qū)。也就是說(shuō),一旦進(jìn)程調(diào)用一個(gè)系統(tǒng)函數(shù),該函數(shù)通常要運(yùn)行到結(jié)束并在CPU分配給不同的進(jìn)程之前返回。這種類型的內(nèi)核是單線程(single-threaded)的。IRQ可以中斷系統(tǒng)調(diào)用的執(zhí)行來(lái)運(yùn)行ISR。第十六頁(yè),共169頁(yè)。6.2.4守護(hù)進(jìn)程習(xí)慣上,守護(hù)進(jìn)程執(zhí)行名字以字符“d”結(jié)尾的程序。典型守護(hù)進(jìn)程syslogd、klogd、crond第十七頁(yè),共169頁(yè)。認(rèn)識(shí)Linux內(nèi)核第十八頁(yè),共169頁(yè)。內(nèi)核源程序目錄結(jié)構(gòu)第十九頁(yè),共169頁(yè)。內(nèi)核源程序目錄結(jié)構(gòu)內(nèi)核源程序代碼安裝在/usr/src/linux目錄下Documentation:文檔arch:體系結(jié)構(gòu)相關(guān)的代碼Drivers:外圍設(shè)備的軟件驅(qū)動(dòng)程序Fs:Linux支持的所有文件系統(tǒng)include:這個(gè)目錄包含了Linux源程序樹中大部分的C語(yǔ)言包含(.h)文件。init:這個(gè)目錄下面的兩個(gè)文件中比較重要的一個(gè)是main.c,它包含了大部分協(xié)調(diào)內(nèi)核初始化的代碼ipc:這個(gè)目錄包含核心的進(jìn)程間通訊的代碼Modules:只是一個(gè)用來(lái)存放建立好的模塊的目錄

第二十頁(yè),共169頁(yè)。內(nèi)核源程序目錄結(jié)構(gòu)(續(xù))Kernel:Linux中最重要的部分,實(shí)現(xiàn)平臺(tái)獨(dú)立的基本功能。這部分內(nèi)容包括進(jìn)程調(diào)度(kernel/sched.c)以及創(chuàng)建和撤銷進(jìn)程的代碼(kernel/fork.c和kernel/exit.c)Lib:目錄包含兩部分的內(nèi)容。lib/inflate.c中的函數(shù)能夠在系統(tǒng)啟動(dòng)時(shí)展開經(jīng)過(guò)壓縮的內(nèi)核(請(qǐng)參看第4章)。lib目錄下剩余的其它文件實(shí)現(xiàn)一個(gè)標(biāo)準(zhǔn)C庫(kù)的有用子集mm:該目錄包含了體系結(jié)構(gòu)無(wú)關(guān)的內(nèi)存管理代碼net:這個(gè)目錄包含了Linux應(yīng)用的網(wǎng)絡(luò)協(xié)議代碼scripts:該目錄包含了用來(lái)配置內(nèi)核的腳本第二十一頁(yè),共169頁(yè)。6.3進(jìn)程與資源管理第二十二頁(yè),共169頁(yè)。進(jìn)程抽象地址空間虛擬CPUCPU…地址空間虛擬CPU定時(shí)器、中斷、…保護(hù)機(jī)制IPC調(diào)度程序內(nèi)核數(shù)據(jù)結(jié)構(gòu)主存CPU應(yīng)用程序進(jìn)程管理程序硬件圖6-9進(jìn)程抽象第二十三頁(yè),共169頁(yè)。不同抽象級(jí)別的概要硬件層。硬件從PC指定的內(nèi)存地址中取出一條指令并執(zhí)行它,然后再取下一條指令執(zhí)行。只有硬件進(jìn)程執(zhí)行存儲(chǔ)指令的概念。進(jìn)程管理程序?qū)?。進(jìn)程管理程序創(chuàng)建一組理想化的虛擬機(jī)器(virtualmachine)。進(jìn)程管理程序通過(guò)使用定時(shí)器、中斷、各種保護(hù)機(jī)制、進(jìn)程間通信(IPC)、同步機(jī)制、調(diào)度計(jì)劃以及一組數(shù)據(jù)結(jié)構(gòu)來(lái)使用硬件層創(chuàng)建Linux進(jìn)程。應(yīng)用程序與進(jìn)程管理程序(通過(guò)使用系統(tǒng)調(diào)用接口)進(jìn)行交互。應(yīng)用程序?qū)?。?yīng)用程序?qū)邮褂脗鹘y(tǒng)的Linux進(jìn)程。

第二十四頁(yè),共169頁(yè)。1、Linux進(jìn)程第二十五頁(yè),共169頁(yè)。進(jìn)程基本狀態(tài)基本狀態(tài)間的轉(zhuǎn)換:執(zhí)行狀態(tài)就緒狀態(tài)阻塞狀態(tài)新狀態(tài)終止?fàn)顟B(tài)接收進(jìn)程調(diào)度退出中斷等待I/O或事件I/O或事件發(fā)生第二十六頁(yè),共169頁(yè)。Linux進(jìn)程概況每個(gè)進(jìn)程分為內(nèi)核態(tài)(特權(quán)級(jí)0)和用戶態(tài)(特權(quán)級(jí)3)兩種級(jí)別。2.4.0版本中,每個(gè)task_struct結(jié)構(gòu)占1680字節(jié)。系統(tǒng)中的最大進(jìn)程數(shù)由系統(tǒng)的物理內(nèi)存大小決定。第二十七頁(yè),共169頁(yè)。Linux進(jìn)程狀態(tài)Linux進(jìn)程有以下狀態(tài):

Running

進(jìn)程處于運(yùn)行(它是系統(tǒng)的當(dāng)前進(jìn)程)或者準(zhǔn)備運(yùn)行狀態(tài)(它在等待系統(tǒng)將CPU分配給它)。

Waiting

進(jìn)程在等待一個(gè)事件或者資源。Linux將等待進(jìn)程分成兩類;可中斷與不可中斷??芍袛嗟却M(jìn)程可以被信號(hào)中斷;不可中斷等待進(jìn)程直接在硬件條件等待,并且任何情況下都不可中斷。

Stopped

進(jìn)程被停止,通常是通過(guò)接收一個(gè)信號(hào)。正在被調(diào)試的進(jìn)程可能處于停止?fàn)顟B(tài)。

Zombie

這是由于某些原因被終止的進(jìn)程,但是在task數(shù)據(jù)中仍然保留

task_struct結(jié)構(gòu)。它象一個(gè)已經(jīng)死亡的進(jìn)程。

第二十八頁(yè),共169頁(yè)。Linux進(jìn)程狀態(tài)變遷圖停止態(tài)僵死態(tài)正在運(yùn)行態(tài)就緒態(tài)不可中斷等待態(tài)可中斷等待態(tài)進(jìn)程跟蹤停止命令進(jìn)程終止未申請(qǐng)到所需資源未申請(qǐng)到所需資源所需資源被滿足所需資源被滿足進(jìn)程調(diào)度時(shí)間片到被喚醒第二十九頁(yè),共169頁(yè)。進(jìn)程的結(jié)構(gòu)Linux下一個(gè)進(jìn)程在內(nèi)存里有三部分的數(shù)據(jù),就是“代碼段”、“堆棧段”和“數(shù)據(jù)段”。“代碼段”,就是存放了程序代碼的數(shù)據(jù),假如機(jī)器中有數(shù)個(gè)進(jìn)程運(yùn)行相同的一個(gè)程序,那么它們就可以使用相同的代碼段。“堆棧段”存放的就是子程序的返回地址、子程序的參數(shù)以及程序的局部變量。數(shù)據(jù)段存放程序的全局變量,常數(shù)以及動(dòng)態(tài)數(shù)據(jù)分配的數(shù)據(jù)空間(比如用malloc之類的函數(shù)取得的空間)。系統(tǒng)如果同時(shí)運(yùn)行數(shù)個(gè)相同的程序,它們之間就不能使用同一個(gè)堆棧段和數(shù)據(jù)段。第三十頁(yè),共169頁(yè)。進(jìn)程控制塊

/usr/src/linux-2.4/include/linux/sched.hstructtask_struct{ volatilelongstate;/*-1unrunnable,0runnable,>0stopped*/ unsignedlongflags;/*perprocessflags,definedbelow*/ intsigpending; mm_segment_taddr_limit;/*threadaddressspace:0-0xBFFFFFFFforuser-thead0-0xFFFFFFFFforkernel-thread*/ structexec_domain*exec_domain; volatilelongneed_resched;unsignedlongptrace; intlock_depth;/*Lockdepth*/ longcounter; longnice; unsignedlongpolicy; structmm_struct*mm; inthas_cpu,processor; unsignedlongcpus_allowed;第三十一頁(yè),共169頁(yè)。進(jìn)程ID(PIDs)每個(gè)Unix進(jìn)程的唯一標(biāo)志符,范圍在0到32,767之間的整數(shù)。PID0和PID1對(duì)于系統(tǒng)有特定的意義;其它的進(jìn)程標(biāo)識(shí)符都被認(rèn)為是普通進(jìn)程。在Linux中,PID不一定非要唯一——雖然通常都是唯一的,但是兩個(gè)任務(wù)也可以共享一個(gè)PID。這是Linux對(duì)線程支持的一個(gè)副作用,這些線程從概念上講應(yīng)該共享一個(gè)PID,因?yàn)樗鼈兪峭粋€(gè)進(jìn)程的一部分。在Linux中,你可以創(chuàng)建兩個(gè)任務(wù),并且共享且僅共享它們的PID——從實(shí)際使用角度講它們不會(huì)是線程,但是它們可以使用同一個(gè)PID。第三十二頁(yè),共169頁(yè)。state進(jìn)程的當(dāng)前狀態(tài)TASK_RUNNINGTASK_INTERRUPTIBLETASK_UNINTERRUPTIBLETASK_ZOMBIETASK_STOPPEDTASK_S第三十三頁(yè),共169頁(yè)。flags進(jìn)程標(biāo)志PF_ALIGNWARN 正在打印"對(duì)齊"警告信息PF_STARTING正在創(chuàng)建進(jìn)程PF_EXITING進(jìn)程正在退出PF_FORKNOEXEC進(jìn)程剛創(chuàng)建,但還沒(méi)執(zhí)行PF_SUPERPRIV使用超級(jí)用戶特權(quán)PF_DUMPCOREdumpedcorePF_SIGNALED進(jìn)程被信號(hào)(Signal)終止PF_MEMALLOC正在分配內(nèi)存PF_VFORK對(duì)于用vfork創(chuàng)建的進(jìn)程,退出前正在喚醒父進(jìn)程PF_USEDFPU該進(jìn)程使用FPU(SMPonly)第三十四頁(yè),共169頁(yè)。ptracePF_DTRACEdelayedtrace(usedonm68k)PF_TRACESYS正在跟蹤PF_PTRACED被ptrace系統(tǒng)調(diào)用監(jiān)控第三十五頁(yè),共169頁(yè)。priority進(jìn)程優(yōu)先級(jí),priority的值給出進(jìn)程每次獲取CPU后,可使用的時(shí)間(按jiffies計(jì))。優(yōu)先級(jí)可通過(guò)系統(tǒng)調(diào)用sys_setpriority()改變(kernel/sys.c)第三十六頁(yè),共169頁(yè)。rt_priorityrt_priority給出實(shí)時(shí)進(jìn)程的優(yōu)先級(jí),rt_priority+1000給出進(jìn)程每次獲取CPU后,可使用的時(shí)間(同樣按jiffies計(jì))。實(shí)時(shí)進(jìn)程的優(yōu)先級(jí)可通過(guò)系統(tǒng)調(diào)用sys_sched_setscheduler()改變,不過(guò)實(shí)際的工作是由setscheduler()完成的,這兩個(gè)函數(shù)均定義在kernel/sched.c中。第三十七頁(yè),共169頁(yè)。counter在輪轉(zhuǎn)法(roundrobin)調(diào)度時(shí)表示進(jìn)程當(dāng)前還可運(yùn)行多久。在進(jìn)程開始運(yùn)行時(shí)被賦為priority的值,以后每隔一個(gè)tick(時(shí)鐘中斷)遞減1,減到0時(shí)引起新一輪調(diào)度。重新調(diào)度將從run-queue隊(duì)列選出counter值最大的就緒進(jìn)程獲得CPU,因此counter起到了進(jìn)程的動(dòng)態(tài)優(yōu)先級(jí)的作用(priority則是靜態(tài)優(yōu)先級(jí))。第三十八頁(yè),共169頁(yè)。policy該進(jìn)程的進(jìn)程調(diào)度策略,可以通過(guò)系統(tǒng)調(diào)用sys_sched_setscheduler()更改(kernel/sched.c)。調(diào)度策略有:SCHED_OTHER0非實(shí)時(shí)進(jìn)程,基于優(yōu)先權(quán)的輪轉(zhuǎn)法(roundrobin)SCHED_FIFO1實(shí)時(shí)進(jìn)程,用先進(jìn)先出算法SCHED_RR2實(shí)時(shí)進(jìn)程,用基于優(yōu)先權(quán)的輪轉(zhuǎn)法第三十九頁(yè),共169頁(yè)。進(jìn)程隊(duì)列指針structtask_struct*next_task,*prev_task;所有進(jìn)程(以PCB的形式)組成一個(gè)雙向鏈表。next_task和prev_task就是鏈表的前后向指針。鏈表的頭和尾都是init_task(即0號(hào)進(jìn)程)。通過(guò)宏for_each_task可以很方便的搜索所有進(jìn)程:include/linux/sched.h #definefor_each_task(p)\for(p=&init_task;(p=p->next_task)!=&init_task;)第四十頁(yè),共169頁(yè)。進(jìn)程隊(duì)列指針structtask_struct*p_opptr,*p_pptr;structtask_struct*p_cptr,*p_ysptr,*p_osptr;以上分別是指向原始父進(jìn)程(originalparent)、父進(jìn)程(parent)、子進(jìn)程(youngestchild)及新老兄弟進(jìn)程(youngersibling,oldersibling)的指針。相關(guān)的操作宏參見kernel/linux/sched.h。第四十一頁(yè),共169頁(yè)。父子進(jìn)程間關(guān)系第四十二頁(yè),共169頁(yè)。第四十三頁(yè),共169頁(yè)。2、進(jìn)程管理的相關(guān)命令第四十四頁(yè),共169頁(yè)。ps命令命令格式:ps[options][pids]常用選項(xiàng): -l

以長(zhǎng)列表的形式列出 -a

顯示其它用戶的進(jìn)程 -e

顯示環(huán)境 -r

只顯示正在運(yùn)行的程序第四十五頁(yè),共169頁(yè)。ps命令第四十六頁(yè),共169頁(yè)。ps命令欄目說(shuō)明: UID

用戶的標(biāo)識(shí)號(hào) PID

進(jìn)程的標(biāo)識(shí)號(hào),是系統(tǒng)賦予每個(gè)正在執(zhí)行的進(jìn)程的唯一編號(hào) PPID

父進(jìn)程的標(biāo)識(shí)號(hào) PRI

進(jìn)程優(yōu)先級(jí) SIZE

虛擬內(nèi)存大小 RSS

駐留空間大小 STAT

進(jìn)程狀態(tài)。R—正在運(yùn)行;S—睡眠;D—不可中斷睡眠;T—停止或跟蹤;Z—僵尸進(jìn)程;W—沒(méi)有駐留頁(yè) TTY

進(jìn)程所在的虛擬終端號(hào) TIME

該進(jìn)程已經(jīng)運(yùn)行的時(shí)間 COMMAND

該進(jìn)程的名稱第四十七頁(yè),共169頁(yè)。ps命令第四十八頁(yè),共169頁(yè)。ps命令第四十九頁(yè),共169頁(yè)。pstree顯示系統(tǒng)進(jìn)程樹結(jié)構(gòu)常用選項(xiàng) -a顯示各進(jìn)程的命令行參數(shù)-p顯示各進(jìn)程的進(jìn)程號(hào)-h對(duì)當(dāng)前進(jìn)程及其祖先高亮度顯示第五十頁(yè),共169頁(yè)。kill命令命令格式: kill[-s信號(hào)|-p][-a]進(jìn)程號(hào)... kill-l[信號(hào)]常用選項(xiàng): -l

輸出信號(hào)名列表,可以在/usr/include/linux/signal.h文件中找到 -p

指定kill命令只是顯示進(jìn)程的pid,并不真正送出結(jié)束信號(hào) -s<信號(hào)名>

指出欲發(fā)出的信號(hào),信號(hào)是以信號(hào)名或數(shù)字給出的默認(rèn)值為TERM信號(hào)第五十一頁(yè),共169頁(yè)。&命令功能:將進(jìn)程放到后臺(tái)運(yùn)行方法:在要運(yùn)行的程序命令的最后加上“&”字符。例子:(見上頁(yè))yes>/dev/null& yes命令:向標(biāo)準(zhǔn)輸出發(fā)送無(wú)窮盡的一串“y”。/dev/null像一個(gè)黑洞,任何被送入這個(gè)黑洞的數(shù)據(jù)都會(huì)消失。[1]——yes的作業(yè)號(hào)7840——進(jìn)程標(biāo)識(shí)號(hào)第五十二頁(yè),共169頁(yè)。killall命令按名給進(jìn)程發(fā)信號(hào)第五十三頁(yè),共169頁(yè)。nice命令功能:通過(guò)修改調(diào)度優(yōu)先級(jí)來(lái)運(yùn)行一個(gè)程序。格式: nice[options][COMMAND[arg…]]常用選項(xiàng): -n<adjustment>

加上由<adjustment>指定的優(yōu)先級(jí)而不是默認(rèn)值10。取值范圍是0-19 --version

輸出版本信息nice值小的進(jìn)程優(yōu)先級(jí)高;nice值大的進(jìn)程優(yōu)先級(jí)低

第五十四頁(yè),共169頁(yè)。nice命令第五十五頁(yè),共169頁(yè)。renice命令renice命令允許用戶修改一個(gè)正在運(yùn)行進(jìn)程的優(yōu)先權(quán)。利用renice命令可以在命令執(zhí)行時(shí)調(diào)整其優(yōu)先權(quán)。其格式如下:$renice-numberPID其中,參數(shù)number與nice命令的number意義相同。注:(1)用戶只能對(duì)自己所有的進(jìn)程使用renice命令。(2)root用戶可以在任何進(jìn)程上使用renice命令。(3)只有root用戶才能提高進(jìn)程的優(yōu)先權(quán)。第五十六頁(yè),共169頁(yè)。skill/snice報(bào)告進(jìn)程狀態(tài)第五十七頁(yè),共169頁(yè)。nohup命令使進(jìn)程在用戶退出后仍繼續(xù)執(zhí)行命令格式:nohup命令結(jié)果則會(huì)寫到用戶自己的目錄下的nohup.out這個(gè)文件里(也可以使用輸出重定向,讓它輸出到一個(gè)特定的文件)。第五十八頁(yè),共169頁(yè)。top命令功能:顯示系統(tǒng)動(dòng)態(tài)的進(jìn)程控制和進(jìn)程調(diào)度,還可察看內(nèi)存動(dòng)態(tài)使用的實(shí)時(shí)信息。格式:top[options]字段說(shuō)明Uptime

顯示系統(tǒng)已運(yùn)行時(shí)間和系統(tǒng)的三個(gè)加載均值,加載均值是指那些準(zhǔn)備在1分、5分、15分內(nèi)運(yùn)行的進(jìn)程的平均數(shù)。 process

顯示在最近一次更新是運(yùn)行的進(jìn)程總數(shù)并作分類,可通過(guò)交互命令t來(lái)切換進(jìn)程和狀態(tài)顯示。 CPUstates

顯示再用戶模式下的CPU利用的百分比、系統(tǒng)方式、優(yōu)先級(jí)任務(wù)(優(yōu)先級(jí)任務(wù)是指那些優(yōu)先級(jí)為負(fù)的)和空閑任務(wù)。 Mem

顯示內(nèi)存使用的統(tǒng)計(jì),包含總的可用內(nèi)存、空閑內(nèi)存、一用內(nèi)存、共享內(nèi)存和用于緩存的內(nèi)存??赏ㄟ^(guò)交互命令m來(lái)切換內(nèi)存信息顯示。第五十九頁(yè),共169頁(yè)。top命令(續(xù))字段說(shuō)明

PID

進(jìn)程的標(biāo)識(shí)號(hào),是系統(tǒng)賦予每個(gè)正在執(zhí)行的進(jìn)程的唯一編號(hào)PPID

父進(jìn)程的標(biāo)識(shí)號(hào)UID

用戶的標(biāo)識(shí)號(hào)USER

顯示任務(wù)所有者的用戶號(hào)PRI

進(jìn)程優(yōu)先級(jí)NI

顯示任務(wù)的nice值SIZE

虛擬內(nèi)存大小TSIZE

顯示任務(wù)的代碼大小DSIZE

顯示數(shù)據(jù)加上堆棧的大小,但對(duì)ELF進(jìn)程不顯示。TRS

顯示文本駐留空間的大小。第六十頁(yè),共169頁(yè)。top命令(續(xù))字段說(shuō)明SWAP

顯示對(duì)交換空間的統(tǒng)計(jì),包含總的交換空間,可用交換空間和一用交換空間。D

顯示臟頁(yè)的大小LIB

顯示用用庫(kù)頁(yè)的大小,對(duì)ELF進(jìn)程也無(wú)效。RSS

顯示被任務(wù)占用的物理內(nèi)存的總量(以KB計(jì))SHARE先時(shí)任務(wù)占用的共享內(nèi)存的量。STAT

進(jìn)程狀態(tài)。R—進(jìn)程正在運(yùn)行;S—睡眠;D—不可中斷睡眠;T—停止或跟蹤;Z—僵尸進(jìn)程;W—沒(méi)有駐留頁(yè)TTY

進(jìn)程所在的虛擬終端號(hào)TIME

該進(jìn)程已經(jīng)運(yùn)行的時(shí)間COMMAND

該進(jìn)程的名稱第六十一頁(yè),共169頁(yè)。top命令(續(xù))交互命令: 空格鍵

立即更新顯示。 i

不顯示空閑的或僵尸進(jìn)程信息。 n或#

改變顯示的進(jìn)程數(shù)量。 q

退出top。 r

重新調(diào)整一個(gè)指定進(jìn)程的優(yōu)先級(jí)。 f或F

在顯示時(shí)加上或移去字段。 o或O

改變顯示字段的順序。 m

切換內(nèi)存信息的顯示。 t

切換進(jìn)程和CPU狀態(tài)的顯示。

第六十二頁(yè),共169頁(yè)。top命令第六十三頁(yè),共169頁(yè)。uptime顯示系統(tǒng)已運(yùn)行時(shí)間和系統(tǒng)的三個(gè)加載均值,加載均值是指那些準(zhǔn)備在1分、5分、15分內(nèi)運(yùn)行的進(jìn)程的平均數(shù)。第六十四頁(yè),共169頁(yè)。第六十五頁(yè),共169頁(yè)。/proc文件系統(tǒng)第六十六頁(yè),共169頁(yè)。/proc文件系統(tǒng)簡(jiǎn)介/proc文件系統(tǒng)是一個(gè)偽文件系統(tǒng),它只存在內(nèi)存當(dāng)中,而不占用外存空間。它以文件系統(tǒng)的方式為訪問(wèn)系統(tǒng)內(nèi)核數(shù)據(jù)的操作提供接口。用戶和應(yīng)用程序可以通過(guò)proc得到系統(tǒng)的信息,并可以改變內(nèi)核的某些參數(shù)。由于系統(tǒng)的信息,如進(jìn)程,是動(dòng)態(tài)改變的,所以用戶或應(yīng)用程序讀取proc文件時(shí),proc文件系統(tǒng)是動(dòng)態(tài)從系統(tǒng)內(nèi)核讀出所需信息并提交的。第六十七頁(yè),共169頁(yè)。/proc目錄列表第六十八頁(yè),共169頁(yè)。/proc下重要文件與子目錄/proc/1

關(guān)于進(jìn)程1的信息目錄。每個(gè)進(jìn)程在/proc

下有一個(gè)名為其進(jìn)程號(hào)的目錄。/proc/cpuinfo

處理器信息,如類型、制造商、型號(hào)和性能。/proc/devices

當(dāng)前運(yùn)行的核心配置的設(shè)備驅(qū)動(dòng)的列表。/proc/dma

顯示當(dāng)前使用的DMA通道。/proc/

核心配置的文件系統(tǒng)。/proc/interrupts

顯示使用的中斷/proc/ioports

當(dāng)前使用的I/O端口。/proc/kcore

系統(tǒng)物理內(nèi)存映象。與物理內(nèi)存大小完全一樣,但不實(shí)際占用這么多內(nèi)存/proc/kmsg

核心輸出的消息。也被送到syslog

。第六十九頁(yè),共169頁(yè)。/proc下重要文件與子目錄(續(xù))/proc/ksyms

核心符號(hào)表。/proc/loadavg

系統(tǒng)"平均負(fù)載";3個(gè)沒(méi)有意義的指示器指出系統(tǒng)當(dāng)前的工作量。/proc/meminfo

存儲(chǔ)器使用信息,包括物理內(nèi)存和swap。/proc/modules

當(dāng)前加載了哪些核心模塊。/proc/net

網(wǎng)絡(luò)協(xié)議狀態(tài)信息。/proc/self

到查看/proc

的程序的進(jìn)程目錄的符號(hào)連接。當(dāng)兩個(gè)進(jìn)程查看/proc

時(shí),是不同的連接。這主要便于程序得到它自己的進(jìn)程目錄。/proc/stat

系統(tǒng)的不同狀態(tài)/proc/uptime

系統(tǒng)啟動(dòng)的時(shí)間長(zhǎng)度。/proc/version

核心版本。第七十頁(yè),共169頁(yè)。/proc文件系統(tǒng)第七十一頁(yè),共169頁(yè)。/proc文件系統(tǒng)第七十二頁(yè),共169頁(yè)。/proc進(jìn)程目錄的結(jié)構(gòu)目錄名稱

目錄內(nèi)容

Cmdline命令行參數(shù)

Environ環(huán)境變量值

Fd一個(gè)包含所有文件描述符的目錄

Mem

進(jìn)程的內(nèi)存被利用情況

Stat進(jìn)程狀態(tài)

StatusProcess

status

in

human

readable

form

Cwd當(dāng)前工作目錄的鏈接

ExeLink

to

the

executable

of

this

process

Maps內(nèi)存印象

Statm進(jìn)程內(nèi)存狀態(tài)信息

Root

鏈接此進(jìn)程的root目錄第七十三頁(yè),共169頁(yè)。第七十四頁(yè),共169頁(yè)。3、進(jìn)程創(chuàng)建第七十五頁(yè),共169頁(yè)。創(chuàng)建一個(gè)進(jìn)程新的進(jìn)程的創(chuàng)建是通過(guò)克隆當(dāng)前的進(jìn)程來(lái)實(shí)現(xiàn)的。一個(gè)新的任務(wù)是通過(guò)系統(tǒng)調(diào)用創(chuàng)建的(fork或clone),克隆發(fā)生在核心的核心態(tài)。在系統(tǒng)調(diào)用的最后,產(chǎn)生一個(gè)新的進(jìn)程,等待調(diào)度程序選擇它運(yùn)行。從系統(tǒng)的物理內(nèi)存中為這個(gè)克隆進(jìn)程的堆棧(用戶和核心)分配一個(gè)或多個(gè)物理的頁(yè)用于新的task_struct數(shù)據(jù)結(jié)構(gòu)。一個(gè)進(jìn)程標(biāo)識(shí)符將會(huì)創(chuàng)建,在系統(tǒng)的進(jìn)程標(biāo)識(shí)符組中是唯一的。但是,也可能克隆的進(jìn)程保留它的父進(jìn)程的進(jìn)程標(biāo)識(shí)符。新的task_struct進(jìn)入了task向量表中,舊的(當(dāng)前的)進(jìn)程的task_struct的內(nèi)容拷貝到了克隆的task_struct。第七十六頁(yè),共169頁(yè)。do_fork系統(tǒng)調(diào)用流程第七十七頁(yè),共169頁(yè)。創(chuàng)建一個(gè)進(jìn)程克隆進(jìn)程的時(shí)候,Linux允許兩個(gè)進(jìn)程共享資源而不是擁有不同的拷貝。包括進(jìn)程的文件,信號(hào)處理和虛擬內(nèi)存。共享這些資源的時(shí)候,它們相應(yīng)的count字段相應(yīng)增減,這樣Linux不會(huì)釋放這些資源直到兩個(gè)進(jìn)程都停止使用。例如,如果克隆的進(jìn)程要共享虛擬內(nèi)存,它的task_struct會(huì)包括一個(gè)指向原來(lái)進(jìn)程的mm_struct的指針,mm_struct的count域增加,表示當(dāng)前共享它的進(jìn)程數(shù)目。第七十八頁(yè),共169頁(yè)。創(chuàng)建一個(gè)進(jìn)程(續(xù))創(chuàng)建的子進(jìn)程與父進(jìn)程的區(qū)別:

-進(jìn)程號(hào)(PID)

-父進(jìn)程號(hào)(PPID)

-所有的文件鎖被重置 -收到信號(hào)量做的動(dòng)作不同第七十九頁(yè),共169頁(yè)。一個(gè)創(chuàng)建進(jìn)程的簡(jiǎn)單例子#include<stdio.h> #include<sys/types.h> #include<unistd.h> voidmain(void) { printf("Hello\n"); fork(); printf("bye\n"); }第八十頁(yè),共169頁(yè)。forkfork:n.叉,耙,叉形物,餐叉;分岔;岔路 vt,vi分岔;使成叉形

fork函數(shù)原型: #include<unistd.h> pid_tfork(void);/*pid_t是一個(gè)unisignedint,是進(jìn)程號(hào)對(duì)應(yīng)的數(shù)據(jù)類型*/fork函數(shù)創(chuàng)建一個(gè)新的進(jìn)程對(duì)于父進(jìn)程,fork函數(shù)返回了子程序的進(jìn)程號(hào),而對(duì)于子程序,fork函數(shù)則返回零。對(duì)父進(jìn)程而言,它的進(jìn)程號(hào)是由比它更低層的系統(tǒng)調(diào)用賦予的,而對(duì)于子進(jìn)程而言,它的進(jìn)程號(hào)即是fork函數(shù)對(duì)父進(jìn)程的返回值。第八十一頁(yè),共169頁(yè)。另一個(gè)創(chuàng)建子進(jìn)程的例子main(){

inti,pid;i=0;

pid=fork()if(pid==-1){printf(“Forkerror!\n”);exit(-1);}elseif(pid==0){/*子進(jìn)程程序*/

for(i=1;i<1000;i++) printf(“BBB\n”);}else{ /*父進(jìn)程程序*/

for(i=1;i<1000;i++) printf(“AAA\n");}}第八十二頁(yè),共169頁(yè)。創(chuàng)建子進(jìn)程的例子第八十三頁(yè),共169頁(yè)。fork過(guò)程中父子進(jìn)程的內(nèi)存空間內(nèi)容第八十四頁(yè),共169頁(yè)。一個(gè)程序,兩個(gè)返回值?程序i=0fork()…iret(fork)系統(tǒng)調(diào)用返回pid=…子進(jìn)程mov…push…int…系統(tǒng)調(diào)用…popmove賦值jz判斷父進(jìn)程mov…push…入棧int…系統(tǒng)調(diào)用…popmove賦值jz判斷第八十五頁(yè),共169頁(yè)。進(jìn)程的終止正常終止從main函數(shù)返回調(diào)用exit函數(shù)調(diào)用_exit系統(tǒng)調(diào)用函數(shù)進(jìn)程通過(guò)調(diào)用系統(tǒng)調(diào)用exit自動(dòng)退出,它在內(nèi)核中是由sys_exit實(shí)現(xiàn)的(23322行)。當(dāng)C程序從它的main部分返回時(shí),就會(huì)潛在調(diào)用exit。異常終止調(diào)用abort函數(shù)進(jìn)程接收到某信號(hào)第八十六頁(yè),共169頁(yè)。進(jìn)程的終止當(dāng)進(jìn)程退出時(shí),內(nèi)核釋放所有分配給這個(gè)進(jìn)程的資源——內(nèi)存、文件,等等內(nèi)核不能立即回收代表進(jìn)程的structtask_struct結(jié)構(gòu),這是因?yàn)樵撨M(jìn)程的祖先必須能夠使用wait系統(tǒng)調(diào)用查詢其子孫進(jìn)程的退出狀態(tài)。wait返回它檢測(cè)出的死亡狀態(tài)的進(jìn)程的PID。處于這種在兩種狀態(tài)之間的進(jìn)程——它既不是活動(dòng)的,也沒(méi)有真正死亡——被稱為僵進(jìn)程(zombies)。sys_exit的任務(wù)就是把活動(dòng)進(jìn)程轉(zhuǎn)化為僵進(jìn)程。第八十七頁(yè),共169頁(yè)。等待進(jìn)程完成子進(jìn)程運(yùn)行結(jié)束后(正?;虍惓#?,它并沒(méi)有馬上從系統(tǒng)的進(jìn)程分配表中被刪掉,而是進(jìn)入僵死狀態(tài)(Zombie),一直等到父進(jìn)程來(lái)回收它的結(jié)束狀態(tài)信息。如果父進(jìn)程沒(méi)有回收走子進(jìn)程的結(jié)束狀態(tài)就已經(jīng)退出,子進(jìn)程將永遠(yuǎn)處于僵死狀態(tài);也有例外,如父進(jìn)程先于子進(jìn)程結(jié)束,子進(jìn)程將被init進(jìn)程繼承,并回init進(jìn)程回收其結(jié)束狀態(tài)信息。第八十八頁(yè),共169頁(yè)。等待進(jìn)程完成回收子進(jìn)程結(jié)束狀態(tài)信息wait,waitpid函數(shù)原型: #include<sys/wait.h> pid_twait(int*stat_loc); pid_twaitpid(pid_tpid,int*stat_loc,intoptions);第八十九頁(yè),共169頁(yè)。wait當(dāng)進(jìn)程調(diào)用wait,它將進(jìn)入睡眠狀直到有一個(gè)子進(jìn)程結(jié)束。wait函數(shù)返回子進(jìn)程的進(jìn)程id,stat_loc中返回子進(jìn)程的退出狀態(tài)。waitpid的第一個(gè)參數(shù)pid的意義:pid>0:等待進(jìn)程id為pid的子進(jìn)程。pid==0:等待與自己同組的任意子進(jìn)程。pid==-1:等待任意一個(gè)子進(jìn)程pid<-1:等待進(jìn)程組號(hào)為-pid的任意子進(jìn)程。因此,wait(&stat)等價(jià)于waitpid(-1,&stat,0)第九十頁(yè),共169頁(yè)。wait的例子intstatus;intpid;pid=fork(); if(pid==0)/*childprocess*/

{

printf("\nI'mthechild!");

exit(0);

}

else/*parentprocess*/

{

wait(&status);

printf("\nI'mtheparent!")

printf("\nChildreturned:%d\n",status)

}第九十一頁(yè),共169頁(yè)。執(zhí)行一個(gè)新程序執(zhí)行程序系統(tǒng)調(diào)用execve 函數(shù)原型: #include<unistd.h> intexecve(constchar*path,constchar*argv[],constchar*envp[]);Linux還提供其它幾個(gè)執(zhí)行程序函數(shù),execl,execlp,execle,execv,execvp都不是系統(tǒng)調(diào)用,依賴于execve。第九十二頁(yè),共169頁(yè)。執(zhí)行一個(gè)新程序path,執(zhí)行的文件argv,參數(shù)表envp,環(huán)境變量表,一般直接用environ如:char*argv[]={“gcc”,“-g”,“-c”,“rbtree.c”,NULL};execve(“/usr/bin/gcc”,argv,environ);第九十三頁(yè),共169頁(yè)。執(zhí)行一個(gè)新程序execve啟動(dòng)一個(gè)新的程序,新的地址空間完全覆蓋當(dāng)前進(jìn)程的地址空間,但當(dāng)前進(jìn)程把開的文件描述字(除非特別設(shè)置),當(dāng)前工作目錄等將被繼承。execve只返回負(fù)值表示調(diào)用失敗,如果成功的話將永不返回。第九十四頁(yè),共169頁(yè)。EXEC的例子/*usingexecvptoexecutethecontentsofargv*/ #include<stdio.h> #include<unistd.h> #include<stdlib.h> intmain(intargc,char*argv[]) {execvp(argv[1],&argv[1]); perror("execfailure"); exit(1); }第九十五頁(yè),共169頁(yè)。思考exec與fork有何不同?Fork與exec合二為一好不好?第九十六頁(yè),共169頁(yè)。關(guān)于建立進(jìn)程的典型代碼段if((pid=fork())==-1){/*錯(cuò)誤處理*/…}elseif(pid>0){/*父進(jìn)程運(yùn)行,例如wait(pid);*/….}else{/*子進(jìn)程運(yùn)行,例如exec(“ap1”,…);*/….}第九十七頁(yè),共169頁(yè)。第九十八頁(yè),共169頁(yè)。第九十九頁(yè),共169頁(yè)。初始化Linux內(nèi)核start_kernel:內(nèi)核初始化的工作init:內(nèi)核運(yùn)行的第一個(gè)用戶進(jìn)程,它要負(fù)責(zé)觸發(fā)其它必需的進(jìn)程以使系統(tǒng)作為一個(gè)整體進(jìn)入可用的狀態(tài)。init是系統(tǒng)中所有進(jìn)程的祖先。getty進(jìn)程接受用戶登錄getty進(jìn)程產(chǎn)生login進(jìn)程,login進(jìn)程產(chǎn)生用戶自己的shell,使用自己的shell,可以產(chǎn)生每一個(gè)用戶運(yùn)行的進(jìn)程。

第一百頁(yè),共169頁(yè)。內(nèi)核初始化詳細(xì)過(guò)程參見sys_init.gif第一百零一頁(yè),共169頁(yè)。終端上的登錄過(guò)程第一百零二頁(yè),共169頁(yè)。終端登錄方式下的UNIX進(jìn)程層次第一百零三頁(yè),共169頁(yè)。進(jìn)程家族樹中的登錄過(guò)程

init(1)-+-crond(98)

|-emacs(387)

|-gpm(146)

|-inetd(110)

|-kerneld(18)

|-kflushd(2)

|-klogd(87)

|-kswapd(3)

|-login(160)---bash(192)---emacs(225)

|-lpd(121)

|-mingetty(161)

|-mingetty(162)

|-login(403)---bash(404)---pstree(594)|-xinetd---in.telnetd---login---bash

|-syslogd(78)

`-update(166)

第一百零四頁(yè),共169頁(yè)。網(wǎng)絡(luò)登錄方式下的UNIX進(jìn)程層次第一百零五頁(yè),共169頁(yè)。UNIXshell工作過(guò)程第一百零六頁(yè),共169頁(yè)。copy-on-write寫時(shí)復(fù)制通過(guò)fork創(chuàng)建子進(jìn)程系統(tǒng)開銷很大,需要將每種資源都復(fù)制一個(gè)副本。這些開銷并不是所有的情況下都是必須的,比如某進(jìn)程fork出一個(gè)子進(jìn)程后,其子進(jìn)程僅僅是為了調(diào)用exec執(zhí)行另一個(gè)執(zhí)行文件,那么在fork過(guò)程中對(duì)于虛存空間的復(fù)制將是一個(gè)多余的過(guò)程Linux中采取了copy-on-write技術(shù),所以這一步驟的所做的工作只是虛存管理部分的復(fù)制以及頁(yè)表的創(chuàng)建,而并沒(méi)有包括物理也面的拷貝父子進(jìn)程以只讀方式共享頁(yè)框,當(dāng)其中之一要修改頁(yè)框時(shí),內(nèi)核才通過(guò)缺頁(yè)異常處理程序分配一個(gè)新的頁(yè)框,并將頁(yè)框標(biāo)記為可寫。第一百零七頁(yè),共169頁(yè)。第一百零八頁(yè),共169頁(yè)。4、線程第一百零九頁(yè),共169頁(yè)。線程操作系統(tǒng)中線程的概念線程的分類。分為內(nèi)核空間的線程和用戶空間的線程進(jìn)程和線程的區(qū)別。進(jìn)程和線程之間的最大區(qū)別是一個(gè)進(jìn)程的所有線程共享同一個(gè)內(nèi)存空間并共享系統(tǒng)定義的“資源”。這些資源包括打開的文件句柄(文件描述符)、共享內(nèi)存、進(jìn)程同步原語(yǔ)和當(dāng)前目錄。因?yàn)楣蚕砣謨?nèi)存并且?guī)缀醪槐胤峙湫聝?nèi)存,所以創(chuàng)建線程比創(chuàng)建進(jìn)程更簡(jiǎn)單更快。第一百一十頁(yè),共169頁(yè)。Linux線程Linux內(nèi)核使用的觀點(diǎn)——線程只是偶然的共享相同的全局內(nèi)存空間的進(jìn)程。Linux內(nèi)核并沒(méi)有真正區(qū)分進(jìn)程和線程這兩者在概念上的不同,在內(nèi)核代碼中進(jìn)程和線程都使用更通用的名字“任務(wù)”來(lái)引用。輕量級(jí)進(jìn)程glibc支持用戶級(jí)線程第一百一十一頁(yè),共169頁(yè)。clone()系統(tǒng)調(diào)用clone()系統(tǒng)調(diào)用接口,用不同的參數(shù)指定創(chuàng)建輕量進(jìn)程還是普通進(jìn)程。clone()調(diào)用最后會(huì)調(diào)用do_fork()實(shí)現(xiàn)pid_tclone(int(*fn)(void*arg),void*stack,intflags,void*arg);返回值同fork第一百一十二頁(yè),共169頁(yè)。clone()系統(tǒng)調(diào)用參數(shù)說(shuō)明參數(shù):fn是進(jìn)程所執(zhí)行的過(guò)程,stack是進(jìn)程所使用的堆棧,flags是CLONE_VM,CLONE_FS(fs記錄了進(jìn)程所在文件系統(tǒng)的根目錄和當(dāng)前目錄信息),CLONE_FILES(進(jìn)程可能的文件),CLONE_SIGHAND(自行定義的對(duì)信號(hào)的處理方式),CLONE_PID(Linux內(nèi)核的clone()沒(méi)有實(shí)現(xiàn)對(duì)CLONE_PID參數(shù)的支持)的組合。fork時(shí)flag=SIGCHLD第一百一十三頁(yè),共169頁(yè)。clone()系統(tǒng)調(diào)用的例子void*func(intarg)

{

......

}

intmain()

{intclone_flag,arg;...... clone_flag=CLONE_VM|CLONE_SIGHAND|CLONE_FS|CLONE_FILES; stack=(char*)malloc(STACK_FRAME); stack+=STACK_FRAME; retval=clone((void*)func,stack,clone_flag,arg); ...... }第一百一十四頁(yè),共169頁(yè)。Linux下的用戶空間線程Linux系統(tǒng)下的多線程遵循POSIX線程接口,稱為pthread。頭文件pthread.h,連接時(shí)需要使用庫(kù)libpthread.a。Linux下pthread的實(shí)現(xiàn)是通過(guò)系統(tǒng)調(diào)用clone()來(lái)實(shí)現(xiàn)的。一個(gè)線程實(shí)體對(duì)應(yīng)一個(gè)核心輕量級(jí)進(jìn)程,而線程之間的管理在核外函數(shù)庫(kù)中實(shí)現(xiàn)。第一百一十五頁(yè),共169頁(yè)。線程的創(chuàng)建和使用線程的創(chuàng)建是用下面的幾個(gè)函數(shù)來(lái)實(shí)現(xiàn)的.

#include

intpthread_create(pthread_t*thread,pthread_attr_t*attr,

void*(*start_routine)(void*),void*arg);

voidpthread_exit(void*retval);

intpthread_join(pthread*thread,void**thread_return);第一百一十六頁(yè),共169頁(yè)。參數(shù)說(shuō)明thread是用來(lái)表明創(chuàng)建線程的ID,attr指出線程創(chuàng)建時(shí)候的屬性,用NULL表明使用缺省屬性.start_routine函數(shù)指針是線程創(chuàng)建成功后開始執(zhí)行的函數(shù),arg是這個(gè)函數(shù)的唯一一個(gè)參數(shù).表明傳遞給start_routine的參數(shù).通過(guò)從子例程返回或者調(diào)用pthread_exit()例程,Linux線程就退出了。當(dāng)父線程調(diào)用pthread_join()例程時(shí),就回收線程使用的資源。pthread_join()在本質(zhì)上與進(jìn)程的wait()函數(shù)很相似。pthread_join()不回收線程分配的堆內(nèi)存。需要由程序或線程來(lái)顯式地釋放全局分配的內(nèi)存。第一百一十七頁(yè),共169頁(yè)。線程編程的簡(jiǎn)單例子#include<stdio.h>#include<pthread.h>voidthread(void){

inti;

for(i=0;i<3;i++)

printf("Thisisapthread.\n");

}intmain(void){

pthread_tid;

inti,ret;

ret=pthread_create(&id,NULL,(void*)thread,NULL); if(ret!=0){

printf("Createpthreaderror!\n");

exit(1);

}

for(i=0;i<3;i++)

printf("Thisisthemainprocess.\n");

pthread_join(id,NULL);

return(0);

}第一百一十八頁(yè),共169頁(yè)。5、進(jìn)程調(diào)度第一百一十九頁(yè),共169頁(yè)。實(shí)時(shí)進(jìn)程與非實(shí)時(shí)進(jìn)程Linux把執(zhí)行的任務(wù)比較緊迫的進(jìn)程定義為實(shí)時(shí)進(jìn)程,這些進(jìn)程通常會(huì)比一般進(jìn)程先得到機(jī)會(huì)運(yùn)行。但這種實(shí)時(shí)只是軟實(shí)時(shí),不滿足諸如中斷等待時(shí)間等硬實(shí)時(shí)要求。兩種調(diào)度策略:一種執(zhí)行的任務(wù)比較短小,因此采用先進(jìn)先出的策略;另一種則采用時(shí)間片輪轉(zhuǎn)法。非實(shí)時(shí)進(jìn)程是相對(duì)實(shí)時(shí)進(jìn)程而言的,Linux系統(tǒng)把執(zhí)行的任務(wù)不怎么緊迫的進(jìn)程統(tǒng)稱為非實(shí)時(shí)進(jìn)程。Linux通常對(duì)這類進(jìn)程采用優(yōu)先權(quán)算法進(jìn)行調(diào)度。第一百二十頁(yè),共169頁(yè)。Linux進(jìn)程優(yōu)先級(jí)在Linux中,非實(shí)時(shí)進(jìn)程有兩種優(yōu)先級(jí),一種是靜態(tài)優(yōu)先級(jí),另一種是動(dòng)態(tài)優(yōu)先級(jí)。實(shí)時(shí)進(jìn)程又增加了第三種優(yōu)先級(jí),實(shí)時(shí)優(yōu)先級(jí)。第一百二十一頁(yè),共169頁(yè)。靜態(tài)優(yōu)先級(jí)靜態(tài)優(yōu)先級(jí)——它不隨時(shí)間而改變,只能由用戶進(jìn)行修改。它指明了在被迫和其它進(jìn)程競(jìng)爭(zhēng)CPU之前該進(jìn)程所應(yīng)該被允許的時(shí)間片的最大值(20)。第一百二十二頁(yè),共169頁(yè)。動(dòng)態(tài)優(yōu)先級(jí)動(dòng)態(tài)優(yōu)先級(jí)——只要進(jìn)程擁有CPU,它就隨著時(shí)間不斷減?。划?dāng)它小于0時(shí),標(biāo)記進(jìn)程重新調(diào)度。它指明了在這個(gè)時(shí)間片中所剩余的時(shí)間量(最初為20)。第一百二十三頁(yè),共169頁(yè)。實(shí)時(shí)優(yōu)先級(jí)實(shí)時(shí)優(yōu)先級(jí)——值為1000。Linux把實(shí)時(shí)優(yōu)先級(jí)與counter值相加作為實(shí)時(shí)進(jìn)程的優(yōu)先權(quán)值。較高權(quán)值的進(jìn)程總是優(yōu)先于較低權(quán)值的進(jìn)程,如果一個(gè)進(jìn)程不是實(shí)時(shí)進(jìn)程,其優(yōu)先權(quán)就遠(yuǎn)小于1000,所以實(shí)時(shí)進(jìn)程總是優(yōu)先。第一百二十四頁(yè),共169頁(yè)。Linux進(jìn)程調(diào)度的策略進(jìn)程調(diào)度的策略主要考慮以下幾個(gè)原則: *高效使處理器的利用率最高,空閑最小; *公平使每一個(gè)申請(qǐng)?zhí)幚砥鞯倪M(jìn)程都得到合理的處理器時(shí)間; *周轉(zhuǎn)時(shí)間短使用戶提交任務(wù)后得到結(jié)果的時(shí)間盡可能短; *吞吐量大使單位時(shí)間內(nèi)處理的任務(wù)數(shù)量盡可能多; *響應(yīng)時(shí)間短使對(duì)每個(gè)用戶響應(yīng)的時(shí)間盡可能短。第一百二十五頁(yè),共169頁(yè)。Linux進(jìn)程的調(diào)度算法時(shí)間片輪轉(zhuǎn)調(diào)度算法:用于實(shí)時(shí)進(jìn)程。優(yōu)先權(quán)調(diào)度算法 用于非實(shí)時(shí)進(jìn)程。系統(tǒng)選擇運(yùn)行隊(duì)列中優(yōu)先級(jí)最高的進(jìn)程運(yùn)行。Linux采用搶占式的優(yōu)級(jí)算法,即系統(tǒng)中當(dāng)前運(yùn)行的進(jìn)程永遠(yuǎn)是可運(yùn)行進(jìn)程中優(yōu)先權(quán)最高的那個(gè)。FIFO(先進(jìn)先出)調(diào)度算法 采用FIFO的實(shí)時(shí)進(jìn)程必須是運(yùn)行時(shí)間較短的進(jìn)程,因?yàn)檫@種進(jìn)程一旦獲得CPU就只有等到它運(yùn)行完或因等待資源主動(dòng)放棄CPU時(shí)其它進(jìn)程才能獲得運(yùn)行機(jī)會(huì)。第一百二十六頁(yè),共169頁(yè)。Linux進(jìn)程的調(diào)度時(shí)機(jī)進(jìn)程狀態(tài)轉(zhuǎn)換時(shí):如進(jìn)程終止,睡眠等;可運(yùn)行隊(duì)列中增加新的進(jìn)程時(shí);當(dāng)前進(jìn)程的時(shí)間片耗盡時(shí);進(jìn)程從系統(tǒng)調(diào)用返回到用戶態(tài)時(shí);內(nèi)核處理完中斷后,進(jìn)程返回到用戶態(tài)。第一百二十七頁(yè),共169頁(yè)。調(diào)度優(yōu)先級(jí)調(diào)度優(yōu)先級(jí):

(1)中斷(硬件支持)

(2)當(dāng)前的核心態(tài)進(jìn)程

(3)其他核心態(tài)進(jìn)程

(4)用戶進(jìn)程(軟件管理)第一百二十八頁(yè),共169頁(yè)。

用戶進(jìn)程的優(yōu)先級(jí)

用戶進(jìn)程的優(yōu)先級(jí)分類

(1)實(shí)時(shí)進(jìn)程

(2)交互進(jìn)程:視為IObound進(jìn)程

(3)批處理進(jìn)程:視為CPUbound進(jìn)程第一百二十九頁(yè),共169頁(yè)。具體描述中斷可以搶占核心進(jìn)程,但必須保證在中斷處理結(jié)束后返回它。--一個(gè)核心態(tài)進(jìn)程可以禁用它所運(yùn)行的處理器上的中斷,從而保證不會(huì)被中斷請(qǐng)求信號(hào)中斷它的運(yùn)行。核心態(tài)進(jìn)程不可搶占中斷處理進(jìn)程。--中斷處理期間,僅僅是在中斷處理進(jìn)程處理完成或其他被允許的中斷發(fā)生時(shí)候才發(fā)生任務(wù)切換。核心態(tài)進(jìn)程不可搶占其他核心態(tài)進(jìn)程。--除非一個(gè)核心態(tài)進(jìn)程自愿睡眠,否則不能切換到別的進(jìn)程。這保證了核心代碼塊的對(duì)其他進(jìn)程的整體性,大大的簡(jiǎn)化了核心保護(hù)機(jī)制。特點(diǎn):核心態(tài)進(jìn)程是非搶占,用戶態(tài)進(jìn)程是搶占的。

優(yōu)點(diǎn):核心數(shù)據(jù)的同步和保護(hù)機(jī)制比較簡(jiǎn)單。

缺點(diǎn):不能很好的支持響應(yīng)速度要求高的實(shí)時(shí)應(yīng)用。第一百三十頁(yè),共169頁(yè)。普通進(jìn)程調(diào)度算法對(duì)于普通進(jìn)程,Linux采用動(dòng)態(tài)優(yōu)先調(diào)度選擇進(jìn)程主要依據(jù)counter的大小。進(jìn)程創(chuàng)建時(shí),優(yōu)先級(jí)priority被賦一個(gè)初值,一般為0~70之間的數(shù)字,這個(gè)數(shù)字同時(shí)也是計(jì)數(shù)器counter的初值。都表示進(jìn)程的“時(shí)間片”。Priority代表分配給該進(jìn)程的時(shí)間片,counter表示該進(jìn)程剩余的時(shí)間片。在進(jìn)程運(yùn)行過(guò)程中,counter不斷減少,而priority保持不變,以便在counter變?yōu)?的時(shí)候(該進(jìn)程用完了所分配的時(shí)間片)對(duì)counter重新賦值。當(dāng)一個(gè)普通進(jìn)程的時(shí)間片用完以后,并不馬上用priority對(duì)counter進(jìn)行賦值,只有所有處于可運(yùn)行狀態(tài)的普通進(jìn)程的時(shí)間片(p->counter==0)都用完了以后,才用priority對(duì)counter重新賦值,這個(gè)普通進(jìn)程才有了再次被調(diào)度的機(jī)會(huì)。第一百三十一頁(yè),共169頁(yè)。Linux進(jìn)程動(dòng)態(tài)優(yōu)先級(jí)變化過(guò)程第一百三十二頁(yè),共169頁(yè)。時(shí)間片Linux的時(shí)間單位也是“時(shí)鐘滴答”,(Linux為10ms)。進(jìn)程的時(shí)間片就是指多少個(gè)時(shí)鐘滴答,比如,若priority為20,則分配給該進(jìn)程的時(shí)間片就為20個(gè)時(shí)鐘滴答,也就是20*10ms=200ms。Linux中某個(gè)進(jìn)程的調(diào)度策略(policy)、優(yōu)先級(jí)(priority)等可以作為參數(shù)由用戶自己決定,具有相當(dāng)?shù)撵`活性。內(nèi)核創(chuàng)建新進(jìn)程時(shí)分配給進(jìn)程的時(shí)間片缺省為200ms,用戶可以通過(guò)系統(tǒng)調(diào)用改變它。第一百三十三頁(yè),共169頁(yè)。實(shí)時(shí)進(jìn)程調(diào)度策略兩種調(diào)度策略,即FIFO(先來(lái)先服務(wù)調(diào)度)和RR(時(shí)間片輪轉(zhuǎn)調(diào)度)。實(shí)時(shí)進(jìn)程的counter只是用來(lái)表示該進(jìn)程的剩余時(shí)間片,并不作為衡量它是否值得運(yùn)行的標(biāo)準(zhǔn)。每個(gè)進(jìn)程有兩個(gè)優(yōu)先級(jí),實(shí)時(shí)優(yōu)先級(jí)就是用來(lái)衡量實(shí)時(shí)進(jìn)程是否值得運(yùn)行的。Linux用函數(shù)goodness()來(lái)衡量一個(gè)處于可運(yùn)行狀態(tài)的進(jìn)程值得運(yùn)行的程度。該函數(shù)綜合了上面提到的各個(gè)方面,給每個(gè)處于可運(yùn)行狀態(tài)的進(jìn)程賦予一個(gè)權(quán)值(weight),調(diào)度程序以這個(gè)權(quán)值作為選擇進(jìn)程的唯一依據(jù)。第一百三十四頁(yè),共169頁(yè)。Policy的值SCHED_OTHER:普通的用戶進(jìn)程,進(jìn)程的缺省類型,采用動(dòng)態(tài)優(yōu)先調(diào)度策略,選擇進(jìn)程的依據(jù)主要是根據(jù)進(jìn)程goodness值的大小。可以被高goodness值的進(jìn)程搶先。SCHED_FIFO:這是一種實(shí)時(shí)進(jìn)程,遵守POSIX1.b標(biāo)準(zhǔn)的FIFO(先入先出)調(diào)度規(guī)則。它會(huì)一直運(yùn)行,直到有一個(gè)進(jìn)程因I/O阻塞,或者主動(dòng)釋放CPU,或者是CPU被另一個(gè)具有更高rt_priority的實(shí)時(shí)進(jìn)程搶先。在Linux實(shí)現(xiàn)中,SCHED_FIFO進(jìn)程仍然擁有時(shí)間片-只有當(dāng)時(shí)間片用完時(shí)它們才被迫釋放CPU。因此,如同POSIX1.b一樣,這樣的進(jìn)程就象沒(méi)有時(shí)間片(不是采用分時(shí))一樣運(yùn)行。SCHED_RR:這也是一種實(shí)時(shí)進(jìn)程,遵守POSIX1.b標(biāo)準(zhǔn)的RR(循環(huán)round-robin)調(diào)度規(guī)則。除了時(shí)間片有些不同外,這種策略與SCHED_FIFO類似。當(dāng)SCHED_RR進(jìn)程的時(shí)間片用完后,就被放到SCHED_FIFO和SCHED_RR隊(duì)列的末尾。第一百三十五頁(yè),共169頁(yè)。其他只要系統(tǒng)中有一個(gè)實(shí)時(shí)進(jìn)程在運(yùn)行,則任何SCHED_OTHER進(jìn)程都不能在任何CPU運(yùn)行。每個(gè)實(shí)時(shí)進(jìn)程有一個(gè)rt_priority,因此,可以按照rt_priority在所有SCHED_RR進(jìn)程之間分配CPU。其作用與SCHED_OTHER進(jìn)程的priority作用一樣。只有root用戶能夠用系統(tǒng)調(diào)用sched_setscheduler,來(lái)改變當(dāng)前進(jìn)程的類型(sys_nice,sys_setpriority)。此外,內(nèi)核還定義了SCHED_YIELD,這并不是一種調(diào)度策略,而是截取調(diào)度策略的一個(gè)附加位。如同前面說(shuō)明的一樣,如果有其他進(jìn)程需要CPU,它就提示調(diào)度程序釋放CPU。特別要注意的就是這甚至?xí)饘?shí)時(shí)進(jìn)程把CPU釋放給非實(shí)時(shí)進(jìn)程。第一百三十六頁(yè),共169頁(yè)。直接啟動(dòng)調(diào)度直接啟動(dòng):發(fā)生在當(dāng)前進(jìn)程因等待資源而需要進(jìn)入被阻塞狀態(tài)時(shí)。調(diào)度程序執(zhí)行的步驟如下:

1、把當(dāng)前進(jìn)程(全局變量current指向的task_struct變量)放到適當(dāng)?shù)牡却?duì)列里;

2、把當(dāng)前進(jìn)程的state設(shè)為TASK_INTERRUPTIBEL或者TASK_UNINTERRUPTIBEL;

3、調(diào)用schedule(),準(zhǔn)備讓新的進(jìn)程掌握CPU;

4、檢查當(dāng)前進(jìn)程所需的資源是否可用,如果是,則把當(dāng)前進(jìn)程從等待隊(duì)列里刪除,否則回到第2步第一百三十七頁(yè),共169頁(yè)。被動(dòng)調(diào)用調(diào)度通過(guò)在當(dāng)前進(jìn)程的need_resched設(shè)為1,就可以實(shí)現(xiàn)另一種方式重新調(diào)度各個(gè)進(jìn)程。因?yàn)槊看握{(diào)入一個(gè)用戶態(tài)進(jìn)程之前,這個(gè)變量的值都會(huì)被檢查,因此schedule()又會(huì)很快被調(diào)用。被動(dòng)調(diào)用在以下情況下執(zhí)行: (1)當(dāng)當(dāng)前進(jìn)程用完了它的CPU時(shí)間片,update_process_times()重新進(jìn)行計(jì)算。 (2)當(dāng)一個(gè)進(jìn)程被喚醒,而且它的優(yōu)先級(jí)比當(dāng)前進(jìn)程高。wake_up_process()調(diào)用reschedule_idle(),設(shè)置當(dāng)前進(jìn)程的need_resched,使被喚醒的進(jìn)程盡快掌握CPU。 (3)當(dāng)sched_setschedler()或sched_yield()系統(tǒng)調(diào)用被調(diào)用的時(shí)候。第一百三十八頁(yè),共169頁(yè)。主要的進(jìn)程調(diào)度的函數(shù)分析schedule(void):真正執(zhí)行調(diào)度的函數(shù),它選擇一個(gè)最合適的進(jìn)程執(zhí)行,并且真正進(jìn)行上下文切換,使得選中的進(jìn)程得以執(zhí)行。reschedule_idle(structtask_struct*p):為進(jìn)程選擇一個(gè)合適的CPU來(lái)執(zhí)行,如果它選中了某個(gè)CPU,則將該CPU上當(dāng)前運(yùn)行進(jìn)程的need_resched標(biāo)志置為1,然后向它發(fā)出一個(gè)重新調(diào)度的處理機(jī)間中斷,使得選中的CPU能夠在中斷處理返回時(shí)執(zhí)行schedule函數(shù),真正調(diào)度進(jìn)程p在CPU上執(zhí)行。goodness()函數(shù):用來(lái)衡量一個(gè)處于可運(yùn)行狀態(tài)的進(jìn)程值得運(yùn)行的程度。第一百三十九頁(yè),共169頁(yè)。goodness()函數(shù)分析goodness()函數(shù)計(jì)算一個(gè)處于可運(yùn)行狀態(tài)的進(jìn)程值得運(yùn)行的程度。一個(gè)任務(wù)的goodness是以下因素的函數(shù):正在運(yùn)行的任務(wù)、想要運(yùn)行的任務(wù)、當(dāng)前的CPU。goodness返回下面兩類值中的一個(gè):1000以下或者1000以上。1000或者1000以上的值只能賦給“實(shí)時(shí)”進(jìn)程,從0到999的值只能賦給普通進(jìn)程。實(shí)際上,在單處理器情況下,普通進(jìn)程的goodness值只使用這個(gè)范圍底部的一部分,從0到41。在SMP情況下,SMP模式會(huì)優(yōu)先照顧等待同一個(gè)處理器的進(jìn)程。實(shí)時(shí)進(jìn)程的goodness值的范圍是從1001到1099。源碼在sched.c中。第一百四十頁(yè),共169頁(yè)。goodness()計(jì)算進(jìn)程的權(quán)值根據(jù)policy區(qū)分實(shí)時(shí)進(jìn)程和普通進(jìn)程。若為實(shí)時(shí)進(jìn)程返回權(quán)值1000+p->rt_priority。若非實(shí)時(shí)進(jìn)程,將進(jìn)程剩余時(shí)間片加priority作為權(quán)值返回。如果進(jìn)程是內(nèi)核線程或用戶空間與當(dāng)前進(jìn)程相同,因而不必切換用戶空間,則給予權(quán)值額外加一的"優(yōu)惠"。第一百四十一頁(yè),共169頁(yè)。schedule()函數(shù)分析作用:選擇一個(gè)合適的進(jìn)程在CPU上執(zhí)行,它僅僅根據(jù)'goodness'來(lái)工作。流程: ①將prev和next設(shè)置為schedule最感興趣的兩個(gè)進(jìn)程:其中一個(gè)是在調(diào)用schedule時(shí)正在運(yùn)行的進(jìn)程(prev),另外一個(gè)應(yīng)該是接著就給予CPU的進(jìn)程(next)。注意:prev和next可能是相同的-schedule可以重新調(diào)度已經(jīng)獲得cpu的進(jìn)程. ②中斷處理程序運(yùn)行"下半部分". ③內(nèi)核實(shí)時(shí)系統(tǒng)部分的實(shí)現(xiàn),循環(huán)調(diào)度程序(SCHED_RR)通過(guò)移動(dòng)"耗盡的"RR進(jìn)程-已經(jīng)用完其時(shí)間片的進(jìn)程-到隊(duì)列末尾,這樣具有相同優(yōu)先級(jí)的其他RR進(jìn)程就可以獲得CPU了。同時(shí),這補(bǔ)充了耗盡進(jìn)程的時(shí)間片。 ④由于代碼的其他部分已經(jīng)決定了進(jìn)程必須被移進(jìn)或移出TASK_RUNNING狀態(tài),所以會(huì)經(jīng)常使用schedule,例如,如果進(jìn)程正在等待的硬件條件已經(jīng)發(fā)生,所以如果必要,這個(gè)switch會(huì)改變進(jìn)程的狀態(tài)。如果進(jìn)程已經(jīng)處于TASK_RUNNING狀態(tài),它就無(wú)需處理了。如果它是可以中斷的(等待信號(hào)),并且信號(hào)已經(jīng)到達(dá)了進(jìn)程,就返回TASK_RUNNING狀態(tài)。在所以其他情況下(例如,進(jìn)程已經(jīng)處于TASK_UNINTERRUPTIBLE狀態(tài)了),應(yīng)該從運(yùn)行隊(duì)列中將進(jìn)程移走。 ⑤將p初始化為運(yùn)行隊(duì)列的第一個(gè)任務(wù);p會(huì)遍歷隊(duì)列中的所有任務(wù)。 ⑥c記錄了運(yùn)行隊(duì)列中所有進(jìn)程最好的第一百四十二頁(yè),共169頁(yè)。6、進(jìn)程間通信(IPC)第一百四十三頁(yè),共169頁(yè)?;靖拍顬槭裁葱枰狪PC原子操作,死鎖和競(jìng)態(tài)同步第一百四十四頁(yè),共169頁(yè)。管道最常見的IPC機(jī)制通過(guò)pipe系統(tǒng)調(diào)用 #include<unistd.h>intpipe(int[2]);數(shù)據(jù)要經(jīng)過(guò)內(nèi)核傳遞,效率較低只能在關(guān)系進(jìn)程之間進(jìn)行,比如父子進(jìn)程之間管道是單工的第一百四十五頁(yè),共169頁(yè)。使用pipe系統(tǒng)調(diào)用的例子#include<stdio.h>#include<sys/types.h>#include<unistd.h>#defineMAXLINE256voiderr_sys(constchar*info){ perror(info); exit(1);}intmain(void){intn,fd[2];pid_tpid;charline[MAXLINE]; if(pipe(fd)<0)err_sys("pipeerror");if((pid=fork())<0)err_sys("forkerror");elseif(pid>0){//parentclose(fd[0]);write(fd[1],"helloworld\n",12);}else{ //childclose(fd[1]);n=read(fd[0],line,MAXLINE);write(STDOUT_FILENO,line,n);}exit(0);}第一百四十六頁(yè),共169頁(yè)。命名管道命名管道是一種先進(jìn)先出(FIFO)的數(shù)據(jù)結(jié)構(gòu),它允許兩個(gè)進(jìn)程通過(guò)管道聯(lián)接實(shí)現(xiàn)信息交換。

在Unix系統(tǒng)中,命名管道是一種特殊類型的文件,因此可以對(duì)命名管道進(jìn)行讀寫操作;當(dāng)然,同樣

也會(huì)有讀寫和執(zhí)行等權(quán)限的限制。FIFO是存在于文件系統(tǒng)的對(duì)象,用"mknode<name>p",或mkfifo(1,3)命令或函數(shù)建立通過(guò)FIFO的通訊可發(fā)生在任何兩個(gè)進(jìn)程之間,只要對(duì)FIFO有適當(dāng)?shù)脑L問(wèn)權(quán)限對(duì)FIFO的讀寫操作與普通文件類似用FIFO實(shí)現(xiàn)的C/S結(jié)構(gòu)第一百四十七頁(yè),共169頁(yè)。SystemV的IPC機(jī)制消息傳遞共享內(nèi)存:效率最高的IPC機(jī)制,但沒(méi)有同步機(jī)制信號(hào)量:實(shí)際是一種同步機(jī)制,通常與共享內(nèi)存一起使用第一百四十八頁(yè),共169頁(yè)。消息隊(duì)列消息隊(duì)列(messagequeues)是進(jìn)程之間互相發(fā)送消息的一種異步(asynchronously)方式四種與隊(duì)列相關(guān)的系統(tǒng)調(diào)用:msgget——得到唯一標(biāo)識(shí)一個(gè)消息隊(duì)列的標(biāo)識(shí)號(hào)。msgsnd——向一個(gè)消息隊(duì)列發(fā)送一條消息。msgrcv——從一個(gè)消息隊(duì)列中接受一條消息。msgctl——在消息隊(duì)列上執(zhí)行一組管理操作——檢索關(guān)于它的限制的信息(比如隊(duì)列所允許的最大消息數(shù)據(jù)量)、刪除一個(gè)隊(duì)列,等等。

第一百四十九頁(yè),共169頁(yè)。信號(hào)量(Semaphores)Linux內(nèi)核將信號(hào)量分為兩類:非實(shí)時(shí)的(Nonrealtime)——大部分是些傳統(tǒng)的信號(hào)量,例如SIGSEGV,SIGHUP和SIGKILL。實(shí)時(shí)的(realtime)——由POSIX1003.1b標(biāo)準(zhǔn)規(guī)定第一百五十頁(yè),共169頁(yè)。共享內(nèi)存共享內(nèi)存(sharedmemory):一塊預(yù)留出的內(nèi)存區(qū)域,而且一組進(jìn)程均可對(duì)其進(jìn)行訪問(wèn)。共享內(nèi)存是三種IPC機(jī)制里最快的一種,而且也是最簡(jiǎn)單的一種。問(wèn)題:互斥訪問(wèn)第一百五十一頁(yè),共169頁(yè)。第一百五十二頁(yè),共169頁(yè)。7、進(jìn)程編程第一百五十三頁(yè),共169頁(yè)。進(jìn)程控制相關(guān)函數(shù)(1)進(jìn)程標(biāo)識(shí)符 #inclu

溫馨提示

  • 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ì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論