進程的創建是Linux系統編程中的重要概念之一。在本節中,我們將介紹進程的創建、獲取進程ID和父進程ID、進程共享、exec函數族、wait和waitpid等相關內容。
文章目錄
- 1. 進程的創建
- 1.1 函數原型和返回值
- 1.2 函數示例
- 2. 獲取進程ID和父進程ID
- 2.1 函數原型和返回值
- 2.2 函數示例
- 3. exec函數族
- 3.1 `exec()`函數族的常見成員:
- 3.2 函數示例
- 4. wait和waitpid
- 4.1 函數解釋
- 4.2 函數示例
- 總結
1. 進程的創建
在Linux系統中,進程的創建使用fork()
系統調用。fork()
系統調用會創建一個與當前進程相同的子進程,子進程會復制父進程的所有資源,包括代碼、數據和文件描述符等。
1.1 函數原型和返回值
fork()
函數的原型如下:
#include <unistd.h>pid_t fork(void);
fork()
函數 沒有任何參數 ,它的返回值是一個pid_t
類型的整數。具體解釋如下:
- 如果調用成功,
fork()
函數會在父進程中返回子進程的PID(子進程ID),在子進程中返回0。 - 如果調用失敗,
fork()
函數會返回-1,并設置errno
來指示錯誤類型。
1.2 函數示例
代碼示例如下:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>int main() {pid_t pid = fork();if (pid == -1) {printf("Failed to fork a new process.\n");return 1;} else if (pid == 0) {printf("This is the child process.\n");} else {printf("This is the parent process.\n");}return 0;
}
上述代碼中,fork()
系統調用會返回兩次,分別在父進程和子進程中返回。通過判斷返回值,我們可以區分父進程和子進程,并執行不同的代碼邏輯。
2. 獲取進程ID和父進程ID
在Linux系統中,可以使用getpid()
和getppid()
系統調用來獲取當前進程的ID和父進程的ID。
2.1 函數原型和返回值
getpid()
和getppid()
函數的原型如下:
#include <sys/types.h>
#include <unistd.h>pid_t getpid(void);
pid_t getppid(void);
這兩個函數都 沒有任何參數 ,它們的返回值都是一個pid_t
類型的整數。具體解釋如下:
getpid()
函數返回調用進程的進程ID(PID)。getppid()
函數返回調用進程的父進程的進程ID(PPID)。
2.2 函數示例
代碼示例如下:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>int main() {pid_t pid = getpid();pid_t ppid = getppid();printf("Process ID: %d\n", pid);printf("Parent Process ID: %d\n", ppid);return 0;
}
3. exec函數族
在Linux系統中,exec()
函數族可以用于將當前進程替換為新的程序。exec()
函數族包括execl()
、execv()
、execle()
、execve()
等函數。這些函數可以根據不同的參數形式來執行不同的替換方式。
3.1 exec()
函數族的常見成員:
-
int execl(const char *path, const char *arg, ...);
- 參數
path
是要執行的新程序的路徑。 - 參數
arg
是一個字符串,表示新程序的第一個參數。 - 可變參數列表是新程序的其他參數,必須以
NULL
結束。 - 函數執行成功時不會返回,如果返回則表示執行失敗。
- 參數
-
int execv(const char *path, char *const argv[]);
- 參數
path
是要執行的新程序的路徑。 - 參數
argv
是一個字符串數組,表示新程序的參數列表,最后一個元素必須是NULL
。 - 函數執行成功時不會返回,如果返回則表示執行失敗。
- 參數
-
int execle(const char *path, const char *arg, ..., char *const envp[]);
- 參數
path
是要執行的新程序的路徑。 - 參數
arg
是一個字符串,表示新程序的第一個參數。 - 可變參數列表是新程序的其他參數,必須以
NULL
結束。 - 參數
envp
是一個字符串數組,表示新程序的環境變量列表,最后一個元素必須是NULL
。 - 函數執行成功時不會返回,如果返回則表示執行失敗。
- 參數
-
int execvp(const char *file, char *const argv[]);
- 參數
file
是要執行的新程序的文件名。 - 參數
argv
是一個字符串數組,表示新程序的參數列表,最后一個元素必須是NULL
。 - 函數執行成功時不會返回,如果返回則表示執行失敗。
- 參數
這些函數在執行成功時不會返回,而是直接將當前進程替換為新程序。如果返回,則表示執行失敗,可以根據返回值來判斷錯誤類型。
exec()
函數族可以用于在當前進程中加載和執行新程序,可以實現程序的動態切換和功能擴展。一般情況下,exec()
函數族會在調用fork()
函數創建子進程后使用,以替換子進程的代碼和數據。
3.2 函數示例
代碼示例如下:
#include <stdio.h>
#include <unistd.h>int main() {printf("Before exec()\n");execl("/bin/ls", "ls", "-l", NULL);printf("After exec()\n");return 0;
}
上述代碼中,execl()
函數會將當前進程替換為ls -l
命令。execl()
函數的第一個參數是要執行的程序路徑,后續參數是傳遞給新程序的命令行參數。
4. wait和waitpid
在Linux系統中,父進程可以使用wait()
或waitpid()
系統調用等待子進程的結束。這些系統調用會阻塞父進程的執行,直到子進程結束。
4.1 函數解釋
wait()
和waitpid()
是用于等待子進程結束并獲取子進程的退出狀態的函數。
-
pid_t wait(int *status);
- 函數會掛起當前進程,直到一個子進程結束。
- 如果成功等到子進程結束,函數會返回子進程的進程ID。
- 參數
status
是一個指向整型的指針,用于存儲子進程的退出狀態信息。 - 如果調用失敗,函數會返回-1。
-
pid_t waitpid(pid_t pid, int *status, int options);
- 函數會掛起當前進程,直到指定的子進程結束。
- 參數
pid
指定要等待的子進程的進程ID。 - 參數
status
是一個指向整型的指針,用于存儲子進程的退出狀態信息。 - 參數
options
是一個整型值,用于指定等待的選項。 - 如果調用失敗,函數會返回-1。
wait()
和waitpid()
函數的返回值是子進程的進程ID,如果調用失敗,則返回-1。通過參數 status
可以獲取子進程的退出狀態信息,包括退出碼、終止信號等。
waitpid()
函數相比于wait()
函數更加靈活,可以通過參數 pid
和 options
控制等待的子進程。
其中,pid
的取值可以是:
-1
:等待任意子進程。0
:等待與當前進程組ID相同的子進程。- 具體的子進程ID:等待指定的子進程。
options
參數可以通過位掩碼的方式指定多個選項,常用的選項有:
WNOHANG
:非阻塞方式,如果沒有子進程結束,立即返回。WUNTRACED
:也會返回已經停止的子進程的狀態。WCONTINUED
:也會返回已經繼續運行的子進程的狀態。
wait()
和waitpid()
函數可以用于處理子進程的退出狀態,釋放子進程的資源,并進行進程間的同步。在使用這兩個函數時,需要注意處理錯誤情況和避免僵尸進程的產生。
4.2 函數示例
代碼示例如下:
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>int main() {pid_t pid = fork();if (pid == -1) {printf("Failed to fork a new process.\n");return 1;} else if (pid == 0) {printf("This is the child process.\n");} else {wait(NULL);printf("This is the parent process.\n");}return 0;
}
上述代碼中,父進程使用wait(NULL)
系統調用等待子進程的結束。wait()
系統調用會阻塞父進程的執行,直到子進程結束。
總結
fork()
函數:用于創建子進程,返回值不同表示在不同的進程中執行。exec()
函數族:用于在當前進程中加載和執行新程序,可以實現程序的動態切換和功能擴展。execl()
:接受可變參數的形式,參數以字符串形式傳遞。execle()
:接受可變參數的形式,同時傳遞環境變量。execvp()
:接受參數數組的形式,參數以字符串數組形式傳遞。
wait()
和waitpid()
函數:用于等待子進程結束并獲取子進程的退出狀態。wait()
:等待任意子進程結束。waitpid()
:可以指定等待的子進程。- 通過參數
status
可以獲取子進程的退出狀態信息。 - 可以通過
options
參數控制等待的選項,如非阻塞方式等。 - 需要注意處理錯誤情況和避免僵尸進程的產生。
這些函數和系統調用可以用于進程的創建、執行和等待,實現進程間的同步和協作。通過這些函數,可以實現進程的動態切換、功能擴展和資源釋放。同時,需要注意處理錯誤情況,避免產生僵尸進程和資源泄漏的問題。