進程建立與終止


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

過程建立是通過fork()系統呼叫實現的。 新建立的進程稱為子進程,啟動該進程的進程(或執行開始時的進程)稱為父進程。 在fork()系統呼叫之後,現在有兩個進程 - 父進程和子進程。 如何區分它們? 非常簡單,可通過它們的返回值來區分它們。

在建立子進程之後,讓我們看看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;
}

執行步驟

編譯 -

yiibai$ gcc basicfork.c -o basicfork

執行後輸出結果如下 -

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

註 - 通常在呼叫fork()之後,子進程和父進程將執行不同的任務。 如果需要執行相同的任務,那麼對於每個fork()呼叫,它將執行n次,其中n是呼叫fork()的次數。

在上面的情況下,fork()被呼叫一次,因此輸出列印兩次(2次冪)。 如果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!