程序是一組可以執行一次、多次或同時執行的指令和數據。一個進程就是這樣一個程序的執行。因此,這些進程可以運行許多程序。在同一進程中,操作系統可以加載各種程序。重用進程的狀態,例如當前目錄、權限和文件句柄,由新程序繼承。此類事情與 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

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() 系統調用。有關更多信息,請使用這些系統調用運行您的程序並查看結果。謝謝你!