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