Linux下的進(jìn)程控制解讀
進(jìn)程創(chuàng)建
在Linux環(huán)境下,我們使用系統(tǒng)調(diào)用接口 fork()函數(shù),來(lái)創(chuàng)建進(jìn)程!

參數(shù):無(wú)參;
返回值:
創(chuàng)建失敗,返回負(fù)值;
創(chuàng)建成功,對(duì)于子進(jìn)程返回0,對(duì)于父進(jìn)程返回子進(jìn)程的pid;
fork返回值的認(rèn)識(shí)
可以移步至我的另一篇文章:Linux下的進(jìn)程地址空間----頁(yè)表
fork創(chuàng)建失敗的原因
1、物理內(nèi)存不夠了用了;創(chuàng)建子進(jìn)程也是需要消耗物理內(nèi)存的!
2、父進(jìn)程創(chuàng)建子進(jìn)程的上限到了,OS為了限制用戶父進(jìn)程無(wú)限制的創(chuàng)建子進(jìn)程,通常都會(huì)給父進(jìn)程設(shè)置一個(gè)"進(jìn)程上限";
fork函數(shù)的應(yīng)用場(chǎng)景
1、一個(gè)父進(jìn)程希望復(fù)制自己,使父子進(jìn)程同時(shí)執(zhí)行不同的代碼段。例如:父進(jìn)程等待客服端請(qǐng)求,生成子進(jìn)程來(lái)處理請(qǐng)求;
2、一個(gè)進(jìn)程需要執(zhí)行不同的程序。例如:子進(jìn)程從fork函數(shù)返回后,調(diào)用Add()接口,父進(jìn)程去執(zhí)行Sub()接口;
進(jìn)程終止
進(jìn)程終止的三種方式
1、程序正常運(yùn)行,最后結(jié)果正確;
2、程序正常運(yùn)行,最后結(jié)果錯(cuò)誤;
3、程序異常終止?。ū热纾撼霈F(xiàn)除以0、對(duì)空指針解引用、kill -9 命令殺掉進(jìn)程等等)這本質(zhì)上:就是OS向該進(jìn)程發(fā)送了一種信號(hào)!
進(jìn)程退出碼
進(jìn)程退出碼存在的前提就是程序正常運(yùn)行完畢!在其他情況下,進(jìn)程退出碼沒(méi)有意義!
那么什么是進(jìn)程退出碼?
一個(gè)程序是從main函數(shù)開(kāi)始的吧,那么終止也是終止與main函數(shù)對(duì)吧,main函數(shù)最后是不是有個(gè)return 0;這個(gè)0就是進(jìn)程退出碼;
return 0,表示該進(jìn)程正常運(yùn)行,且運(yùn)行結(jié)果正確;
return 其他數(shù)據(jù),表示該進(jìn)程正常運(yùn)行,但是運(yùn)行結(jié)果錯(cuò)誤,那么到底是為什么錯(cuò)誤呢?作為父進(jìn)程需要知道原因,我們此時(shí)return 的數(shù)字就表示這個(gè)錯(cuò)誤原因,這個(gè)數(shù)字也是進(jìn)程退出碼!
當(dāng)然不止main函數(shù)的返回值是進(jìn)程退出碼,exit()/_exit()函數(shù)的參數(shù)都是進(jìn)程退出碼!
我們可以理解為exit()/-exit()//函數(shù)的參數(shù)等價(jià)于return 數(shù)字;
return 數(shù)字只能在main函數(shù)內(nèi)部進(jìn)行返回,但是如果我們?cè)趍ain函數(shù)以外的地方,遇到了不合理的地方想要提前終止進(jìn)程(比如利用malloc開(kāi)辟空間失敗,我們就可以提前終止進(jìn)程),我們就可以利用exit()/_exit(),來(lái)提前終止掉該進(jìn)程!
exit()/_exit()//的參數(shù)就相當(dāng)于main函數(shù)的返回值!0:表示正常運(yùn)行結(jié)束,結(jié)果運(yùn)行正確;其他數(shù)字表示正常運(yùn)行結(jié)束,結(jié)果運(yùn)行錯(cuò)誤!
那么exit()/與_exit()看起來(lái)長(zhǎng)得很像啊,那么他們有區(qū)別嗎?
當(dāng)然有,我們可以通過(guò)下面一段測(cè)試代碼來(lái)看待結(jié)果:

分析:printf在輸出“Hello World!”的時(shí)候,會(huì)首先將字符串發(fā)送到“緩沖區(qū)”,但是由于字符串末尾沒(méi)有’\n’,printf后面沒(méi)有輸入語(yǔ)句,printf語(yǔ)句后面沒(méi)有fflush強(qiáng)制刷新緩沖區(qū)!我們并不會(huì)立即看到字符串,在休眠2s過(guò)后進(jìn)程調(diào)用exit提前終止掉了,也就是程序結(jié)束了,程序結(jié)束是會(huì)刷新緩沖區(qū),也就是說(shuō)我們會(huì)看到“Hello World!”,那么結(jié)果到底是不是?我們運(yùn)行一下:

結(jié)果的確是這樣!
那么如果我們?cè)賮?lái)利用_exit()函數(shù)來(lái)提前終止程序呢?


我們會(huì)發(fā)現(xiàn)什么也沒(méi)有?。?!
嗯?為什么會(huì)這樣?
首先我們的字符串會(huì)被先發(fā)送到緩沖區(qū),這是沒(méi)有問(wèn)題的?問(wèn)題是我們利用_exit()提前結(jié)束掉進(jìn)程過(guò)后,屏幕上沒(méi)有出現(xiàn)字符串!但是利用exit()提前結(jié)束,確有字符串!
這到底是為什么?
首先我們需要明白,exit()是C語(yǔ)言庫(kù)函數(shù)里面的函數(shù)接口,而_exit()不屬于C語(yǔ)言,_exit()是系統(tǒng)調(diào)用;exit()內(nèi)部也是通過(guò)調(diào)用_exit()系統(tǒng)調(diào)用來(lái)終止進(jìn)程的,只不過(guò)exit()內(nèi)部更加豐富,在結(jié)束進(jìn)程之前,會(huì)做一些工作,比如:執(zhí)行用戶定義的清理
函數(shù)、刷新緩沖區(qū)、關(guān)閉流等;但是_exit()沒(méi)有這么多前戲,就是純粹的終止進(jìn)程!它不會(huì)刷新緩存區(qū),因此我們?cè)谡{(diào)用_exit()結(jié)束進(jìn)程的時(shí)候,沒(méi)有刷新緩沖區(qū),直接就結(jié)束掉進(jìn)程了,我們的字符串也就一直停留在緩沖區(qū),沒(méi)有機(jī)會(huì)輸出到屏幕上!

同時(shí)我們的return 數(shù)字;準(zhǔn)確上來(lái)說(shuō)等價(jià)于exit();因此在平常的使用中我們更推薦使用exit();
為什么需要進(jìn)程退出碼?
子進(jìn)程是被父進(jìn)程創(chuàng)建的,父進(jìn)程創(chuàng)建子進(jìn)程是為了讓子進(jìn)程幫助自己完成某樣任務(wù),那么子進(jìn)程運(yùn)行結(jié)束了,子進(jìn)程到底把這個(gè)任務(wù)完成的怎么樣?是好?還是壞?作為父進(jìn)程是需要知道的!進(jìn)程退出碼就是用于告訴父進(jìn)程它交給子進(jìn)程完成的任
務(wù)完成的怎么樣的信息!
父進(jìn)程再把這個(gè)信息報(bào)告給我們用戶!
但是對(duì)于我們用戶來(lái)說(shuō),進(jìn)程退出碼就是一個(gè)單純的數(shù)字,我們作為人類只看的懂字符串!因此我們需要一樣表來(lái)映射進(jìn)程退出碼的對(duì)應(yīng)信息!在C語(yǔ)言庫(kù)中,給我們提供了一張這樣的映射表,我們可以通過(guò)strerror()函數(shù)來(lái)訪問(wèn)這種表!

參數(shù): 錯(cuò)誤號(hào);
返回值: 錯(cuò)誤號(hào)對(duì)應(yīng)的字符串首地址!
通過(guò)下面一段程序,我們來(lái)輸出一下“錯(cuò)誤表”中對(duì)應(yīng)的錯(cuò)誤信息:

運(yùn)行結(jié)果:

我們可以看到“錯(cuò)誤表”里面總共記錄了134個(gè)錯(cuò)誤信息;當(dāng)然這只是Linux環(huán)境下的,Window環(huán)境下可能會(huì)不一樣!這張“錯(cuò)誤表”雖然是C語(yǔ)言庫(kù)給我們提供的,但是我們沒(méi)必要一定要遵守這張表,我們可以映射自己的“錯(cuò)誤表”;當(dāng)然這些錯(cuò)誤信息最多也就255個(gè);
如何查看進(jìn)程退出碼?
好,現(xiàn)在我知道了什么是進(jìn)程退出碼和為什么要有進(jìn)程退出碼,那么能不能讓我們見(jiàn)一見(jiàn)進(jìn)程退出碼?
當(dāng)然可以:查看進(jìn)程退出碼用命令echo $?//這個(gè)命令是查看最近一次進(jìn)程運(yùn)行結(jié)束的退出碼!
比如現(xiàn)在我們故意將我們的進(jìn)程退出碼設(shè)置"特殊"一點(diǎn),方便我們觀察:


當(dāng)然我們也可以用于產(chǎn)看系統(tǒng)指令的進(jìn)程退出碼,比如:

我們可以用這個(gè)進(jìn)程退出碼去查一下C庫(kù)的“錯(cuò)誤表”:

發(fā)現(xiàn)ls的進(jìn)程退出碼(2)的確實(shí)對(duì)應(yīng)的“No such file or directory”的錯(cuò)誤信息,表示ls命令采用了C庫(kù)的“錯(cuò)誤表”;
當(dāng)然也有一些是命令是不遵循的,比如:

查看C庫(kù)“錯(cuò)誤表”:

我們發(fā)現(xiàn)是匹配不上的,說(shuō)明kill命令并沒(méi)有采用C庫(kù)里面的錯(cuò)誤信息,而是采用了自己設(shè)計(jì)的!
進(jìn)程等待
為什么要進(jìn)行進(jìn)程等待?
進(jìn)程等待是誰(shuí)等?等誰(shuí)?
答案是:父進(jìn)程等,等子進(jìn)程!
明白了這一點(diǎn),我們?cè)賮?lái)談為什么要進(jìn)行進(jìn)程等待?
1、子進(jìn)程不可能直接就推出了,父進(jìn)程需要獲取子進(jìn)程的退出碼,來(lái)獲知交給子進(jìn)程的任務(wù)完成的怎么樣;
2、因此,子進(jìn)程在終止過(guò)后會(huì)進(jìn)入僵尸狀態(tài),以此來(lái)讓父進(jìn)程獲取子進(jìn)程的退出碼;但是處于僵尸狀態(tài)有一個(gè)弊端:僵尸不死不滅,就算是用kill -9命令也無(wú)法將其殺死!因?yàn)樗旧砭鸵呀?jīng)終止了,沒(méi)辦法殺死一個(gè)已經(jīng)死去的進(jìn)程!但是,該進(jìn)程占據(jù)的空間還沒(méi)有釋放,如果沒(méi)有人來(lái)釋放掉該空間的話,就會(huì)造成內(nèi)存泄漏!為此父進(jìn)程在獲取到子進(jìn)程的退出碼過(guò)后,會(huì)順便將子進(jìn)程的空間也一并釋放了;
什么是進(jìn)程等待?
知道了為什么需要進(jìn)行進(jìn)程等待,我們也就明白了進(jìn)程等待的本質(zhì):
進(jìn)程等待的本質(zhì):獲取子進(jìn)程退出碼以此來(lái)知曉父進(jìn)程交代給子進(jìn)程的任務(wù)子進(jìn)程完成的怎么樣,并順便釋放掉子進(jìn)程的空間!
怎么進(jìn)行進(jìn)程等待?
我們可以使用系統(tǒng)調(diào)用wait()/waitpid();來(lái)實(shí)現(xiàn)!
在具體使用之前,我們需要先了解一下這兩個(gè)系統(tǒng)調(diào)用:
pid_t wait(int*status);
Linux下包含頭文件:sys/types.h和sys/wait.h
參數(shù): 輸出型參數(shù)用于獲取進(jìn)程退出碼和信號(hào)(如果程序正常運(yùn)行結(jié)束的話,信號(hào)是0);當(dāng)然如果我們不關(guān)心進(jìn)程的退出碼和信號(hào)的話,我們可以將其設(shè)置為NULL;
返回值: 等待成功:返回等待進(jìn)程的pid;等待失敗(比如父進(jìn)程沒(méi)有子進(jìn)程),返回-1;
下面我們就先來(lái)實(shí)際用一下wait()系統(tǒng)調(diào)用:

運(yùn)行結(jié)果:

實(shí)際上我們不需要使用sleep()函數(shù),當(dāng)父進(jìn)程調(diào)用wait函數(shù)時(shí),父進(jìn)程也會(huì)自動(dòng)的等待子進(jìn)程運(yùn)行完畢!相當(dāng)于在子進(jìn)程運(yùn)行的這段期間,父進(jìn)程相當(dāng)于卡在了wait函數(shù)內(nèi)部!這叫做阻塞等待!父進(jìn)程會(huì)被OS放入一個(gè)等待隊(duì)列中進(jìn)行等待子進(jìn)程的運(yùn)行結(jié)束!

靜態(tài)圖片不好演示父進(jìn)程等待的這個(gè)過(guò)程,讀者可以自行驗(yàn)證!

注意:wait是處理當(dāng)前進(jìn)程中最先進(jìn)入僵尸狀態(tài)的子進(jìn)程;
上面介紹了wait()系統(tǒng)調(diào)用,接著我們來(lái)介紹一下waitpid()系統(tǒng)調(diào)用,waitpid與wait功能相似,wait是處理最先處于僵尸狀態(tài)的子進(jìn)程,waitpid是處理指定pid的子進(jìn)程;
pid_t waitpid(pid_t pid,int*status,int options);
參數(shù): pid:指定等待的子進(jìn)程;pid=-1時(shí)則處理最先處于僵尸狀態(tài)的子進(jìn)程;
- status:輸出型參數(shù);與wait的status功能一樣;
- option:決定父進(jìn)程在等待的過(guò)程中是否可與去做其他事情;
- 0:不可以;WNOHANG:可以!
返回值::
option=0:
- 等待成功,返回子進(jìn)程pid;
- 等待失敗,返回-1;
option=WNOHANG:
- 等待成功,返回子進(jìn)程pid;
- 子進(jìn)程還沒(méi)運(yùn)行結(jié)束,返回0;
- 等待失?。ㄗ舆M(jìn)程不存在),返回-1,
具體用法如下:


現(xiàn)在如果我們關(guān)心子進(jìn)程的退出信息呢?
那么我們的status參數(shù)就不能在傳空指針了,我們需要傳遞一個(gè)int類型的指針過(guò)去,這個(gè)int類型的指針必須指向一塊有效的空間!相當(dāng)于:

也就是說(shuō)status必須指向一個(gè)int類型的空間,這個(gè)int類型的空間用來(lái)存儲(chǔ)子進(jìn)程的退出碼+信號(hào)信息!
是的!你沒(méi)聽(tīng)錯(cuò)!這個(gè)int空間會(huì)被用來(lái)存儲(chǔ)兩種信息!
- int 類型有4個(gè)字節(jié)對(duì)吧!而我們的退出碼也就0~255種情況一個(gè)字節(jié)就能存儲(chǔ)起來(lái),我們的信號(hào)信息也就幾十個(gè)情況,也能用一個(gè)字節(jié)存儲(chǔ)起來(lái)!
- status不能簡(jiǎn)單的當(dāng)作整形來(lái)看待,可以當(dāng)作位圖來(lái)看待,具體細(xì)節(jié)如下圖(只研究status低16比特位):

那么我們?nèi)绾文贸龅竭M(jìn)程退出碼和終止信號(hào)?
我們可以利用(status指向的整形>>8)&0xFF的方式來(lái)拿出進(jìn)程退出碼!(status&0x7F)的方式來(lái)拿出終止信號(hào);
下面我們來(lái)具體演示一下:

我們?cè)O(shè)置的子進(jìn)程的退出碼是107,如果子進(jìn)程是正常運(yùn)行結(jié)束的話,那么終止信號(hào)也就是0;
那么結(jié)果是不是呢?

答案確實(shí)是這樣?
當(dāng)然如果程序是異常終止的話,那么信號(hào)也是其它數(shù)字,這時(shí)候在看進(jìn)程退出碼已經(jīng)沒(méi)有任何意義了!
(我們這里故意制造一個(gè),子進(jìn)程除以0的語(yǔ)句,來(lái)使子進(jìn)程異常終止:)


那么父進(jìn)程是如何獲取到子進(jìn)程的進(jìn)程退出碼的和終止信號(hào)的?
在子進(jìn)程的pcb結(jié)構(gòu)體中,有兩個(gè)變量:
int exit_code;//用于記錄當(dāng)前進(jìn)程的退出碼; int exit_signal//用于記錄當(dāng)前進(jìn)程的終止信號(hào);
當(dāng)子進(jìn)程進(jìn)入僵尸狀態(tài),也就是子進(jìn)程被終止掉了!OS會(huì)根據(jù)子進(jìn)程終止時(shí)的退出碼和終止信號(hào)來(lái)填充exit_code和exit_signal;當(dāng)父進(jìn)程使用wait()/waitpid()系統(tǒng)調(diào)用的時(shí)候,OS就會(huì)將子進(jìn)程pcb里面的
exit_code和exit_signal存儲(chǔ)于status指針指向的int空間中,而status所指向的空間是屬于父進(jìn)程的,父進(jìn)程也就自然而然的拿到了子進(jìn)程的退出碼和終止信號(hào)!
父進(jìn)程在使用wait()/waitpid()的期間在做什么?
通過(guò)上面使用wait()的時(shí)候我們發(fā)現(xiàn)。即使不用sleep()讓父進(jìn)程,而是直接調(diào)用wait()接口,父進(jìn)程依舊會(huì)等待子進(jìn)程的運(yùn)行結(jié)束,父進(jìn)程并沒(méi)有直接越過(guò)wait()接口而去執(zhí)行后面的指令!在子進(jìn)程運(yùn)行期間,父進(jìn)程就像是卡在了wait()函數(shù)內(nèi)部,我們
把這種情況叫做阻塞等待!在子進(jìn)程運(yùn)行期間,OS會(huì)把父進(jìn)程放入一個(gè)阻塞隊(duì)列中進(jìn)行等待!在此期間父進(jìn)程什么也做不了!在進(jìn)程的pcb結(jié)構(gòu)體中有一個(gè)指針指向該pcb的父進(jìn)程pcb:

當(dāng)我們的子進(jìn)程運(yùn)行結(jié)束過(guò)后,OS會(huì)根據(jù)子進(jìn)程parent指向找到該子進(jìn)程的父進(jìn)程,然后將其父進(jìn)程從阻塞隊(duì)列中喚醒!然后在讓父進(jìn)程來(lái)獲取子進(jìn)程的進(jìn)程退出碼和終止信號(hào)!最后順便完成子進(jìn)程的空間釋放!
看到這里,或許我們會(huì)疑惑,父進(jìn)程在使用wait()接口等待的時(shí)候就真什么也不做,一直等著子進(jìn)程,是不是效率有點(diǎn)低了?能不能讓父進(jìn)程在等待的這段時(shí)間去做一點(diǎn)別的事情?或者說(shuō)讓父進(jìn)程每隔一個(gè)時(shí)間段去看一看子進(jìn)程運(yùn)行結(jié)束沒(méi)有,總之就是不要讓父進(jìn)程一直等待著子進(jìn)程?
當(dāng)然可以!當(dāng)然使用wait()接口肯定不行,因?yàn)閰?shù)太少了!只要父進(jìn)程已使用wait()接口等待,父進(jìn)程就會(huì)卡在wait()函數(shù)內(nèi)部,直到子進(jìn)程運(yùn)行結(jié)束!但是我們可以使用waitpid()接口哇!
還記得waitpid()有個(gè)參數(shù)option嗎?當(dāng)option為0的時(shí)候,父進(jìn)程在等待子進(jìn)程期間就會(huì)進(jìn)入阻塞隊(duì)列中進(jìn)行等待,也就是說(shuō)父進(jìn)程會(huì)卡在waitpid()內(nèi)部,知道子進(jìn)程運(yùn)行結(jié)束!當(dāng)option=WNOHANG的時(shí)候父進(jìn)程不會(huì)進(jìn)入阻塞隊(duì)列中,而是檢測(cè)一下子進(jìn)程的狀態(tài),當(dāng)子進(jìn)程運(yùn)行結(jié)束時(shí)waitpid()會(huì)返回子進(jìn)程的pid;當(dāng)子進(jìn)程正在運(yùn)行時(shí)waitpid(),返回0;當(dāng)?shù)却r(shí),waitpid()返回-1;至此當(dāng)父進(jìn)程使用waitpid()并且option參數(shù)設(shè)計(jì)成WNOHANG時(shí)父進(jìn)程就不會(huì)卡在waitpid()接口內(nèi)部,不管是那種情況這個(gè)“模式”下的waitpid()都是會(huì)返回一個(gè)值,我們就可以根據(jù)這個(gè)返回值來(lái)設(shè)計(jì)父進(jìn)程下一步該做什么?如果返回值是0,說(shuō)明子進(jìn)程還在運(yùn)行,我們可以讓父進(jìn)程去執(zhí)行一些其他代碼,然后循環(huán)回來(lái)繼續(xù)接收一下waitpid()的返回值!像這種情況叫做阻塞輪詢!
下面我們通過(guò)具體的代碼來(lái)表現(xiàn)一下阻塞輪詢:

運(yùn)行結(jié)果:

從運(yùn)行結(jié)果我們可以看出,當(dāng)我們把option參數(shù)設(shè)成WNOHANG過(guò)后,父進(jìn)程沒(méi)有卡在waitpid()內(nèi)部,而是和子進(jìn)程一起在運(yùn)行!
現(xiàn)在我們?cè)賮?lái)對(duì)比一下,阻塞等待(也就是option參數(shù)設(shè)計(jì)成0即可):


我們可以看到在使用阻塞等待的時(shí)候,父進(jìn)程沒(méi)有去做其他事情(比如打印乘法口訣表)而是一直等待者子進(jìn)程的運(yùn)行結(jié)束,當(dāng)子進(jìn)程運(yùn)行結(jié)束后,父進(jìn)程通過(guò)waitpid()接收到子進(jìn)程pid,pid>0不滿足while進(jìn)入的條件!于是直接去執(zhí)行了printf子進(jìn)程運(yùn)行結(jié)束的語(yǔ)句!
這就是阻塞等待與阻塞輪詢的區(qū)別!
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Linux bash:./xxx:無(wú)法執(zhí)行二進(jìn)制文件報(bào)錯(cuò)
這篇文章主要介紹了Linux bash:./xxx:無(wú)法執(zhí)行二進(jìn)制文件報(bào)錯(cuò),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03
ubuntu中python調(diào)用C/C++方法之動(dòng)態(tài)鏈接庫(kù)詳解
這篇文章主要給大家介紹了關(guān)于如何在ubuntu中python調(diào)用C/C++方法之動(dòng)態(tài)鏈接庫(kù)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起看看吧2018-11-11
在Linux系統(tǒng)下如何編譯并執(zhí)行C++程序
這篇文章主要介紹了在Linux系統(tǒng)下如何編譯并執(zhí)行C++程序問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01
解決Linux系統(tǒng)yum安裝報(bào)錯(cuò)Cannot find a valid base
本文介紹了如何在Linux系統(tǒng)中設(shè)置本地yum源,包括修改yum配置文件、禁用默認(rèn)網(wǎng)絡(luò)源、創(chuàng)建掛載點(diǎn)以及掛載鏡像文件等步驟,操作詳細(xì),適合需要離線安裝軟件或更新系統(tǒng)的用戶參考2024-09-09
Linux利用lsof/extundelete工具恢復(fù)誤刪除的文件或目錄
這篇文章主要給大家介紹了關(guān)于Linux利用lsof/extundelete工具恢復(fù)誤刪除的文件或目錄的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08

