到目前為止,我們知道每當執(zhí)行一個程序時,就會創(chuàng)建一個進程,并在執(zhí)行完成后終止。 如果我們需要在程序中創(chuàng)建一個進程,并且可能希望為其安排不同的任務(wù)。 這可以實現(xiàn)嗎? 是的,顯然是通過進程創(chuàng)建來實現(xiàn)。 當然,工作完成后進程會自動終止,或者根據(jù)需要終止。
過程創(chuàng)建是通過fork()系統(tǒng)調(diào)用實現(xiàn)的。 新創(chuàng)建的進程稱為子進程,啟動該進程的進程(或執(zhí)行開始時的進程)稱為父進程。 在fork()系統(tǒng)調(diào)用之后,現(xiàn)在有兩個進程 - 父進程和子進程。 如何區(qū)分它們? 非常簡單,可通過它們的返回值來區(qū)分它們。
在創(chuàng)建子進程之后,讓我們看看fork()系統(tǒng)調(diào)用細節(jié)。參考以下代碼 -
#include <sys/types.h>
#include <unistd.h>
pid_t fork(void);
創(chuàng)建子進程。 這個調(diào)用之后,有兩個進程,現(xiàn)有的進程稱為父進程,新創(chuàng)建的進程稱為子進程。
fork()系統(tǒng)調(diào)用返回三個值之一 -
讓我們來看看一個簡單的程序。
// 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
執(zhí)行后輸出結(jié)果如下 -
Called fork() system call
Called fork() system call
注 - 通常在調(diào)用
fork()之后,子進程和父進程將執(zhí)行不同的任務(wù)。 如果需要運行相同的任務(wù),那么對于每個fork()調(diào)用,它將運行n次,其中n是調(diào)用fork()的次數(shù)。
在上面的情況下,fork()被調(diào)用一次,因此輸出打印兩次(2次冪)。 如果fork()被調(diào)用3次,那么輸出將被打印8次(2的3次方)。 如果被稱為5次,則打印32次,依此類推。
看到fork()創(chuàng)建子進程,就可以看到父進程和子進程的詳細信息了。
文件: 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;
}
編譯和執(zhí)行步驟 -
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()系統(tǒng)調(diào)用(或_Exit()系統(tǒng)調(diào)用)或exit()庫函數(shù)。_exit()和exit()之間的區(qū)別主要是清理活動。 exit()在將控制權(quán)返回給內(nèi)核之前做了一些清理,而_exit()(或_Exit())會立即將控制權(quán)返回給內(nèi)核。
考慮下面的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);
}
編譯和執(zhí)行結(jié)果 -
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);
}
編譯和執(zhí)行結(jié)果 -
Hello, World!