程序是一組可以執行一次、多次或同時執行的指令和數據。一個進程就是這樣一個程序的執行。因此,這些進程可以運行許多程序。在同一進程中,操作系統可以加載各種程序。重用進程的狀態,例如當前目錄、權限和文件句柄,由新程序繼承。此類事情與 fork()、exec()、wait()、exit() 等系統調用在同一級別完成。
本文通過示例和用例詳細介紹了 Linux 系統調用 fork()、exec()、wait() 和 exit()。
叉()
fork() 是 Linux/Unix 系統中非常特殊和有用的系統調用之一。進程使用它來創建自己的副本的進程。子進程可以由父進程在此類系統調用的幫助下創建。在子進程完成執行之前,父進程不會掛起。
fork() 的一些亮點是:
- 父進程獲取具有非零值的子進程 ID。
- 零值返回給孩子。
- 如果在創建子進程時發生系統或硬件錯誤,則將 -1 返回到 fork()。
- 子進程獲取的唯一進程ID與現有進程組的ID不匹配。
為了詳細解釋fork(),我們通過一個例子來闡明fork()的概念。
$ sudo vim fork.c
這是複制/粘貼的代碼:
#include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<sys/types.h> int main(int argc, char **argv) { pid_t pid; pid = fork(); if(pid==0) { printf("It is the child process and pid is %dn",getpid()); exit(0); } else if(pid > 0) { printf("It is the parent process and pid is %dn",getpid()); } else { printf("Error while forkingn"); exit(EXIT_FAILURE); } return 0; }
輸出:
$make fork
運行腳本後,您將獲得如下屏幕截圖所示的結果。
$ ./fork
嵌入 ()
exec() 是一個系統調用,它通過用新的進程映像替換當前進程映像來工作。但是,原來的進程仍然是一個新進程,只是新進程替換了頭數據、堆棧數據等。通過將程序加載到當前進程空間來從入口點運行程序。
為了說明,讓我們看一下下面給出的示例。
$ sudo vim exec.c
這是代碼:
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include <sys/wait.h> main(void) { pid_t pid = 0; int status; pid = fork(); if (pid == 0) { printf("I am the child."); execl("/bin/ls", "ls", "-l", "/home/ubuntu/", (char *) 0); perror("In exec(): "); } if (pid > 0) { printf("I am the parent, and the child is %d.n", pid); pid = wait(&status); printf("End of process %d: ", pid); if (WIFEXITED(status)) { printf("The process ended with exit(%d).n", WEXITSTATUS(status)); } if (WIFSIGNALED(status)) { printf("The process ended with kill -%d.n", WTERMSIG(status)); } } if (pid < 0) { perror("In fork():"); } exit(0); }
輸出:
$ make exec
運行腳本後,您將獲得如下屏幕截圖所示的結果。
$ ./exec
等待()
與 fork 一樣,創建並執行子進程,但父進程暫停,直到子進程執行。在這種情況下,掛起父進程會自動激活 wait() 系統調用。當子進程完成執行時,父進程再次獲得控制權。
為了詳細解釋wait(),我們以wait()系統調用為例。
$ sudo vim wait.c
這是代碼示例:
#include<stdio.h> // printf() #include<stdlib.h> // exit() #include<sys/types.h> // pid_t #include<sys/wait.h> // wait() #include<unistd.h> // fork int main(int argc, char **argv) { pid_t pid; pid = fork(); if(pid==0) { printf("It is the child process and pid is %dn",getpid()); int i=0; for(i=0;i<8;i++) { printf("%dn",i); } exit(0); } else if(pid > 0) { printf("It is the parent process and pid is %dn",getpid()); int status; wait(&status); printf("Child is reapedn"); } else { printf("Error in forking..n"); exit(EXIT_FAILURE); } return 0; }
輸出:
$ make wait
運行腳本後,您將獲得如下屏幕截圖所示的結果。
$ ./wait
寫出 ()
exit() 是一種用於終止此類函數或進程的系統調用。此系統調用定義線程的執行完成,尤其是在多線程環境中。捕獲進程的狀態以供以後參考。
使用 exit() 系統調用後,進程使用的所有資源都被操作系統獲取並終止進程。系統調用 Exit() 等價於 exit()。
概括
#include <unistd.h> void _exit(int status); #include <stdlib.h> void _Exit(int status);
您可以在上面的 fork() 和 wait() 示例中看到 exit() 函數的使用。要退出進程,請使用 exit() 系統調用。
結論是
本文通過一些示例探討了 fork()、exec()、wait() 和 exit() 系統調用。有關更多信息,請使用這些系統調用運行您的程序並查看結果。謝謝你!