進程創建與終止

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

過程創建是通過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!