目录
当前位置: 首页 > 教程 > 进程通信 >

进程创建与终止

精华
小牛编辑
111浏览
2023-03-14

到目前为止,我们知道每当执行一个程序时,就会创建一个进程,并在执行完成后终止。 如果我们需要在程序中创建一个进程,并且可能希望为其安排不同的任务。 这可以实现吗? 是的,显然是通过进程创建来实现。 当然,工作完成后进程会自动终止,或者根据需要终止。

过程创建是通过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!