进程创建和终止
到目前为止,我们知道每当我们执行一个程序时,就会创建一个进程,并在执行完成后终止该进程。如果我们需要在程序中创建一个进程,并且可能希望为其安排不同的任务,该怎么办?这可以实现吗?是的,显然是通过进程创建。当然,在工作完成后,它会自动终止,或者您可以根据需要终止它。
进程创建是通过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 "); 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 ", pid); pid = fork(); if (pid < 0) { perror("fork() failure "); return 1; } // Child process if (pid == 0) { printf("This is child process "); mypid = getpid(); myppid = getppid(); printf("Process id is %d and PPID is %d ", mypid, myppid); } else { // Parent process sleep(2); printf("This is parent process "); mypid = getpid(); myppid = getppid(); printf("Process id is %d and PPID is %d ", mypid, myppid); printf("Newly created process id or child pid is %d ", 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() "); return; } int main() { atexit(exitfunc); printf("Hello, World! "); 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() "); return; } int main() { atexit(exitfunc); printf("Hello, World! "); _exit (0); }
编译和执行步骤
Hello, World!