#include
int execlp(const char *file, const char *arg, ... /* (char *)NULL */);
// 相當於 shell 執行:ls -al /home
execlp("ls", "ls", "-al", "/home", (char *)NULL);
// 相當於:grep -r "pattern" /var/log
execlp("grep", "grep", "-r", "pattern", "/var/log", (char *)NULL);
常見錯誤:忘記結束的 `NULL`、參數順序錯誤、將選項與值合併為一個字串 (如 `"-al /home"`)。
#include
#include
#include
#include
#include
int main(void) {
printf("PID %d: 準備執行 ls -al /tmp\n", getpid());
// 使用 execlp 執行 ls
execlp("ls", "ls", "-al", "/tmp", (char *)NULL);
// 只有失敗時才會執行到這裡
fprintf(stderr, "execlp 失敗: %s\n", strerror(errno));
return EXIT_FAILURE;
}
gcc execlp_demo.c -o execlp_demo
./execlp_demo
PID 12345: 準備執行 ls -al /tmp
total 12
drwxrwxrwt 3 root root 4096 Jan 1 10:00 .
drwxr-xr-x 18 root root 4096 Jan 1 09:00 ..
-rw-r--r-- 1 user user 100 Jan 1 10:00 foo.txt
drwx------ 2 user user 4096 Jan 1 10:00 ssh-xyz123
# 程式結束,不會返回原進程繼續執行
| 函數 | 參數形式 | PATH 搜尋 | 環境變數 | 典型用途 |
|---|---|---|---|---|
| execl | 列表 (arg0, arg1..., NULL) | 否 (需完整路徑) | 繼承 | 路徑固定的內部命令 |
| execlp | 列表 | 是 | 繼承 | 用戶輸入命令名、PATH 環境 |
| execle | 列表 + envp[] | 否 | **指定新環境** | 需控制環境變數 |
| execv | argv[] 陣列 | 否 | 繼承 | 參數動態構建 (陣列) |
| execvp | argv[] 陣列 | 是 | 繼承 | 參數動態 + PATH 搜尋 |
| execvpe | argv[] + envp[] | 是 | **指定新環境** | 完全控制參數與環境 |
pid_t pid = fork();
if (pid == 0) { // 子進程
execlp("ls", "ls", "-l", (char *)NULL);
perror("execlp"); // 失敗才執行
_exit(EXIT_FAILURE);
} else if (pid > 0) { // 父進程
waitpid(pid, NULL, 0); // 等待子進程結束
printf("子進程已結束,父進程繼續\n");
} else {
perror("fork");
}
此模式實現「父進程繼續運行,子進程執行新程式」的並發邏輯,是 Shell、服務管理器、任務調度器的基石。
| errno | 宏 | 原因 | 對策 |
|---|---|---|---|
| ENOENT | No such file or directory | PATH 中找不到可執行文件 | 確認命令拼寫、安裝套件、PATH 設定 |
| EACCES | Permission denied | 文件無執行權限 | `chmod +x` 或檢查掛載選項 noexec |
| ENOMEM | Out of memory | 內核無法分配新進程映像 | 檢查內存、ulimit -v |
| E2BIG | Argument list too long | 參數+環境變數總長超限 | 縮減參數、環境變數 |
`execlp` 以「PATH 搜尋 + 列表參數 + 進程映像替換」三大特性,成為實現命令執行、腳本解釋器、插件加載的核心系統調用。掌握 `fork + exec` 模式與參數構建規範,是 Linux 系統編程進階的必經之路。