📜  流程,父流程和子流程之间的差异

📅  最后修改于: 2021-08-24 05:05:12             🧑  作者: Mango

运行程序是一个 过程。从这个过程中,可以创建另一个过程。这两个过程之间存在父子关系。这可以使用称为fork()的库函数来实现。 fork()函数将运行中的进程分为两个进程,现有的一个称为父进程,新的一个称为子进程。这是一个演示此程序:

C
// C program to demonstrate
// the above concept
#include 
#include
#include  
  
// Driver code
int main()
{
  printf ("Before Forking\n");
  fork();
  printf ("After Forking\n");
}


C
// C program for the above approach
#include 
  
// Driver Code
int main( )
{
  int pid;
  pid = fork();
  if (pid == 0)
  {
    printf ("In child process\n");
      
    /* code to play animated GIF file */
  }
  else
  {
    printf ("In parent process\n");
      
    /* code to copy file */
  }
}


C
// C program to implement
// the above approach
# include 
  
// Driver code
int main()
{
  int pid;
  pid = fork();
  
  if (pid == 0)
  {
    printf ("Child : I am the child process\n");
    printf ("Child : Child’s PID: %d\n", getpid());
    printf ("Child : Parent’s PID: %d\n", getppid());
  }
  else
  {
    printf ("Parent : I am the parent process\n");
    printf ("Parent : Parent’s PID: %d\n", getpid());
    printf ("Parent : Child’s PID: %d\n", pid);
  }
}


输出
Before Forking
After Forking
Before Forking
After Forking

说明: fork()之后的所有语句均执行两次:

  1. 一次由父进程处理。
  2. 语句第二次由子进程执行。

让我们更详细地讨论以下概念:

  1. 过程。
  2. 父进程。
  3. 子进程。

进程进程是正在执行的程序,即活动程序。一个过程不仅仅是程序代码,它还包括以下内容:

  1. 程序计数器。
  2. 进程堆栈。
  3. 寄存器。
  4. 程序代码等

相反,程序代码只是一个文本部分。

进程在执行时会更改其状态。新状态部分取决于流程的当前活动。流程在执行过程中的不同状态是:

  1. 新的
  2. 准备好
  3. 跑步
  4. 受阻
  5. 已终止。

过程控制块和过程表与每个过程相关联。它包含有关该过程的以下重要信息:

  1. 进程状态。
  2. 进程号。
  3. 程序计数器。
  4. 文件和寄存器列表。
  5. CPU信息。
  6. 内存信息等

父进程除启动进程外,所有进程都是在一个进程执行fork()系统调用时创建的。执行 fork()系统调用是父进程。父进程是使用fork()系统调用创建子进程的进程。一个父进程可能有多个子进程,但是一个子进程只有一个父进程。

成功完成fork()系统调用:

  • 子进程的进程ID(PID)返回到父进程。
  • 0返回到子进程。

在fork()系统调用失败时,

  • -1返回到父进程。
  • 未创建子进程。

子进程子进程是由操作系统中的父进程使用fork()系统调用创建的。子进程也可以称为子进程或子任务。

  • 子进程被创建为其父进程的副本。
  • 子进程继承其大部分属性。
  • 如果子进程没有父进程,则子进程由内核直接创建。
  • 如果子进程退出或被中断,则将SIGCHLD信号发送到父进程,以通知子进程的终止或退出。

为什么我们需要创建一个子进程?
有时需要一种程序同时执行多个函数。由于这些作业可能是相互关联的,因此无法创建两个不同的程序来执行它们。例如:假设有两个作业:将源文件的内容复制到目标文件,并显示一个动画进度条,指示正在进行文件复制。 GIF进度条文件应继续播放,直到进行文件复制为止。复制过程完成后,应停止播放GIF进度条文件。由于这两个作业是相互关联的,因此无法在两个不同的程序中执行。同样,它们不能一个接一个地执行。两项工作应同时执行。

在这种时候, fork()用于创建子进程,然后以这样的方式编写程序:父进程进行文件复制,动画GIF文件的显示由子进程进行

程序1:这里的任务是演示如何同时执行两个不同但相互关联的工作。因此,仅显示了同时执行2个作业的方法,跳过了用于文件复制和播放GIF动画文件的实际代码。

C

// C program for the above approach
#include 
  
// Driver Code
int main( )
{
  int pid;
  pid = fork();
  if (pid == 0)
  {
    printf ("In child process\n");
      
    /* code to play animated GIF file */
  }
  else
  {
    printf ("In parent process\n");
      
    /* code to copy file */
  }
}

说明: fork()创建一个子进程,并在该子进程中复制父进程的代码。此后,在两个过程中继续执行fork()函数。因此,fork()内部的重复代码只执行一次,而内部的其余代码则在父进程和子进程中都执行。因此,即使实际上只调用一次,控制也会从fork()返回两次。当控件从父进程的fork()返回时,它将返回子进程的PID,而当控件从子进程的fork()返回时,它将始终返回0。我们想要在父流程中执行的代码,而不是我们想要在子流程中执行的代码。在上面的程序中使用if语句实现了此逻辑。在“如果块”在子进程的情况下执行,“else块”在父进程的情况下执行

程式2:
该程序将使用fork()调用来创建子进程。在子进程中,我们将打印子项及其父项的PID ,而在父进程中,我们将打印父项及其子项的PID

C

// C program to implement
// the above approach
# include 
  
// Driver code
int main()
{
  int pid;
  pid = fork();
  
  if (pid == 0)
  {
    printf ("Child : I am the child process\n");
    printf ("Child : Child’s PID: %d\n", getpid());
    printf ("Child : Parent’s PID: %d\n", getppid());
  }
  else
  {
    printf ("Parent : I am the parent process\n");
    printf ("Parent : Parent’s PID: %d\n", getpid());
    printf ("Parent : Child’s PID: %d\n", pid);
  }
}

输出:

Child : I am the child process
Child : Child's PID: 4706
Child : Parent's PID: 4705
Parent : I am the Parent process
Parent : Parent's PID: 4705
Parent : Child's PID: 4706