前言
前面我們講了C語言的基礎知識,也了解了一些數(shù)據結構,并且講了有關C++的一些知識,也學習了一些Linux的基本操作,也了解并學習了有關Linux開發(fā)工具vim 、gcc/g++ 使用、yum工具以及git 命令行提交代碼也相信大家都掌握的不錯,上一篇文章我們了解了關于進程的地址空間,今天博主帶大家了解一下 —— 進程的控制——創(chuàng)建、終止、等待、程序替換, 下面話不多說坐穩(wěn)扶好咱們要開車了?。?!??
一、進程創(chuàng)建
1. fork函數(shù)初識
?基本概念
fork
函數(shù)是操作系統(tǒng)中的一個系統(tǒng)調用,用于創(chuàng)建一個新的進程,該進程是調用fork函數(shù)的進程的一個副本。新創(chuàng)建的進程稱為子進程,原始進程稱為父進程。
fork
函數(shù)的函數(shù)原型:
#include <unistd.h>
pid_t fork(void);
?fork函數(shù)返回值
-
父進程中的返回值:
-
如果
fork
函數(shù)返回一個大于0的值,表示當前執(zhí)行的是父進程。這個返回值是子進程的PID(進程ID),可以用來操作子進程。 -
如果
fork
函數(shù)返回-1,表示創(chuàng)建子進程失敗,通常是因為系統(tǒng)資源不足或權限不夠等原因,此時應該處理錯誤情況。
-
如果
-
子進程中的返回值:
-
如果
fork
函數(shù)返回0,表示當前執(zhí)行的是子進程??梢愿鶕枰谧舆M程中執(zhí)行相應的任務邏輯。
-
如果
根據fork函數(shù)的返回值,可以在程序中使用條件語句來區(qū)分父進程和子進程的不同邏輯,從而實現(xiàn)不同的處理方式。例如,可以在父進程中等待子進程的完成,或者在子進程中執(zhí)行某種特定的任務。
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main() {
pid_t pid = fork();
if (pid > 0) {
// 父進程邏輯
printf("This is the parent process. Child's PID: %d\n", pid);
} else if (pid == 0) {
// 子進程邏輯
printf("This is the child process. Parent's PID: %d\n", getppid());
} else {
// fork失敗
fprintf(stderr, "Failed to create child process.\n");
return 1;
}
// 父子進程共享的代碼
printf("This message is printed by both parent and child processes.\n");
return 0;
}
需要注意的是,fork
函數(shù)的使用可能會導致代碼的分支,需要小心處理父子進程之間共享的資源以及避免產生競爭條件,以確保程序的正確性和可靠性。
2. fork函數(shù)的寫時拷貝
fork
函數(shù)的寫時拷貝(Copy-on-Write,COW)是一種優(yōu)化策略,用于在創(chuàng)建子進程時避免立即復制父進程的整個地址空間,這種機制可以提高性能和減少內存消耗。
在傳統(tǒng)的fork操作中,父進程會創(chuàng)建一個子進程,并且子進程會復制父進程的所有資源,包括內存空間、文件描述符等。這樣的完全復制操作非常消耗時間和內存。而使用寫時拷貝機制,只有在需要修改共享的內存頁時才會進行復制操作,從而節(jié)省了系統(tǒng)資源。
具體來說,當調用fork函數(shù)創(chuàng)建子進程時,操作系統(tǒng)會執(zhí)行以下步驟:
- 父進程會創(chuàng)建一個與自己擁有相同地址空間的子進程。
- 子進程繼承了父進程的頁表,這意味著它與父進程共享相同的虛擬內存地址空間。
- 在初始階段,父進程和子進程共享所有的物理頁面,這些頁面被標記為“只讀”。
- 當父進程或子進程嘗試修改共享的內存頁時,操作系統(tǒng)會將相應的頁面復制到一個新的物理頁面,并將其標記為“可寫”。
- 父進程和子進程現(xiàn)在各自擁有一個獨立的物理頁面,它們不再共享相同的數(shù)據。
通過寫時拷貝技術,父進程和子進程共享大部分內存頁,只在需要修改共享內存時才進行復制操作。這樣可以節(jié)省時間和內存,并提高系統(tǒng)性能。例如,在fork之后,如果子進程立即執(zhí)行exec函數(shù)加載了一個新的程序,那么就不需要進行任何復制操作,這是因為子進程并不需要修改父進程的內存數(shù)據。
需要注意的是,寫時拷貝只是在邏輯上實現(xiàn)了共享,而不是物理上的共享。父進程和子進程仍然擁有各自獨立的虛擬地址空間,它們之間的共享是通過允許讀取相同的物理內存來實現(xiàn)的,只有在修改時才會發(fā)生內存復制。
總結起來,fork函數(shù)的寫時拷貝機制使得父進程和子進程在初始階段共享相同的內存空間,只有在需要修改共享內存時才進行復制操作,從而提高了性能和降低了資源消耗。
二、進程終止
1. 進程退出場景
-
代碼運行完畢,結果正確:當我們運行一個程序時,通常會期望它在合理的時間內完成指定的任務,并返回正確的結果。如果程序能夠正常執(zhí)行并得到正確的輸出,那么我們就稱之為結果正確。
-
代碼運行完畢,結果不正確:然而,在某些情況下,程序可能會返回錯誤的輸出,這時我們就說結果不正確。這可能是由于程序中的邏輯錯誤、算法錯誤、數(shù)據不一致或格式錯誤等原因導致的。
-
代碼異常終止:另外一種情況是當程序因為錯誤或異常而非正常退出時,我們稱之為代碼異常終止。在這種情況下,程序可能會拋出異常、崩潰或者停止響應。
2. 進程常見退出方法
-
正常終止(可以通過 echo $? 查看進程退出碼)
- 調用退出函數(shù):在許多編程語言中,都提供了用于結束進程的退出函數(shù),如C/C++的
exit()
函數(shù)和Java的System.exit()
方法。這些函數(shù)可以接受一個整數(shù)作為參數(shù),表示進程的退出狀態(tài)碼,通常使用0表示正常終止。 - 返回主函數(shù):在C/C++中,從主函數(shù)中返回0也表示進程正常終止。
- 調用退出函數(shù):在許多編程語言中,都提供了用于結束進程的退出函數(shù),如C/C++的
int main() {
// 執(zhí)行完所有任務后,通過返回0表示正常終止進程
return 0;
}
- 異常退出:
ctrl + c
,信號終止
3. exit函數(shù)
exit
函數(shù)是一個庫函數(shù),它用于正常終止程序并返回到操作系統(tǒng)。通過調用 exit
函數(shù),進程會經歷一系列清理操作,例如關閉打開的文件、釋放動態(tài)分配的內存等,然后將控制權交還給操作系統(tǒng)。這個過程被稱為進程的正常退出。
?exit
函數(shù)的原型:
#include <stdlib.h>
void exit(int status);
其中,status
參數(shù)表示進程的退出狀態(tài)值。它可以是整數(shù)類型,用來傳遞進程的運行結果或者其他信息。通常情況下,使用 0 表示程序的正常退出,非零值表示程序異常退出或者出錯的特定狀態(tài)。
?當調用 exit
函數(shù)時,以下操作將在進程退出之前執(zhí)行:
- 調用注冊的終止處理程序(通過
atexit
函數(shù)注冊的函數(shù))。 - 關閉標準流(stdin、stdout、stderr)和其他打開的文件。
- 刷新緩沖區(qū),確保輸出正確地寫入文件。
- 通知操作系統(tǒng)進程的退出狀態(tài)碼。
調用 exit
函數(shù)后,程序將不會返回到 exit
調用之后的代碼位置,而是直接返回到操作系統(tǒng)。因此,在調用 exit
函數(shù)后的代碼將不會被執(zhí)行。例如:
#include <stdio.h>
#include <stdlib.h>
int main() {
printf("Before exit\n");
exit(0); // 正常終止進程,退出狀態(tài)碼為0
printf("After exit\n"); // 這行代碼不會執(zhí)行
return 0;
}
?? 注意:使用 exit
函數(shù)時應確保在終止前完成必要的清理工作,以免資源泄漏或未定義行為。此外,可以通過在命令行或者父進程中獲取退出狀態(tài)碼來獲取程序的運行結果或其他信息。
4. _exit函數(shù)
_exit
函數(shù)是一個系統(tǒng)調用,它可以用來立即終止進程的執(zhí)行。與 exit
函數(shù)不同的是, _exit
函數(shù)不會調用任何注冊的終止處理程序,也不會沖洗輸出緩沖區(qū),而是通過直接向內核發(fā)送退出狀態(tài)碼來終止進程。因此,使用 _exit
函數(shù)可以避免在進程終止時執(zhí)行一些不必要的或者危險的操作,如清理緩存、關閉文件等。
?_exit
函數(shù)的原型:
#include <unistd.h>
void _exit(int status);
其中,status
參數(shù)表示進程的退出狀態(tài)值。它與在 exit
函數(shù)中的參數(shù)含義相同。
與 exit
函數(shù)一樣,由 _exit
函數(shù)終止的進程將永遠不會返回到其調用進程的代碼路徑處。進程資源(包括打開的文件、未釋放的內存等)都將被釋放,并通知父進程該進程已經結束。
?? 注意:由于 _exit
函數(shù)是一個系統(tǒng)調用,因此它并沒有對庫函數(shù)進行善后工作,如果你在 _exit
函數(shù)之前使用了庫(如 iostream),則可能會導致內存泄露或者其他未定義的行為。為了避免這種情況,應該在使用 _exit
函數(shù)前顯式地調用 std::flush
函數(shù)將緩沖區(qū)清空,并且進行必要的資源釋放工作。
5. exit函數(shù)與_exit函數(shù)的區(qū)別
-
庫函數(shù)與系統(tǒng)調用:
exit
是一個庫函數(shù),而_exit
是一個系統(tǒng)調用。exit
函數(shù)通過調用_exit
系統(tǒng)調用來終止進程。 -
清理操作的執(zhí)行:
exit
函數(shù)在終止進程之前執(zhí)行一系列清理操作,例如關閉文件、刷新緩沖區(qū)等。它還會調用注冊的終止處理程序(通過atexit
函數(shù)注冊的函數(shù))進行額外的清理工作。相比之下,_exit
函數(shù)不會執(zhí)行這些清理操作,直接終止進程。 -
緩沖區(qū)刷新:
exit
函數(shù)會自動刷新輸出緩沖區(qū),確保所有的輸出都被寫入文件。而_exit
函數(shù)不會主動刷新緩沖區(qū),可能導致部分輸出被丟失。 -
返回控制權:
exit
函數(shù)返回到調用exit
的代碼位置,因此可以在程序中根據退出狀態(tài)碼進行特定操作。相反,_exit
直接將控制權返回給操作系統(tǒng),不會返回到調用_exit
的代碼位置。 -
資源釋放:由于
exit
函數(shù)會執(zhí)行清理操作,可以確保打開的文件被正常關閉、動態(tài)分配的內存被釋放等。而_exit
函數(shù)不會執(zhí)行這些操作,可能導致資源泄漏。
?exit
函數(shù)是一個高級的、安全的方式來終止程序。它會執(zhí)行一系列清理工作并確保輸出被正確處理。相比之下,_exit
函數(shù)適用于需要立即終止進程且不進行任何額外處理的情況,如遇到致命錯誤或者需要在子進程中終止時使用。
6. return退出
return
是一種更常見的退出進程方法。執(zhí)行return n;
等同于執(zhí)行exit(n)
,因為調用main
的運行時函數(shù)會將main
的返回值當做 exit
的參數(shù)。與 exit
和 _exit
函數(shù)不同,return
語句只能在函數(shù)內部使用,并且它是一種正常的控制流程操作。
下面是 return
語句的一些關鍵點:
-
函數(shù)中止:
return
語句的執(zhí)行將導致函數(shù)立即結束并返回到函數(shù)的調用者。在函數(shù)執(zhí)行return
后,沒有其他代碼會被執(zhí)行。 -
返回值:
return
語句可以選擇性地返回一個值給調用者。例如,在有返回類型的函數(shù)中,如int
類型,可以使用return
返回一個整數(shù)值。 -
返回類型檢查: 在函數(shù)定義時,需要聲明函數(shù)的返回類型。如果函數(shù)聲明為
void
類型,則表示沒有任何返回值,此時可以省略return
語句或使用return;
來提前結束函數(shù)。 -
多個返回點: 函數(shù)中可以存在多個
return
語句,表示在不同的條件下提前返回。在這種情況下,只有一個return
語句會被執(zhí)行,其他的return
語句都將被忽略。
例如:
#include <stdio.h>
int sum(int a, int b) {
int result = a + b;
return result; // 返回計算結果給調用者
}
void printMessage() {
printf("Hello, World!\n");
return; // 結束函數(shù),沒有返回值
}
int main() {
printf("Before return\n");
return 0; // 終止 main 函數(shù)并退出程序
printf("After return\n"); // 這行代碼不會執(zhí)行
}
??注意:return
語句只能在函數(shù)內部使用,不能用于終止整個程序的執(zhí)行。要終止整個程序,可以使用 exit
或 _exit
函數(shù)。而 return
語句只影響當前函數(shù)的執(zhí)行流程。
三、進程等待
1. 進程等待的概念
進程等待是指一個進程暫停執(zhí)行,直到某個條件滿足或者某個事件發(fā)生后再繼續(xù)執(zhí)行的操作。在操作系統(tǒng)中,進程等待是一種同步機制,用于實現(xiàn)多個進程之間的協(xié)調和互動。
下面是一些常見的情況,需要使用進程等待:
-
資源共享:多個進程可能需要同時訪問某些共享資源,如數(shù)據庫、文件、網絡連接等。為了避免并發(fā)訪問導致資源沖突和數(shù)據不一致,需要通過進程等待來協(xié)調各個進程對資源的使用。
-
任務依賴:有些任務的執(zhí)行可能依賴于其他任務的完成。如果一個進程要執(zhí)行的任務需要使用其他進程尚未完成的結果,就需要使用進程等待來確保所需的數(shù)據已經準備好了。
-
同步操作:在多線程或者多進程編程中,有時候需要保證某些操作的順序性和一致性。例如,在生產者-消費者模型中,消費者進程必須等待生產者進程將數(shù)據放入共享緩沖區(qū)后才能進行消費。
-
并發(fā)控制:有時候需要限制同時執(zhí)行某個代碼塊的進程數(shù)量。例如,資源受限的情況下,只允許有限數(shù)量的進程同時執(zhí)行某個操作,其他進程需要等待。
進程等待的主要目的是確保多個進程之間的協(xié)調和同步,以避免資源競爭、數(shù)據不一致和并發(fā)沖突等問題。通過使用進程等待,可以實現(xiàn)進程之間的合作和資源共享,從而提高系統(tǒng)的可靠性和效率。
2. 進程等待的方法
?wait 方法
wait
方法:wait
方法是在父進程中調用的,用于等待任一子進程退出或終止。它的語法為:
pid_t wait(int *status);
-
status
指向一個整型變量,用于獲取子進程的退出狀態(tài)信息。 -
wait
方法會將調用進程掛起,直到任一子進程退出或終止。如果有多個子進程同時退出,它會返回任一子進程的進程ID。 - 當子進程結束時,父進程會繼續(xù)執(zhí)行,并且通過
status
參數(shù)獲取子進程的退出狀態(tài)。
實戰(zhàn)演示:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main() {
pid_t pid;
int status;
pid = fork();
if (pid < 0) {
fprintf(stderr, "Fork failed.\n");
exit(1);
} else if (pid == 0) {
// 子進程執(zhí)行的代碼
printf("This is the child process.\n");
exit(123); // 子進程以退出狀態(tài)123結束
} else {
// 父進程執(zhí)行的代碼
printf("This is the parent process.\n");
wait(&status);
if (WIFEXITED(status)) {
printf("Child process exited with status: %d\n", WEXITSTATUS(status));
}
}
return 0;
}
在上面的示例中,父進程通過fork()
創(chuàng)建了一個子進程。子進程輸出一條消息后調用exit(123)
退出,并傳遞了退出狀態(tài)值為123給父進程。父進程使用wait()
等待子進程的退出,并通過WIFEXITED
和WEXITSTATUS
宏判斷子進程是否正常退出,并獲取其退出狀態(tài)值。
?waitpid方法
waitpid()
函數(shù)是一個用于等待指定子進程狀態(tài)改變的系統(tǒng)調用。它具有比wait()
更為靈活的功能,可以指定等待的子進程、等待選項以及獲取子進程的退出狀態(tài)信息。
它的語法為:
pid_t waitpid(pid_t pid, int *status, int options);
-
pid
:表示要等待的子進程的PID。- pid > 0:等待具有指定PID的子進程。
- pid == 0:等待與調用進程在同一進程組中的所有子進程。
- pid < -1:等待進程組ID等于pid絕對值的任一子進程。
- pid == -1:等待任一子進程,相當于wait()函數(shù)的功能。
-
status
:一個整型指針,用于獲取子進程的退出狀態(tài)信息。(如果不關心子進程的退出狀態(tài),可以將該參數(shù)設置為NULL
)。 -
options
:參數(shù)用于指定等待選項,可以使用多個選項,通過按位或(|)進行組合。常見的選項有:- WNOHANG:非阻塞模式,即不掛起父進程,如果沒有子進程狀態(tài)發(fā)生改變,則立即返回,返回值為0。
- WUNTRACED:包括已經停止但未報告的子進程在內的所有子進程都會被等待。
- WCONTINUED:等待未報告的已停止子進程被繼續(xù)(通常與WUNTRACED一起使用)。
返回值:
- 如果成功等到指定的子進程狀態(tài)改變,返回該子進程的
PID
(即pid參數(shù)指定的值)。 - 如果調用進程沒有子進程或出現(xiàn)錯誤,返回
-1
,并設置errno
來指示具體的錯誤原因。
??注意事項:
- 當調用
waitpid()
函數(shù)時,父進程會掛起(阻塞),直到指定的子進程狀態(tài)發(fā)生改變。 -
waitpid()
函數(shù)提供了比wait()
更靈活的方式來等待子進程狀態(tài)改變,并且可以通過指定pid
、options
參數(shù)來滿足不同的等待需求。 - 如果指定的子進程已經退出,則
waitpid()
立即返回子進程的PID
;如果指定的子進程尚未退出,則根據指定的選項來確定是否掛起等待。 - 使用
waitpid()
函數(shù)時,父進程可以同時等待多個子進程的狀態(tài)改變。 -
waitpid()
函數(shù)可以用于實現(xiàn)非阻塞的等待子進程狀態(tài)改變的操作,即通過設置WNOHANG
選項,在沒有可等待的子進程時立即返回。
示例代碼:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main() {
pid_t pid;
int status;
pid = fork();
if (pid < 0) {
fprintf(stderr, "Fork failed.\n");
exit(1);
} else if (pid == 0) {
// 子進程執(zhí)行的代碼
printf("This is the child process.\n");
exit(123); // 子進程以退出狀態(tài)123結束
} else {
// 父進程執(zhí)行的代碼
printf("This is the parent process.\n");
while (waitpid(pid, &status, WNOHANG) == 0) {
sleep(1);
printf("Waiting for child process...\n");
}
if (WIFEXITED(status)) {
printf("Child process exited with status: %d\n", WEXITSTATUS(status));
}
}
return 0;
}
在上面的示例中,父進程通過fork()
創(chuàng)建了一個子進程。子進程輸出一條消息后調用exit(123)
退出,并傳遞了退出狀態(tài)值為123給父進程。父進程使用waitpid()
和WNOHANG
選項進行非阻塞地等待子進程的退出,并通過WIFEXITED
和WEXITSTATUS
宏判斷子進程是否正常退出,并獲取其退出狀態(tài)值。
這兩個方法都可以實現(xiàn)父進程對子進程的等待操作,并獲取子進程的狀態(tài)信息。waitpid
方法相比wait
方法更加靈活,可以選擇具體的子進程進行等待,在一些場景下更加有用。
3. 獲取子進程的status
1. 獲取原理
-
wait
和waitpid
,都有一個status
參數(shù),該參數(shù)是一個輸出型參數(shù),由操作系統(tǒng)填充。 - 如果傳遞
NULL
,表示不關心子進程的退出狀態(tài)信息。 - 否則,操作系統(tǒng)會根據該參數(shù),將子進程的退出信息反饋給父進程。
-
status
不能簡單的當作整形來看待,可以當作位圖來看待,具體細節(jié)如下圖(只研究status
低16比特位)
2. WIFEXITED宏 和 WEXITSTATUS宏
WIFEXITED
和WEXITSTATUS
是用于解析子進程退出狀態(tài)信息的宏定義。下面是對這兩個宏的詳細介紹:
-
WIFEXITED
宏:
int WIFEXITED(int status);
WIFEXITED
宏用于判斷子進程是否正常退出(非被信號終止),即子進程是否調用了exit
或返回了main
函數(shù)。
-
參數(shù)
status
:子進程的退出狀態(tài)信息,通常是通過wait()
或waitpid()
函數(shù)獲取的。 -
返回值:若子進程正常退出,則返回非零值(
true
),否則返回0(false
)。
- WEXITSTATUS宏:
int WEXITSTATUS(int status);
WEXITSTATUS
宏用于獲取子進程的退出狀態(tài)值(0-255
)。只有在WIFEXITED
宏為true
時才有效。
-
參數(shù)
status
:子進程的退出狀態(tài)信息,通常是通過wait()
或waitpid()
函數(shù)獲取的。 -
返回值:子進程的退出狀態(tài)值。
四、進程程序替換
1. 概念
?進程程序替換(Process Program Replacement)是指在一個正在運行的進程中將當前執(zhí)行的程序替換為新的程序的操作。也可以稱之為進程映像替換(Process Image Replacement)。通過進程程序替換,可以使一個進程在執(zhí)行過程中切換到另一個不同的程序,并繼續(xù)執(zhí)行。使用進程程序替換時,當前進程的內存空間會被新的程序覆蓋,包括代碼、數(shù)據和堆棧等信息。新程序的代碼取代原先進程的代碼,新程序的數(shù)據取代原先進程的數(shù)據,新程序的堆棧取代原先進程的堆棧,從而實現(xiàn)了進程的切換。
2. 替換原理
進程程序替換的原理是通過操作系統(tǒng)提供的相關函數(shù),將當前進程的執(zhí)行映像(包括代碼、數(shù)據和堆棧等信息)替換為新的程序的執(zhí)行映像。具體步驟如下:
- 操作系統(tǒng)接收到進程程序替換的請求。
- 操作系統(tǒng)在磁盤上找到新程序的可執(zhí)行文件,并加載到內存中。
- 操作系統(tǒng)根據新程序的可執(zhí)行文件格式,解析出新程序的代碼、數(shù)據和其他相關信息。
- 操作系統(tǒng)為新程序分配新的地址空間,并將新程序的代碼、數(shù)據和堆棧等信息復制到新的地址空間中。
- 操作系統(tǒng)更新進程控制塊(Process Control Block,PCB)中的相關信息,如程序計數(shù)器(Program Counter)指向新程序的入口地址。
- 操作系統(tǒng)修改進程的內存映射表,更新各個段的物理地址映射關系。
- 操作系統(tǒng)關閉原程序打開的文件描述符,釋放相應的資源。
- 操作系統(tǒng)將控制權交還給新程序的入口代碼,開始執(zhí)行新程序。
- 新程序開始執(zhí)行,繼續(xù)在新的執(zhí)行映像中進行運算和處理。
需要注意的是,進程程序替換只會替換當前進程的執(zhí)行映像,不會影響其他進程。替換后的程序會繼承原進程的一些狀態(tài)信息,如文件描述符、信號處理設置等,以確保新程序能夠正常運行。
3. 替換函數(shù)
?exec函數(shù)
六種以exec開頭的函數(shù),統(tǒng)稱exec函數(shù):
-
int execl(const char *path, const char *arg0, ... /* (char *) NULL */);
- 替換當前進程的執(zhí)行映像為指定路徑的可執(zhí)行文件。
- 參數(shù)
path
是指定可執(zhí)行文件的路徑,參數(shù)arg0
和之后的參數(shù)是傳遞給新程序的命令行參數(shù)。 - 函數(shù)返回值為-1表示替換失敗,否則不會返回。
-
int execlp(const char *file, const char *arg0, ... /* (char *) NULL */);
- 替換當前進程的執(zhí)行映像為指定名稱的可執(zhí)行文件。文件名會在環(huán)境變量
$PATH
指定的目錄中查找。 - 參數(shù)
file
是指定可執(zhí)行文件的名稱,參數(shù)arg0
和之后的參數(shù)是傳遞給新程序的命令行參數(shù)。 - 函數(shù)返回值為-1表示替換失敗,否則不會返回。
- 替換當前進程的執(zhí)行映像為指定名稱的可執(zhí)行文件。文件名會在環(huán)境變量
-
int execle(const char *path, const char *arg0, ... /* (char *) NULL, char *const envp[] */);
- 替換當前進程的執(zhí)行映像為指定路徑的可執(zhí)行文件,并可以通過
envp
參數(shù)設置新程序的環(huán)境變量。 - 參數(shù)
path
是指定可執(zhí)行文件的路徑,參數(shù)arg0
和之后的參數(shù)是傳遞給新程序的命令行參數(shù),最后的envp
參數(shù)是環(huán)境變量數(shù)組。 - 函數(shù)返回值為-1表示替換失敗,否則不會返回。
- 替換當前進程的執(zhí)行映像為指定路徑的可執(zhí)行文件,并可以通過
-
int execv(const char *path, char *const argv[]);
- 替換當前進程的執(zhí)行映像為指定路徑的可執(zhí)行文件,并傳遞參數(shù)列表給新程序。
- 參數(shù)
path
是指定可執(zhí)行文件的路徑,參數(shù)argv
是傳遞給新程序的參數(shù)數(shù)組,以NULL結尾。 - 函數(shù)返回值為-1表示替換失敗,否則不會返回。
-
int execvp(const char *file, char *const argv[]);
- 替換當前進程的執(zhí)行映像為指定名稱的可執(zhí)行文件,并傳遞參數(shù)列表給新程序。文件名會在環(huán)境變量
$PATH
指定的目錄中查找。 - 參數(shù)
file
是指定可執(zhí)行文件的名稱,參數(shù)argv
是傳遞給新程序的參數(shù)數(shù)組,以NULL結尾。 - 函數(shù)返回值為-1表示替換失敗,否則不會返回。
- 替換當前進程的執(zhí)行映像為指定名稱的可執(zhí)行文件,并傳遞參數(shù)列表給新程序。文件名會在環(huán)境變量
-
int execve(const char *path, char *const argv[], char *const envp[]);
- 替換當前進程的執(zhí)行映像為指定路徑的可執(zhí)行文件,并傳遞參數(shù)列表和環(huán)境變量數(shù)組給新程序。
- 參數(shù)
path
是指定可執(zhí)行文件的路徑,參數(shù)argv
是傳遞給新程序的參數(shù)數(shù)組,以NULL結尾,envp
是環(huán)境變量數(shù)組。 - 函數(shù)返回值為-1表示替換失敗,否則不會返回。
這些函數(shù)都可以在C/C++等編程語言中使用,并通過設置參數(shù)來實現(xiàn)進程程序替換的功能。具體使用哪個函數(shù)取決于是否需要指定路徑和環(huán)境變量以及參數(shù)的形式(以列表或數(shù)組表示)。
?命名理解
- l(list) : 表示參數(shù)采用列表
- v(vector) : 參數(shù)用數(shù)組
- p(path) : 有p自動搜索環(huán)境變量PATH
- e(env) : 表示自己維護環(huán)境變量
函數(shù)名 | 參數(shù)格式 | 是否帶路徑 | 是否使用當前環(huán)境變量 |
---|---|---|---|
execl | 列表 | 不是 | 是 |
execlp | 列表 | 是 | 是 |
execle | 列表 | 不是 | 不是,需自己組裝環(huán)境變量 |
execv | 數(shù)組 | 不是 | 是 |
execvp | 數(shù)組 | 是 | 是 |
execve | 數(shù)組 | 不是 | 不是,需自己組裝環(huán)境變量 |
exec函數(shù)族 一個完整的例子(圖)
五、總結
-
進程創(chuàng)建
- 進程創(chuàng)建使用
fork
函數(shù),可以復制當前進程創(chuàng)建一個新的子進程。fork
函數(shù)的返回值不同,子進程中返回0,父進程中返回子進程的PID。fork
函數(shù)利用寫時拷貝技術實現(xiàn)了高效的進程創(chuàng)建。
- 進程創(chuàng)建使用
-
進程終止
- 進程終止可以通過多種方式實現(xiàn),常見的有調用
exit
函數(shù)和_exit
函數(shù)、return
語句以及異常終止。exit
函數(shù)是標準庫函數(shù),進行一些清理工作后終止進程。_exit
函數(shù)是系統(tǒng)調用函數(shù),直接終止進程。return
語句是從main
函數(shù)返回,等價于調用exit
函數(shù)。
- 進程終止可以通過多種方式實現(xiàn),常見的有調用
-
進程等待
- 進程等待是指父進程等待子進程執(zhí)行完畢的過程??梢允褂?code>wait和
waitpid
函數(shù)來實現(xiàn)進程等待。wait
函數(shù)會阻塞父進程,直到子進程退出,返回子進程的PID。waitpid
函數(shù)可以指定等待的子進程PID,并具有更多的選項。
- 進程等待是指父進程等待子進程執(zhí)行完畢的過程??梢允褂?code>wait和
-
進程程序替換
- 進程程序替換是指將當前進程的執(zhí)行映像替換為新的可執(zhí)行文件。替換函數(shù)如
exec
函數(shù)族可以實現(xiàn)進程程序的替換。exec
函數(shù)會加載新的程序代碼和數(shù)據,并開始執(zhí)行新程序。
- 進程程序替換是指將當前進程的執(zhí)行映像替換為新的可執(zhí)行文件。替換函數(shù)如
溫馨提示
感謝您對博主文章的關注與支持!如果您喜歡這篇文章,可以點贊、評論和分享給您的同學,這將對我提供巨大的鼓勵和支持。另外,我計劃在未來的更新中持續(xù)探討與本文相關的內容。我會為您帶來更多關于Linux以及C++編程技術問題的深入解析、應用案例和趣味玩法等。如果感興趣的話可以關注博主的更新,不要錯過任何精彩內容!文章來源:http://www.zghlxwxcb.cn/news/detail-714988.html
再次感謝您的支持和關注。我們期待與您建立更緊密的互動,共同探索Linux、C++、算法和編程的奧秘。祝您生活愉快,排便順暢!文章來源地址http://www.zghlxwxcb.cn/news/detail-714988.html
到了這里,關于【探索Linux】—— 強大的命令行工具 P.10(進程的控制——創(chuàng)建、終止、等待、程序替換)的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!