版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
目錄1 文檔介紹 4文檔編寫目的 4文檔閱讀對(duì)象 4涵蓋范圍 4縮略語(yǔ)定義 4參考文檔 42 常見(jiàn)問(wèn)題匯總 52.1 內(nèi)存操作常見(jiàn)問(wèn)題 52.1.1內(nèi)存分配未成功,卻使用了它 52.1.2內(nèi)存分配雖然成功,但是尚未初始化就引用它 52.1.3內(nèi)存分配成功并且已經(jīng)初始化,但操作越過(guò)了內(nèi)存的邊界 52.1.4忘記了釋放內(nèi)存,造成內(nèi)存泄露 52.1.5釋放了內(nèi)存卻繼續(xù)使用它 62.1.6內(nèi)存泄露分類 62.1.7內(nèi)存泄露表現(xiàn) 72.1.8預(yù)防內(nèi)存泄露的措施 72.2 進(jìn)程操作常見(jiàn)問(wèn)題 82.2.1僵尸進(jìn)程的出現(xiàn) 83 內(nèi)存操作 83.1基本理論和常用函數(shù)介紹 83.2基于應(yīng)用的內(nèi)存操作庫(kù)封裝說(shuō)明 134 進(jìn)程操作 134.1基本理論和常用函數(shù)介紹 134.1.1孤兒進(jìn)程與僵尸進(jìn)程 134.1.2守護(hù)進(jìn)程 154.1.3常用進(jìn)程操作函數(shù) 174.1.4生產(chǎn)系統(tǒng)中對(duì)應(yīng)的進(jìn)程控制應(yīng)用 234.2基于應(yīng)用的進(jìn)程操作庫(kù)封裝說(shuō)明 24
文檔介紹文檔編寫目的主要介紹unix下內(nèi)存函數(shù)和進(jìn)程控制函數(shù)的一些用法,并結(jié)合綜合結(jié)算子系統(tǒng)和智能交換平臺(tái)系統(tǒng)進(jìn)行這兩方面的研究:對(duì)在線系統(tǒng)存在的這兩方面問(wèn)題進(jìn)行匯總,提出相應(yīng)的解決方法。將內(nèi)存和進(jìn)程操作函數(shù)進(jìn)行整理劃分,封裝成標(biāo)準(zhǔn)庫(kù),供以后使用。文檔閱讀對(duì)象unix學(xué)習(xí)者系統(tǒng)維護(hù)人員系統(tǒng)開(kāi)發(fā)人員涵蓋范圍內(nèi)存基本操作內(nèi)存泄露問(wèn)題進(jìn)程控制問(wèn)題縮略語(yǔ)定義參考文檔unix環(huán)境高級(jí)編程Linux常用C函數(shù)(中文版)常見(jiàn)問(wèn)題匯總內(nèi)存操作常見(jiàn)問(wèn)題2.1.1內(nèi)存分配未成功,卻使用了它主要是由于在平時(shí)的代碼編寫中,我們常常沒(méi)有意識(shí)到內(nèi)存分配會(huì)不成功,以為沒(méi)有不成功的情況發(fā)生,從而沒(méi)有進(jìn)行異常控制,導(dǎo)致代碼存在不穩(wěn)定性。常用解決辦法是:在使用內(nèi)存之前檢查指針是否為NULL。如果指針p是函數(shù)的參數(shù),那么在函數(shù)的入口處用assert(p!=NULL)進(jìn)行檢查。如果是用malloc或new來(lái)申請(qǐng)內(nèi)存,應(yīng)該if(p==NULL)或if(p!=NULL)進(jìn)行防錯(cuò)處理。2.1.2內(nèi)存分配雖然成功,但是尚未初始化就引用它犯這種錯(cuò)誤主要有兩個(gè)起因:一是沒(méi)有初始化的觀念;二是誤以為內(nèi)存的缺省初值全為零,導(dǎo)致引用初值錯(cuò)誤(例如數(shù)組)。常用解決辦法是:內(nèi)存的缺省初值究竟是什么并沒(méi)有統(tǒng)一的標(biāo)準(zhǔn),盡管有些時(shí)候?yàn)榱阒担覀儗幙尚牌錈o(wú)不可信其有。所以無(wú)論用何種方式創(chuàng)建數(shù)組,都別忘了賦初值,即便是賦零值也不可省略,不要嫌麻煩。2.1.3內(nèi)存分配成功并且已經(jīng)初始化,但操作越過(guò)了內(nèi)存的邊界例如在使用數(shù)組時(shí)經(jīng)常發(fā)生下標(biāo)“多1”或者“少1”的操作。特別是在for循環(huán)語(yǔ)句中,循環(huán)次數(shù)很容易搞錯(cuò),導(dǎo)致數(shù)組操作越界。2.1.4忘記了釋放內(nèi)存,造成內(nèi)存泄露含有這種錯(cuò)誤的函數(shù)每被調(diào)用一次就丟失一塊內(nèi)存。剛開(kāi)始時(shí)系統(tǒng)的內(nèi)存充足,你看不到錯(cuò)誤。終有一次程序突然死掉,系統(tǒng)出現(xiàn)提示:內(nèi)存耗盡。常用解決辦法是:動(dòng)態(tài)內(nèi)存的申請(qǐng)與釋放必須配對(duì),程序中malloc與free的使用次數(shù)一定要相同,否則肯定有錯(cuò)誤(new/delete同理)。2.1.5釋放了內(nèi)存卻繼續(xù)使用它(1)程序中的對(duì)象調(diào)用關(guān)系過(guò)于復(fù)雜,實(shí)在難以搞清楚某個(gè)對(duì)象究竟是否已經(jīng)釋放了內(nèi)存,此時(shí)應(yīng)該重新設(shè)計(jì)數(shù)據(jù)結(jié)構(gòu),從根本上解決對(duì)象管理的混亂局面。(2)函數(shù)的return語(yǔ)句寫錯(cuò)了,注意不要返回指向“棧內(nèi)存”的“指針”或者“引用”,因?yàn)樵搩?nèi)存在函數(shù)體結(jié)束時(shí)被自動(dòng)銷毀。(3)使用free或delete釋放了內(nèi)存后,沒(méi)有將指針設(shè)置為NULL。導(dǎo)致產(chǎn)生“野指針”。2.1.6內(nèi)存泄露分類1.常發(fā)性內(nèi)存泄漏。發(fā)生內(nèi)存泄漏的代碼會(huì)被多次執(zhí)行到,每次被執(zhí)行的時(shí)候都會(huì)導(dǎo)致一塊內(nèi)存泄漏。2.偶發(fā)性內(nèi)存泄漏。發(fā)生內(nèi)存泄漏的代碼只有在某些特定環(huán)境或操作過(guò)程下才會(huì)發(fā)生。常發(fā)性和偶發(fā)性是相對(duì)的。對(duì)于特定的環(huán)境,偶發(fā)性的也許就變成了常發(fā)性的。所以測(cè)試環(huán)境和測(cè)試方法對(duì)檢測(cè)內(nèi)存泄漏至關(guān)重要。3.一次性內(nèi)存泄漏。發(fā)生內(nèi)存泄漏的代碼只會(huì)被執(zhí)行一次,或者由于算法上的缺陷,導(dǎo)致總會(huì)有一塊且僅有一塊內(nèi)存發(fā)生泄漏。4.隱式內(nèi)存泄漏。程序在運(yùn)行過(guò)程中不停的分配內(nèi)存,但是直到結(jié)束的時(shí)候才釋放內(nèi)存。嚴(yán)格的說(shuō)這里并沒(méi)有發(fā)生內(nèi)存泄漏,因?yàn)樽罱K程序釋放了所有申請(qǐng)的內(nèi)存。但是對(duì)于一個(gè)服務(wù)器程序,需要運(yùn)行幾天,幾周甚至幾個(gè)月,不及時(shí)釋放內(nèi)存也可能導(dǎo)致最終耗盡系統(tǒng)的所有內(nèi)存。所以,我們稱這類內(nèi)存泄漏為隱式內(nèi)存泄漏。2.1.7內(nèi)存泄露表現(xiàn)內(nèi)存泄漏或者是說(shuō),資源耗盡后,系統(tǒng)會(huì)表現(xiàn)出什么現(xiàn)象哪?cpu資源耗盡:估計(jì)是機(jī)器沒(méi)有反應(yīng)了,鍵盤,鼠標(biāo),以及網(wǎng)絡(luò)等等。這個(gè)在windows上經(jīng)??匆?jiàn),特別是中了毒。進(jìn)程id耗盡:沒(méi)法創(chuàng)建新的進(jìn)程了,串口或者telnet都沒(méi)法創(chuàng)建了。硬盤耗盡:機(jī)器要死了,交換內(nèi)存沒(méi)法用,日志也沒(méi)法用了,死是很正常的。內(nèi)存泄漏或者內(nèi)存耗盡:新的連接無(wú)法創(chuàng)建,free的內(nèi)存比較少。發(fā)生內(nèi)存泄漏的程序很多,但是要想產(chǎn)生一定的后果,就需要這個(gè)進(jìn)程是無(wú)限循環(huán)的,是個(gè)服務(wù)進(jìn)程。當(dāng)然,內(nèi)核也是無(wú)限循環(huán)的,所以,如果內(nèi)核發(fā)生了內(nèi)存泄漏,情況就更加不妙。內(nèi)存泄漏是一種很難定位和跟蹤的錯(cuò)誤,目前還沒(méi)看到有什么好用的工具(當(dāng)然,用戶空間有一些工具,有靜態(tài)分析的,也會(huì)動(dòng)態(tài)分析的,但是找內(nèi)核的內(nèi)存泄漏,沒(méi)有好的開(kāi)源工具)內(nèi)存泄漏和對(duì)象的引用計(jì)數(shù)有很大的關(guān)系,再加上c/c都沒(méi)有自動(dòng)的垃圾回收機(jī)制,如果沒(méi)有手動(dòng)釋放內(nèi)存,問(wèn)題就會(huì)出現(xiàn)。如果要避免這個(gè)問(wèn)題,還是要從代碼上入手,良好的編碼習(xí)慣和規(guī)范,是避免錯(cuò)誤的不二法門。一般我們常說(shuō)的內(nèi)存泄漏是指堆內(nèi)存的泄漏。堆內(nèi)存是指程序從堆中分配的,大小任意的(內(nèi)存塊的大小可以在程序運(yùn)行期決定),使用完后必須顯示釋放的內(nèi)存。應(yīng)用程序一般使用malloc,realloc,new等函數(shù)從堆中分配到一塊內(nèi)存,使用完后,程序必須負(fù)責(zé)相應(yīng)的調(diào)用free或delete釋放該內(nèi)存塊,否則,這塊內(nèi)存就不能被再次使用,我們就說(shuō)這塊內(nèi)存泄漏了。2.1.8預(yù)防內(nèi)存泄露的措施1、減小單個(gè)函數(shù)的代碼行數(shù)。2、及時(shí)釋放動(dòng)態(tài)分配的內(nèi)存。3、盡量使用同一系列的內(nèi)存操作函數(shù)進(jìn)行內(nèi)存的分配和釋放。4、實(shí)現(xiàn)自己的內(nèi)存管理策略。5、在代碼中引入一些機(jī)制來(lái)檢查內(nèi)存泄露。比如通過(guò)俘獲標(biāo)準(zhǔn)C庫(kù)的內(nèi)存操作函數(shù),添加一些處理,記錄下內(nèi)存的分配和使用情況,找出泄露點(diǎn)。6、使用專業(yè)的工具進(jìn)行檢測(cè)。進(jìn)程操作常見(jiàn)問(wèn)題2.2.1僵尸進(jìn)程的出現(xiàn)在Unix系統(tǒng)管理中,當(dāng)用ps命令觀察進(jìn)程的執(zhí)行狀態(tài)時(shí),經(jīng)常看到某些進(jìn)程的狀態(tài)欄為defunct,這就是所謂的“僵尸”進(jìn)程?!敖┦边M(jìn)程是一個(gè)早已死亡的進(jìn)程,但在進(jìn)程表(processstable)中仍占了一個(gè)位置(slot)。由于進(jìn)程表的容量是有限的,所以,defunct進(jìn)程不僅占用系統(tǒng)的內(nèi)存資源,影響系統(tǒng)的性能,而且如果其數(shù)目太多,還會(huì)導(dǎo)致系統(tǒng)癱瘓。產(chǎn)生的部分原因:1)一個(gè)進(jìn)程在調(diào)用exit命令結(jié)束自己的生命的時(shí)候,其實(shí)它并沒(méi)有真正的被銷毀,而是留下一個(gè)稱為僵尸進(jìn)程(Zombie)的數(shù)據(jù)結(jié)構(gòu)(系統(tǒng)調(diào)用exit,它的作用是使進(jìn)程退出,但也僅僅限于將一個(gè)正常的進(jìn)程變成一個(gè)僵尸進(jìn)程,并不能將其完全銷毀)。避免方法:1)子進(jìn)程成為defunct直到父進(jìn)程wait(),除非父進(jìn)程忽略了SIGCLD。2)父進(jìn)程沒(méi)有wait()就消亡(仍假設(shè)父進(jìn)程沒(méi)有忽略SIGCLD)的子進(jìn)程(活動(dòng)的或者defunct)成為init的子進(jìn)程,init用重手法處理它們。內(nèi)存操作3.1基本理論和常用函數(shù)介紹內(nèi)存常見(jiàn)的分配方式:1)從靜態(tài)存儲(chǔ)區(qū)域分配。內(nèi)存在程序編譯的時(shí)候就已經(jīng)分配好,這塊內(nèi)存在程序的整個(gè)運(yùn)行期間都存在。例如全局變量,static變量。2)在棧上創(chuàng)建。在執(zhí)行函數(shù)時(shí),函數(shù)內(nèi)局部變量的存儲(chǔ)單元都可以在棧上創(chuàng)建,函數(shù)執(zhí)行結(jié)束時(shí)這些存儲(chǔ)單元自動(dòng)被釋放。棧內(nèi)存分配運(yùn)算內(nèi)置于處理器的指令集中,效率很高,但是分配的內(nèi)存容量有限。3)從堆上分配,亦稱動(dòng)態(tài)內(nèi)存分配。程序在運(yùn)行的時(shí)候用malloc或new申請(qǐng)任意多少的內(nèi)存,程序員自己負(fù)責(zé)在何時(shí)用free或delete釋放內(nèi)存。動(dòng)態(tài)內(nèi)存的生存期由我們決定,使用非常靈活,但問(wèn)題也最多。認(rèn)識(shí)以下幾點(diǎn)規(guī)則,有助于在編碼時(shí)出錯(cuò):【規(guī)則1】用malloc或new申請(qǐng)內(nèi)存之后,應(yīng)該立即檢查指針值是否為NULL。防止使用指針值為NULL的內(nèi)存。【規(guī)則2】不要忘記為數(shù)組和動(dòng)態(tài)內(nèi)存賦初值。防止將未被初始化的內(nèi)存作為右值使用?!疽?guī)則3】避免數(shù)組或指針的下標(biāo)越界,特別要當(dāng)心發(fā)生“多1”或者“少1”操作。【規(guī)則4】動(dòng)態(tài)內(nèi)存的申請(qǐng)與釋放必須配對(duì),防止內(nèi)存泄漏?!疽?guī)則5】用free或delete釋放了內(nèi)存之后,立即將指針設(shè)置為NULL,防止產(chǎn)生“野指針”。常用的函數(shù)如下:CallocFreeMallocMmapMumap下面簡(jiǎn)單介紹下其中幾個(gè)函數(shù)的使用方式:malloc()函數(shù):void*malloc(size_tsize)其中的size即為所用分配的內(nèi)存空間的大小。malloc函數(shù)有一個(gè)將可用的內(nèi)存塊連接為一個(gè)長(zhǎng)長(zhǎng)的列表的所謂空閑鏈表。調(diào)用malloc函數(shù)的時(shí)候,它將沿著連接表尋找一個(gè)大到足以滿足用戶請(qǐng)求所需要的內(nèi)存塊。calloc()函數(shù):void*calloc(size_tnumElements,size_tsizeOfElement);其中numElements為分配的元素的個(gè)數(shù),而sizeOfElement即為每個(gè)元素的大小了。這樣,這兩個(gè)數(shù)的乘積即為要分配的空間的大小了。如果函數(shù)的調(diào)用成功,則malloc()和calloc()這兩個(gè)函數(shù)返回的都將為分配的內(nèi)存空間的首地址。函數(shù)malloc()和函數(shù)calloc()的主要區(qū)別1)malloc()不能初始化所分配的內(nèi)存空間,而calloc()能。如果由malloc()函數(shù)分配的內(nèi)存空間原來(lái)沒(méi)有被使用過(guò),則其中的每一位可能都是0;反之,如果這部分內(nèi)存曾經(jīng)被分配過(guò),則其中可能遺留有各種各樣的數(shù)據(jù)。也就是說(shuō),使用malloc()函數(shù)的程序開(kāi)始時(shí)(內(nèi)存空間還沒(méi)有被重新分配)能正常進(jìn)行,但經(jīng)過(guò)一段時(shí)間(內(nèi)存空間還已經(jīng)被重新分配)可能會(huì)出現(xiàn)問(wèn)題。函數(shù)calloc()會(huì)將所分配的內(nèi)存空間中的每一位都初始化為零,也就是說(shuō),如果你是為字符類型或整數(shù)類型的元素分配內(nèi)存,那麼這些元素將保證會(huì)被初始化為0;如果你是為指針類型的元素分配內(nèi)存,那麼這些元素通常會(huì)被初始化為空指針;如果你為實(shí)型數(shù)據(jù)分配內(nèi)存,則這些元素會(huì)被初始化為浮點(diǎn)型的零。2)另外,calloc返回的是一組對(duì)象的數(shù)組,而malloc返回的是一個(gè)對(duì)象。使用calloc表明是要使用一個(gè)數(shù)組。externvoid*realloc(void*mem_address,unsignedintnewsize);功能:改變mem_address所指內(nèi)存區(qū)域的大小為newsize長(zhǎng)度。1、如果有足夠空間用于擴(kuò)大mem_address指向的內(nèi)存塊,則分配額外內(nèi)存,并返回mem_address,這里說(shuō)的是“擴(kuò)大”,我們知道,realloc是從堆上分配內(nèi)存的,當(dāng)擴(kuò)大一塊內(nèi)存空間時(shí),realloc()試圖直接從堆上現(xiàn)存的數(shù)據(jù)后面的那些字節(jié)中獲得附加的字節(jié),如果能夠滿足,自然天下太平。也就是說(shuō),如果原先的內(nèi)存大小后面還有足夠的空閑空間用來(lái)分配,加上原來(lái)的空間大小=newsize。那么就ok。得到的是一塊連續(xù)的內(nèi)存。2、如果原先的內(nèi)存大小后面沒(méi)有足夠的空閑空間用來(lái)分配,那么從堆中另外找一塊newsize大小的內(nèi)存。并把原來(lái)大小內(nèi)存空間中的內(nèi)容復(fù)制到newsize中。返回新的mem_address指針。(數(shù)據(jù)被移動(dòng)了)。老塊被放回堆上。如果以第二種方式分配內(nèi)存,此時(shí)數(shù)據(jù)發(fā)生了移動(dòng),那么所記錄的原來(lái)的內(nèi)存地址q所指向的內(nèi)存空間實(shí)際上已經(jīng)放回到堆上了!這樣就會(huì)產(chǎn)生q指針的指針懸掛,如果再用q指針進(jìn)行操作就可能發(fā)生意想不到的問(wèn)題。所以在應(yīng)用realloc函數(shù)是應(yīng)當(dāng)格外注意這種情況。Mmap功能描述mmap將一個(gè)文件或者其它對(duì)象映射進(jìn)內(nèi)存。文件被映射到多個(gè)頁(yè)上,如果文件的大小不是所有頁(yè)的大小之和,最后一個(gè)頁(yè)不被使用的空間將會(huì)清零。munmap執(zhí)行相反的操作,刪除特定地址區(qū)域的對(duì)象映射?;谖募挠成洌趍map和munmap執(zhí)行過(guò)程的任何時(shí)刻,被映射文件的st_atime可能被更新。如果st_atime字段在前述的情況下沒(méi)有得到更新,首次對(duì)映射區(qū)的第一個(gè)頁(yè)索引時(shí)會(huì)更新該字段的值。用PROT_WRITE和MAP_SHARED標(biāo)志建立起來(lái)的文件映射,其st_ctime和st_mtime在對(duì)映射區(qū)寫入之后,但在msync()通過(guò)MS_SYNC和MS_ASYNC兩個(gè)標(biāo)志調(diào)用之前會(huì)被更新。用法#include<sys/mman.h>void*mmap(void*start,size_tlength,intprot,intflags,intfd,off_toffset);intmunmap(void*start,size_tlength);參數(shù):start:映射區(qū)的開(kāi)始地址。length:映射區(qū)的長(zhǎng)度。prot:期望的內(nèi)存保護(hù)標(biāo)志,不能與文件的打開(kāi)模式?jīng)_突。是以下的某個(gè)值,可以通過(guò)or運(yùn)算合理地組合在一起PROT_EXEC//頁(yè)內(nèi)容可以被執(zhí)行PROT_READ//頁(yè)內(nèi)容可以被讀取PROT_WRITE//頁(yè)可以被寫入PROT_NONE//頁(yè)不可訪問(wèn)flags:指定映射對(duì)象的類型,映射選項(xiàng)和映射頁(yè)是否可以共享。它的值可以是一個(gè)或者多個(gè)以下位的組合體MAP_FIXED//使用指定的映射起始地址,如果由start和len參數(shù)指定的內(nèi)存區(qū)重疊于現(xiàn)存的映射空間,重疊部分將會(huì)被丟棄。如果指定的起始地址不可用,操作將會(huì)失敗。并且起始地址必須落在頁(yè)的邊界上。MAP_SHARED//與其它所有映射這個(gè)對(duì)象的進(jìn)程共享映射空間。對(duì)共享區(qū)的寫入,相當(dāng)于輸出到文件。直到msync()或者munmap()被調(diào)用,文件實(shí)際上不會(huì)被更新。MAP_PRIVATE//建立一個(gè)寫入時(shí)拷貝的私有映射。內(nèi)存區(qū)域的寫入不會(huì)影響到原文件。這個(gè)標(biāo)志和以上標(biāo)志是互斥的,只能使用其中一個(gè)。MAP_DENYWRITE//這個(gè)標(biāo)志被忽略。MAP_EXECUTABLE//同上MAP_NORESERVE//不要為這個(gè)映射保留交換空間。當(dāng)交換空間被保留,對(duì)映射區(qū)修改的可能會(huì)得到保證。當(dāng)交換空間不被保留,同時(shí)內(nèi)存不足,對(duì)映射區(qū)的修改會(huì)引起段違例信號(hào)。MAP_LOCKED//鎖定映射區(qū)的頁(yè)面,從而防止頁(yè)面被交換出內(nèi)存。MAP_GROWSDOWN//用于堆棧,告訴內(nèi)核VM系統(tǒng),映射區(qū)可以向下擴(kuò)展。MAP_ANONYMOUS//匿名映射,映射區(qū)不與任何文件關(guān)聯(lián)。MAP_ANON//MAP_ANONYMOUS的別稱,不再被使用。MAP_FILE//兼容標(biāo)志,被忽略。MAP_32BIT//將映射區(qū)放在進(jìn)程地址空間的低2GB,MAP_FIXED指定時(shí)會(huì)被忽略。當(dāng)前這個(gè)標(biāo)志只在x86-64平臺(tái)上得到支持。MAP_POPULATE//為文件映射通過(guò)預(yù)讀的方式準(zhǔn)備好頁(yè)表。隨后對(duì)映射區(qū)的訪問(wèn)不會(huì)被頁(yè)違例阻塞。MAP_NONBLOCK//僅和MAP_POPULATE一起使用時(shí)才有意義。不執(zhí)行預(yù)讀,只為已存在于內(nèi)存中的頁(yè)面建立頁(yè)表入口。fd:有效的文件描述詞。如果MAP_ANONYMOUS被設(shè)定,為了兼容問(wèn)題,其值應(yīng)為-1。offset:被映射對(duì)象內(nèi)容的起點(diǎn)。返回說(shuō)明:成功執(zhí)行時(shí),mmap()返回被映射區(qū)的指針,munmap()返回0。失敗時(shí),mmap()返回MAP_FAILED[其值為(void*)-1],munmap返回-1。errno被設(shè)為以下的某個(gè)值EACCES:訪問(wèn)出錯(cuò)EAGAIN:文件已被鎖定,或者太多的內(nèi)存已被鎖定EBADF:fd不是有效的文件描述詞EINVAL:一個(gè)或者多個(gè)參數(shù)無(wú)效ENFILE:已達(dá)到系統(tǒng)對(duì)打開(kāi)文件的限制ENODEV:指定文件所在的文件系統(tǒng)不支持內(nèi)存映射ENOMEM:內(nèi)存不足,或者進(jìn)程已超出最大內(nèi)存映射數(shù)量EPERM:權(quán)能不足,操作不允許ETXTBSY:已寫的方式打開(kāi)文件,同時(shí)指定MAP_DENYWRITE標(biāo)志SIGSEGV:試著向只讀區(qū)寫入SIGBUS:試著訪問(wèn)不屬于進(jìn)程的內(nèi)存區(qū)3.2基于應(yīng)用的內(nèi)存操作庫(kù)封裝說(shuō)明1)內(nèi)存空間分配的庫(kù)函數(shù)封裝進(jìn)程操作4.1基本理論和常用函數(shù)介紹4.1.1孤兒進(jìn)程與僵尸進(jìn)程在Unix系統(tǒng)編程中,常常會(huì)碰到兩個(gè)概念:僵死進(jìn)程和孤兒進(jìn)程。以前曾經(jīng)把這兩個(gè)概念弄混淆過(guò)。什么是僵死進(jìn)程?我們知道,在Unix進(jìn)程模型中,進(jìn)程是按照父進(jìn)程產(chǎn)生子進(jìn)程,子進(jìn)程產(chǎn)生子子進(jìn)程這樣的方式創(chuàng)建出完成各項(xiàng)相互協(xié)作功能的進(jìn)程的。當(dāng)一個(gè)進(jìn)程完成它的工作終止之后,它的父進(jìn)程需要調(diào)用wait()或者waitpid()系統(tǒng)調(diào)用取得子進(jìn)程的終止?fàn)顟B(tài)。如果父進(jìn)程沒(méi)有這么做的話,會(huì)產(chǎn)生什么后果呢?此時(shí),子進(jìn)程雖然已經(jīng)退出了,但是在系統(tǒng)進(jìn)程表中還為它保留了一些退出狀態(tài)的信息,如果父進(jìn)程一直不取得這些退出信息的話,這些進(jìn)程表項(xiàng)就將一直被占用,此時(shí),這些占著茅坑不拉屎的子進(jìn)程就成為“僵死進(jìn)程”(zombie)。系統(tǒng)進(jìn)程表是一項(xiàng)有限資源,如果系統(tǒng)進(jìn)程表被僵死進(jìn)程耗盡的話,系統(tǒng)就可能無(wú)法創(chuàng)建新的進(jìn)程。那么,孤兒進(jìn)程又是怎么回事呢?孤兒進(jìn)程是指這樣一類進(jìn)程:在進(jìn)程還未退出之前,它的父進(jìn)程就已經(jīng)退出了,一個(gè)沒(méi)有了父進(jìn)程的子進(jìn)程就是一個(gè)孤兒進(jìn)程(orphan)。既然所有進(jìn)程都必須在退出之后被wait()或waitpid()以釋放其遺留在系統(tǒng)中的一些資源,那么應(yīng)該由誰(shuí)來(lái)處理孤兒進(jìn)程的善后事宜呢?這個(gè)重任就落到了init進(jìn)程身上,init進(jìn)程就好像是一個(gè)民政局,專門負(fù)責(zé)處理孤兒進(jìn)程的善后工作。每當(dāng)出現(xiàn)一個(gè)孤兒進(jìn)程的時(shí)候,內(nèi)核就把孤兒進(jìn)程的父進(jìn)程設(shè)置為init,而init進(jìn)程會(huì)循環(huán)地wait()它的已經(jīng)退出的子進(jìn)程。這樣,當(dāng)一個(gè)孤兒進(jìn)程“凄涼地”結(jié)束了其生命周期的時(shí)候,init進(jìn)程就會(huì)代表黨和政府出面處理它的一切善后工作。這樣來(lái)看,孤兒進(jìn)程并不會(huì)有什么危害,真正會(huì)對(duì)系統(tǒng)構(gòu)成威脅的是僵死進(jìn)程。那么,什么情況下僵死進(jìn)程會(huì)威脅系統(tǒng)的穩(wěn)定呢?設(shè)想有這樣一個(gè)父進(jìn)程:它定期的產(chǎn)生一個(gè)子進(jìn)程,這個(gè)子進(jìn)程需要做的事情很少,做完它該做的事情之后就退出了,因此這個(gè)子進(jìn)程的生命周期很短,但是,父進(jìn)程只管生成新的子進(jìn)程,至于子進(jìn)程退出之后的事情,則一概不聞不問(wèn),這樣,系統(tǒng)運(yùn)行上一段時(shí)間之后,系統(tǒng)中就會(huì)存在很多的僵死進(jìn)程,倘若用ps命令查看的話,就會(huì)看到很多狀態(tài)為Z的進(jìn)程。嚴(yán)格地來(lái)說(shuō),僵死進(jìn)程并不是問(wèn)題的根源,罪魁禍?zhǔn)资钱a(chǎn)生出大量僵死進(jìn)程的那個(gè)父進(jìn)程。因此,當(dāng)我們尋求如何消滅系統(tǒng)中大量的僵死進(jìn)程時(shí),答案就是把產(chǎn)生大量僵死進(jìn)程的那個(gè)元兇槍斃掉(也就是通過(guò)kill發(fā)送SIGTERM或者SIGKILL信號(hào)啦)。槍斃了元兇進(jìn)程之后,它產(chǎn)生的僵死進(jìn)程就變成了孤兒進(jìn)程,這些孤兒進(jìn)程會(huì)被init進(jìn)程接管,init進(jìn)程會(huì)wait()這些孤兒進(jìn)程,釋放它們占用的系統(tǒng)進(jìn)程表中的資源,這樣,這些已經(jīng)“僵死”的孤兒進(jìn)程就能瞑目而去了。在避免僵尸進(jìn)程上,要考慮以下幾點(diǎn):1)捕捉SIGCHLD信號(hào),并在信號(hào)處理函數(shù)里面調(diào)用wait函數(shù)。2)兩次fork()。4.1.2守護(hù)進(jìn)程守護(hù)進(jìn)程在Linux/Unix系統(tǒng)中有著廣泛的應(yīng)用。有時(shí),開(kāi)發(fā)人員也想把自己的程序變成守護(hù)進(jìn)程。在創(chuàng)建一個(gè)守護(hù)進(jìn)程的時(shí)候,要接觸到子進(jìn)程、進(jìn)程組、會(huì)晤期、信號(hào)機(jī)制、文件、目錄和控制終端等多個(gè)概念。因此守護(hù)進(jìn)程還是比較復(fù)雜的,在這里詳細(xì)地討論Linux/Unix的守護(hù)進(jìn)程的編寫,總結(jié)出八條經(jīng)驗(yàn),并給出應(yīng)用范例。編程要點(diǎn)1.屏蔽一些有關(guān)控制終端操作的信號(hào)。防止在守護(hù)進(jìn)程沒(méi)有正常運(yùn)轉(zhuǎn)起來(lái)時(shí),控制終端受到干擾退出或掛起。示例如下:signal(SIGTTOU,SIG_IGN);signal(SIGTTIN,SIG_IGN);signal(SIGTSTP,SIG_IGN);signal(SIGHUP,SIG_IGN);所有的信號(hào)都有自己的名字。這些名字都以“SIG”開(kāi)頭,只是后面有所不同。開(kāi)發(fā)人員可以通過(guò)這些名字了解到系統(tǒng)中發(fā)生了什么事。當(dāng)信號(hào)出現(xiàn)時(shí),開(kāi)發(fā)人員可以要求系統(tǒng)進(jìn)行以下三種操作:◆忽略信號(hào)。大多數(shù)信號(hào)都是采取這種方式進(jìn)行處理的,這里就采用了這種用法。但值得注意的是對(duì)SIGKILL和SIGSTOP信號(hào)不能做忽略處理?!舨蹲叫盘?hào)。最常見(jiàn)的情況就是,如果捕捉到SIGCHID信號(hào),則表示子進(jìn)程已經(jīng)終止。然后可在此信號(hào)的捕捉函數(shù)中調(diào)用waitpid()函數(shù)取得該子進(jìn)程的進(jìn)程ID和它的終止?fàn)顟B(tài)。另外,如果進(jìn)程創(chuàng)建了臨時(shí)文件,那么就要為進(jìn)程終止信號(hào)SIGTERM編寫一個(gè)信號(hào)捕捉函數(shù)來(lái)清除這些臨時(shí)文件?!魣?zhí)行系統(tǒng)的默認(rèn)動(dòng)作。對(duì)絕大多數(shù)信號(hào)而言,系統(tǒng)的默認(rèn)動(dòng)作都是終止該進(jìn)程。對(duì)這些有關(guān)終端的信號(hào),一般采用忽略處理,從而保障了終端免受干擾。這類信號(hào)分別是,SIGTTOU(表示后臺(tái)進(jìn)程寫控制終端)、SIGTTIN(表示后臺(tái)進(jìn)程讀控制終端)、SIGTSTP(表示終端掛起)和SIGHUP(進(jìn)程組長(zhǎng)退出時(shí)向所有會(huì)議成員發(fā)出的)。2.將程序進(jìn)入后臺(tái)執(zhí)行。由于守護(hù)進(jìn)程最終脫離控制終端,到后臺(tái)去運(yùn)行。方法是在進(jìn)程中調(diào)用fork使父進(jìn)程終止,讓Daemon在子進(jìn)程中后臺(tái)執(zhí)行。這就是常說(shuō)的“脫殼”。子進(jìn)程繼續(xù)函數(shù)fork()的定義如下:#include#includepid_tfork(void);該函數(shù)是Linux/Unix編程中非常重要的函數(shù)。它被調(diào)用一次,但返回兩次。這兩次返回的區(qū)別是子進(jìn)程的返回值為“0”,而父進(jìn)程的返回值為子進(jìn)程的ID。如果出錯(cuò)則返回“-1”。3.脫離控制終端、登錄會(huì)話和進(jìn)程組。開(kāi)發(fā)人員如果要擺脫它們,不受它們的影響,一般使用setsid()設(shè)置新會(huì)話的領(lǐng)頭進(jìn)程,并與原來(lái)的登錄會(huì)話和進(jìn)程組脫離。這只是其中的一種方法,也有如下處理的辦法:if((fd=open("/dev/tty",O_RDWR))>=0){ioctl(fd,TIOCNOTTY,NULL);close(fd);}其中/dev/tty是一個(gè)流設(shè)備,也是終端映射,調(diào)用close()函數(shù)將終端關(guān)閉。4.禁止進(jìn)程重新打開(kāi)控制終端。進(jìn)程已經(jīng)成為無(wú)終端的會(huì)話組長(zhǎng),但它可以重新申請(qǐng)打開(kāi)一個(gè)控制終端。開(kāi)發(fā)人員可以通過(guò)不再讓進(jìn)程成為會(huì)話組長(zhǎng)的方式來(lái)禁止進(jìn)程重新打開(kāi)控制終端,需要再次調(diào)用fork函數(shù)。上面的程序代碼表示結(jié)束第一子進(jìn)程,第二子進(jìn)程繼續(xù)(第二子進(jìn)程不再是會(huì)話組長(zhǎng))。5.關(guān)閉打開(kāi)的文件描述符,并重定向標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤輸出的文件描述符。進(jìn)程從創(chuàng)建它的父進(jìn)程那里繼承了打開(kāi)的文件描述符。如果不關(guān)閉,將會(huì)浪費(fèi)系統(tǒng)資源,引起無(wú)法預(yù)料的錯(cuò)誤。關(guān)閉三者的代碼如下:for(fd=0,fdtablesize=getdtablesize();fd0)……}8.在Linux/Unix下有個(gè)syslogd的守護(hù)進(jìn)程,向用戶提供了syslog()系統(tǒng)調(diào)用。任何程序都可以通過(guò)syslog記錄事件。由于syslog非常好用和易配置,所以很多程序都使用syslog來(lái)發(fā)送它們的記錄信息。一般守護(hù)進(jìn)程也使用syslog向系統(tǒng)輸出信息。syslog有三個(gè)函數(shù),一般只需要用syslog(...)函數(shù),openlog()/closelog()可有可無(wú)。syslog()在shslog.h定義如下:#includevoidsyslog(intpriority,char*format,...);其中參數(shù)priority指明了進(jìn)程要寫入信息的等級(jí)和用途。第二個(gè)參數(shù)是一個(gè)格式串,指定了記錄輸出的格式。在這個(gè)串的最后需要指定一個(gè)%m,對(duì)應(yīng)errno錯(cuò)誤碼。應(yīng)用范例下面給出Linux下編程的守護(hù)進(jìn)程的應(yīng)用范例,在UNIX中,不同版本實(shí)現(xiàn)的細(xì)節(jié)可能不一致,但其實(shí)現(xiàn)的原則是與Linux一致的。main(intargc,char**argv){time_tnow;intchildpid,fd,fdtablesize;interror,in,out;/*忽略終端I/O信號(hào),STOP信號(hào)*/signal(SIGTTOU,SIG_IGN);signal(SIGTTIN,SIG_IGN);signal(SIGTSTP,SIG_IGN);signal(SIGHUP,SIG_IGN);/*父進(jìn)程退出,程序進(jìn)入后臺(tái)運(yùn)行*/if(fork()!=0)exit(1);if(setsid()<0)exit(1);/*創(chuàng)建一個(gè)新的會(huì)議組*//*子進(jìn)程退出,孫進(jìn)程沒(méi)有控制終端了*/if(fork()!=0)exit(1);if(chdir("/tmp")==-1)exit(1);/*關(guān)閉打開(kāi)的文件描述符,包括標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤輸出*/for(fd=0,fdtablesize=getdtablesize();fd<fdtablesize;fd++)close(fd);umask(0);/*重設(shè)文件創(chuàng)建掩模*/signal(SIGCHLD,SIG_IGN);/*忽略SIGCHLD信號(hào)*//*打開(kāi)log系統(tǒng)*/syslog(LOG_USER|LOG_INFO,"守護(hù)進(jìn)程測(cè)試!\n");while(1){time(&now);syslog(LOG_USER|LOG_INFO,"當(dāng)前時(shí)間:\t%s\t\t\n",ctime(&now));sleep(6);}}4.1.3常用進(jìn)程操作函數(shù)以下是常用函數(shù)匯總:ExitExeclExeclpExecvExecveExecvpGetpidGetppidSystemForkVforkWaitwaitpid1)pid_tfork(void);頭文件:#include<sys/types.h>#include<unistd.h>返回:子進(jìn)程中為0,父進(jìn)程中為子進(jìn)程ID,出錯(cuò)為-1由fork創(chuàng)建的新進(jìn)程被稱為子進(jìn)程(childprocess)。該函數(shù)被調(diào)用一次,但返回兩次。兩次返回的區(qū)別是子進(jìn)程的返回值是0,而父進(jìn)程的返回值則是新子進(jìn)程的進(jìn)程ID。將子進(jìn)程ID返回給父進(jìn)程的理由是:因?yàn)橐粋€(gè)進(jìn)程的子進(jìn)程可以多于一個(gè),所以沒(méi)有一個(gè)函數(shù)使一個(gè)進(jìn)程可以獲得其所有子進(jìn)程的進(jìn)程ID。fork使子進(jìn)程得到返回值0的理由是:一個(gè)進(jìn)程只會(huì)有一個(gè)父進(jìn)程,所以子進(jìn)程總是可以調(diào)用getppid以獲得其父進(jìn)程的進(jìn)程ID(進(jìn)程ID0總是由交換進(jìn)程使用,所以一個(gè)子進(jìn)程的進(jìn)程ID不可能為0)。子進(jìn)程和父進(jìn)程繼續(xù)執(zhí)行fork之后的指令。子進(jìn)程是父進(jìn)程的復(fù)制品。例如,子進(jìn)程獲得父進(jìn)程數(shù)據(jù)空間、堆和棧的復(fù)制品。注意,這是子進(jìn)程所擁有的拷貝。父、子進(jìn)程并不共享這些存儲(chǔ)空間部分。如果正文段是只讀的,則父、子進(jìn)程共享正文段。現(xiàn)在很多的實(shí)現(xiàn)并不做一個(gè)父進(jìn)程數(shù)據(jù)段和堆的完全拷貝,因?yàn)樵趂ork之后經(jīng)常跟隨著exec。作為替代,使用了在寫時(shí)復(fù)制(Copy-On-Write,COW)的技術(shù)。這些區(qū)域由父、子進(jìn)程共享,而且內(nèi)核將它們的存取許可權(quán)改變?yōu)橹蛔x的。如果有進(jìn)程試圖修改這些區(qū)域,則內(nèi)核為有關(guān)部分,典型的是虛存系統(tǒng)中的“頁(yè)”,做一個(gè)拷貝.一般來(lái)說(shuō),在fork之后是父進(jìn)程先執(zhí)行還是子進(jìn)程先執(zhí)行是不確定的。這取決于內(nèi)核所使用的調(diào)度算法。如果要求父、子進(jìn)程之間相互同步,則要求某種形式的進(jìn)程間通信.pid_twaitpid(pid_tpid,int*status,intoptions);waitpid函數(shù)原型:#include<sys/types.h>/*提供類型pid_t的定義*/#include<sys/wait.h>pid_twaitpid(pid_tpid,int*status,intoptions);從本質(zhì)上講,系統(tǒng)調(diào)用waitpid和wait的作用是完全相同的,但waitpid多出了兩個(gè)可由用戶控制的參數(shù)pid和options,從而為我們編程提供了另一種更靈活的方式。下面我們就來(lái)詳細(xì)介紹一下這兩個(gè)參數(shù):pid從參數(shù)的名字pid和類型pid_t中就可以看出,這里需要的是一個(gè)進(jìn)程ID。但當(dāng)pid取不同的值時(shí),在這里有不同的意義。1.pid>0時(shí),只等待進(jìn)程ID等于pid的子進(jìn)程,不管其它已經(jīng)有多少子進(jìn)程運(yùn)行結(jié)束退出了,只要指定的子進(jìn)程還沒(méi)有結(jié)束,waitpid就會(huì)一直等下去。2.pid=-1時(shí),等待任何一個(gè)子進(jìn)程退出,沒(méi)有任何限制,此時(shí)waitpid和wait的作用一模一樣。3.pid=0時(shí),等待同一個(gè)進(jìn)程組中的任何子進(jìn)程,如果子進(jìn)程已經(jīng)加入了別的進(jìn)程組,waitpid不會(huì)對(duì)它做任何理睬。4.pid<-1時(shí),等待一個(gè)指定進(jìn)程組中的任何子進(jìn)程,這個(gè)進(jìn)程組的ID等于pid的絕對(duì)值。optionsoptions提供了一些額外的選項(xiàng)來(lái)控制waitpid,目前在Linux中只支持WNOHANG和WUNTRACED兩個(gè)選項(xiàng),這是兩個(gè)常數(shù),可以用”|”運(yùn)算符把它們連接起來(lái)使用,比如:ret=waitpid(-1,NULL,WNOHANG|WUNTRACED);如果我們不想使用它們,也可以把options設(shè)為0,如:ret=waitpid(-1,NULL,0);如果使用了WNOHANG參數(shù)調(diào)用waitpid,即使沒(méi)有子進(jìn)程退出,它也會(huì)立即返回,不會(huì)像wait那樣永遠(yuǎn)等下去。而WUNTRACED參數(shù),用于跟蹤調(diào)試,極少用到,就不說(shuō)了。查看linux源代碼unistd.h我們會(huì)發(fā)現(xiàn),其實(shí)wait就是經(jīng)過(guò)包裝的waitpid:staticinlinepid_twait(int*wait_stat){returnwaitpid(-1,wait_stat,0);}waitpid的返回值比wait稍微復(fù)雜一些,一共有3種情況:1.當(dāng)正常返回的時(shí)候,waitpid返回收集到的子進(jìn)程的進(jìn)程ID;2.如果設(shè)置了選項(xiàng)WNOHANG,而調(diào)用中waitpid發(fā)現(xiàn)沒(méi)有已退出的子進(jìn)程可收集,則返回0;3.如果調(diào)用中出錯(cuò),則返回-1,這時(shí)errno會(huì)被設(shè)置成相應(yīng)的值以指示錯(cuò)誤所在;當(dāng)pid所指示的子進(jìn)程不存在,或此進(jìn)程存在,但不是調(diào)用進(jìn)程的子進(jìn)程,waitpid就會(huì)出錯(cuò)返回,這時(shí)errno被設(shè)置為ECHILD;intsystem(constchar*string);system(執(zhí)行shell命令)相關(guān)函數(shù)fork,execve,waitpid,popen表頭文件#include<stdlib.h>定義函數(shù)intsystem(constchar*string);函數(shù)說(shuō)明system()會(huì)調(diào)用fork()產(chǎn)生子進(jìn)程,由子進(jìn)程來(lái)調(diào)用/bin/sh-cstring來(lái)執(zhí)行參數(shù)string字符串所代表的命令,此命>令執(zhí)行完后隨即返回原調(diào)用的進(jìn)程。在調(diào)用system()期間SIGCHLD信號(hào)會(huì)被暫時(shí)擱置,SIGINT和SIGQUIT信號(hào)則會(huì)被忽略。返回值=-1:出現(xiàn)錯(cuò)誤=0:調(diào)用成功但是沒(méi)有出現(xiàn)子進(jìn)程>0:成功退出的子進(jìn)程的id如果system()在調(diào)用/bin/sh時(shí)失敗則返回127,其他失敗原因返回-1。若參數(shù)string為空指針(NULL),則返回非零值>。如果system()調(diào)用成功則最后會(huì)返回執(zhí)行shell命令后的返回值,但是此返回值也有可能為system()調(diào)用/bin/sh失敗所返回的127,因此最好能再檢查errno來(lái)確認(rèn)執(zhí)行成功。附加說(shuō)明在編寫具有SUID/SGID權(quán)限的程序時(shí)請(qǐng)勿使用system(),system()會(huì)繼承環(huán)境變量,通過(guò)環(huán)境變量可能會(huì)造成系統(tǒng)安全的問(wèn)題。execve(執(zhí)行文件)在父進(jìn)程中fork一個(gè)子進(jìn)程,在子進(jìn)程中調(diào)用exec函數(shù)啟動(dòng)新的程序。exec函數(shù)一共有六個(gè),其中execve為內(nèi)核級(jí)系統(tǒng)調(diào)用,其他(execl,execle,execlp,execv,execvp)都是調(diào)用execve的庫(kù)函數(shù)。表頭文件:#include<unistd.h>定義函數(shù):intexecve(constchar*filename,char*constargv[],char*constenvp[]);函數(shù)說(shuō)明:execve()用來(lái)執(zhí)行參數(shù)filename字符串所代表的文件路徑,第二個(gè)參數(shù)系利用數(shù)組指針來(lái)傳遞給執(zhí)行文件,最后一個(gè)參數(shù)則為傳遞給執(zhí)行文件的新環(huán)境變量數(shù)組。返回值:如果執(zhí)行成功則函數(shù)不會(huì)返回,執(zhí)行失敗則直接返回-1,失敗原因存于errno中。錯(cuò)誤代碼EACCES1.欲執(zhí)行的文件不具有用戶可執(zhí)行的權(quán)限。2.欲執(zhí)行的文件所屬的文件系統(tǒng)是以noexec方式掛上。3.欲執(zhí)行的文件或script翻譯器非一般文件。EPERM1.進(jìn)程處于被追蹤模式,執(zhí)行者并不具有root權(quán)限,欲執(zhí)行的文件具有SUID或SGID位。2.欲執(zhí)行的文件所屬的文件系統(tǒng)是以nosuid方式掛上,欲執(zhí)行的文件具有SUID或SGID位元,但執(zhí)行者并不具有root權(quán)限。E2BIG參數(shù)數(shù)組過(guò)大ENOEXEC無(wú)法判斷欲執(zhí)行文件的執(zhí)行文件格式,有可能是格式錯(cuò)誤或無(wú)法在此平臺(tái)執(zhí)行。EFAULT參數(shù)filename所指的字符串地址超出可存取空間范圍。ENAMETOOLONG參數(shù)filename所指的字符串太長(zhǎng)。ENOENT參數(shù)filename字符串所指定的文件不存在。ENOMEM核心內(nèi)存不足ENOTDIR參數(shù)filename字符串所包含的目錄路徑并非有效目錄EACCES參數(shù)filename字符串所包含的目錄路徑無(wú)法存取,權(quán)限不足ELOOP過(guò)多的符號(hào)連接ETXTBUSY欲執(zhí)行的文件已被其他進(jìn)程打開(kāi)而且正把數(shù)據(jù)寫入該文件中EIOI/O存取錯(cuò)誤ENFILE已達(dá)到系統(tǒng)所允許的打開(kāi)文件總數(shù)。EMFILE已達(dá)到系統(tǒng)所允許單一進(jìn)程所能打開(kāi)的文件總數(shù)。EINVAL欲執(zhí)行文件的ELF執(zhí)行格式不只一個(gè)PT_INTERP節(jié)區(qū)EISDIRELF翻譯器為一目錄ELIBBADELF翻譯器有問(wèn)題。范例:#include<unistd.h>main(){char*argv[]={“l(fā)s”,”-al”,”/etc/passwd”,(char*)0};char*envp[]={“PATH=/bin”,0}execve(“/bin/ls”,argv,envp);}執(zhí)行:-rw-r--r--1rootroot705Sep313:52/etc/passwdwait(等待子進(jìn)程中斷或結(jié)束)相關(guān)函數(shù)waitpid,fork表頭文件#include<sys/types.h>#include<sys/wait.h>定義函數(shù)pid_twait(int*status);函數(shù)說(shuō)明wait()會(huì)暫時(shí)停止目前進(jìn)程的執(zhí)行,直到有信號(hào)來(lái)到或子進(jìn)程結(jié)束。如果在調(diào)用wait()時(shí)子進(jìn)程已經(jīng)結(jié)束,則wait()會(huì)立即返回子進(jìn)程結(jié)束狀態(tài)值。子進(jìn)程的結(jié)束狀態(tài)值會(huì)由參數(shù)status返回,而子進(jìn)程的進(jìn)程識(shí)別碼也會(huì)一快返回。如果不在意結(jié)束狀態(tài)值,則參數(shù)status可以設(shè)成NULL。子進(jìn)程的結(jié)束狀態(tài)值請(qǐng)參考waitpid()。返回值如果執(zhí)行成功則返回子進(jìn)程識(shí)別碼(PID),如果有錯(cuò)誤發(fā)生則返回-1。失敗原因存于errno中。附加說(shuō)明范例一#include<stdlib.h>#include<unistd.h>#include<sys/types.h>#include<sys/wait.h>intmain(){pid_tpid;intstatus,i;if(fork()==0){printf(“Thisisthechildprocess.pid=%d\n”,getpid());exit(5);}else{sleep(1);printf(“Thisistheparentprocess,waitforchild...\n”;pid=wait(&status);i=WEXITSTATUS(status);printf(“child’spi
溫馨提示
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025-2030年中國(guó)旅游度假區(qū)行業(yè)資本規(guī)劃與股權(quán)融資戰(zhàn)略制定與實(shí)施研究報(bào)告
- 2025-2030年中國(guó)咖啡館行業(yè)并購(gòu)重組擴(kuò)張戰(zhàn)略制定與實(shí)施研究報(bào)告
- 新形勢(shì)下金融押運(yùn)行業(yè)快速做大市場(chǎng)規(guī)模戰(zhàn)略制定與實(shí)施研究報(bào)告
- 2025-2030年中國(guó)商用廚房電器行業(yè)全國(guó)市場(chǎng)開(kāi)拓戰(zhàn)略制定與實(shí)施研究報(bào)告
- 2025-2030年中國(guó)汽車分時(shí)租賃行業(yè)全國(guó)市場(chǎng)開(kāi)拓戰(zhàn)略制定與實(shí)施研究報(bào)告
- 2025-2030年中國(guó)鈷行業(yè)開(kāi)拓第二增長(zhǎng)曲線戰(zhàn)略制定與實(shí)施研究報(bào)告
- 關(guān)于大學(xué)生對(duì)學(xué)校組織愛(ài)心活動(dòng)的關(guān)注及其背后真實(shí)心理的調(diào)查
- 國(guó)有企業(yè)2024年工作情況總結(jié)及2025年工作計(jì)劃
- 2024-2030年中國(guó)金融系列行業(yè)市場(chǎng)全景分析及投資前景展望報(bào)告
- 電力工程招投標(biāo)過(guò)程中的風(fēng)險(xiǎn)分析與管理措施
- 礦用液壓支架的設(shè)計(jì)液壓支架的設(shè)計(jì)
- 最新深基坑驗(yàn)收記錄表-開(kāi)挖條件驗(yàn)收表4-2
- 勤工助學(xué)申請(qǐng)表
- 《茶館》教學(xué)反思
- DB44∕T 635-2009 政府投資應(yīng)用軟件開(kāi)發(fā)項(xiàng)目?jī)r(jià)格評(píng)估及計(jì)算方法
- 安裝工程定額講義
- 復(fù)旦大學(xué)留學(xué)生入學(xué)考試模擬卷
- 【信息技術(shù)應(yīng)用能力提升工程2.0】A3演示文稿設(shè)計(jì)與制作 初中語(yǔ)文《雖有嘉肴》主題說(shuō)明
- 小學(xué)四年級(jí)奧數(shù)教程30講(經(jīng)典講解)
- 爛尾樓工程聯(lián)建檢測(cè)與鑒定
- 汽車技術(shù)服務(wù)與營(yíng)銷畢業(yè)論文備選題目
評(píng)論
0/150
提交評(píng)論