程序建立與終止



到目前為止,我們知道每當我們執行一個程式時,就會建立一個程序,並在執行完成後終止。如果我們需要在程式中建立一個程序,並可能希望為它安排不同的任務,該怎麼辦?這可以實現嗎?是的,顯然可以透過程序建立來實現。當然,任務完成後,它會自動終止,或者您可以根據需要終止它。

程序建立是透過**fork()系統呼叫**實現的。新建立的程序稱為子程序,啟動它的程序(或開始執行的程序)稱為父程序。fork()系統呼叫之後,我們現在有兩個程序——父程序和子程序。如何區分它們?很簡單,透過它們的返回值。

System Call

建立子程序後,讓我們看看fork()系統呼叫的細節。

#include <sys/types.h>
#include <unistd.h>

pid_t fork(void);

建立子程序。此呼叫之後,存在兩個程序,現有的程序稱為父程序,新建立的程序稱為子程序。

fork()系統呼叫返回以下三個值之一:

  • 負值表示錯誤,即建立子程序不成功。

  • 子程序返回零。

  • 父程序返回一個正值。此值是新建立子程序的程序 ID。

讓我們考慮一個簡單的程式。

File name: basicfork.c
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main() {
   fork();
   printf("Called fork() system call\n");
   return 0;
}

執行步驟

編譯

gcc basicfork.c -o basicfork

執行/輸出

Called fork() system call
Called fork() system call

**注意**——通常在fork()呼叫之後,子程序和父程序將執行不同的任務。如果需要執行相同的任務,則對於每個fork()呼叫,它將執行2的n次方次,其中**n**是fork()呼叫的次數。

在上述情況下,fork()呼叫一次,因此輸出列印兩次(2的1次方)。如果fork()呼叫,例如3次,則輸出將列印8次(2的3次方)。如果呼叫5次,則列印32次,依此類推。

在瞭解了fork()如何建立子程序之後,現在是時候瞭解父程序和子程序的詳細資訊了。

檔名:pids_after_fork.c

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main() {
   pid_t pid, mypid, myppid;
   pid = getpid();
   printf("Before fork: Process id is %d\n", pid);
   pid = fork();

   if (pid < 0) {
      perror("fork() failure\n");
      return 1;
   }

   // Child process
   if (pid == 0) {
      printf("This is child process\n");
      mypid = getpid();
      myppid = getppid();
      printf("Process id is %d and PPID is %d\n", mypid, myppid);
   } else { // Parent process 
      sleep(2);
      printf("This is parent process\n");
      mypid = getpid();
      myppid = getppid();
      printf("Process id is %d and PPID is %d\n", mypid, myppid);
      printf("Newly created process id or child pid is %d\n", pid);
   }
   return 0;
}

編譯和執行步驟

Before fork: Process id is 166629
This is child process
Process id is 166630 and PPID is 166629
Before fork: Process id is 166629
This is parent process
Process id is 166629 and PPID is 166628
Newly created process id or child pid is 166630

程序可以透過以下兩種方式之一終止:

  • 異常終止,發生在傳遞某些訊號時,例如終止訊號。

  • 正常終止,使用_exit()系統呼叫(或_Exit()系統呼叫)或exit()庫函式。

_exit()和exit()之間的主要區別在於清理活動。**exit()**在返回控制給核心之前會執行一些清理工作,而**_exit()**(或_Exit())會立即將控制返回給核心。

考慮以下帶有exit()的示例程式。

檔名:atexit_sample.c

#include <stdio.h>
#include <stdlib.h>

void exitfunc() {
   printf("Called cleanup function - exitfunc()\n");
   return;
}

int main() {
   atexit(exitfunc);
   printf("Hello, World!\n");
   exit (0);
}

編譯和執行步驟

Hello, World!
Called cleanup function - exitfunc()

考慮以下帶有_exit()的示例程式。

檔名:at_exit_sample.c

#include <stdio.h>
#include <unistd.h>

void exitfunc() {
   printf("Called cleanup function - exitfunc()\n");
   return;
}

int main() {
   atexit(exitfunc);
   printf("Hello, World!\n");
   _exit (0);
}

編譯和執行步驟

Hello, World!
廣告