fork函数的作用_fork函数创建进程

电子常识

2586人已加入

描述

  fork函数的作用

  在Linux中fork函数是非常重要的函数,它的作用是从已经存在的进程中创建一个子进程,而原进程称为父进程。

Fork

  调用fork(),当控制转移到内核中的fork代码后,内核开始做:

  1.分配新的内存块和内核数据结构给子进程。

  2.将父进程部分数据结构内容拷贝至子进程。

  3.将子进程添加到系统进程列表。

  4.fork返回开始调度器,调度。

  来段代码:

  1 #include《stdio.h》

  2 #include《unistd.h》

  3 #include《stdlib.h》

  4 int main()

  5 {

  6 pid_t pid;

  7 printf(“before :pid is %d ”,getpid());

  8 if((pid=fork())==-1)

  9 perror(“fork()”),exit(1);

  10 printf(“After:pid=%d,fork return %d ”,getpid(),pid);

  11 sleep(1);

  12

  13 return 0;

  14 }

  15 123456789101112131415

  

  这个简单的例子有一些微妙的方面:

  •调用一次,返回两次

  fork函数被父进程调用一次,但是却返回两次;一次是返回到父进程,一次是返回到新创建的子进程。

  

  •并发执行

  子进程和父进程是并发运行的独立进程。内核能够以任意的方式交替执行他们的逻辑控制流中的指令。在我们的系统上运行这个程序时,父进程先运行它的printf语句,然后是子进程。

  •相同但是独立的地址空间

  因为父进程和子进程是独立的进程,他们都有自己私有的地址空间,当父进程或者子进程单独改变时,不会影响到彼此,类似于c++的写实拷贝的形式自建一个副本。

  •fork的返回值

  1.fork的子进程返回为0;

  2.父进程返回的是子进程的pid。

  •fork的常规用法

  1.一个父进程希望复制自己,使得子进程同时执行不同的代码段,例如:父进程等待客户端请求,生成一个子进程来等待请求处理。

  2.一个进程要执行一个不同的程序。

  •fokr调用失败的原因

  1.系统中有太多进程

  2.实际用户的进程数超过限制

  fork函数创建进程

  在linux下,C语言创建进程用fork函数,接下来我们通过代码来一步步了解fork函数的各个知识点。

  1、依赖的头文件

  1#include 《unistd.h》

  2、fork的原理和概念

  fork子进程就是从父进程拷贝一个新的进程出来,子进程和父进程的进程ID不同,但用户数据一样。

  在C语言中,创建一个子进程代码如下:

  pid_t pid; //pid_t 从底层来看,实际上是int类型。

  pid = fork();

  3、父进程和子进程

  执行fork函数后有2种返回值:对于父进程,返回的是子进程的PID(即返回一个大于0的数字);对于子进程,则返回0,所以我们可以通过pid这个返回值来判断当前进程是父进程还是子进程。如下代码所示:

  if(pid 》 0)

  {

  printf(“im parent process, pid: %d ”, getpid());

  }

  else if(pid == 0)

  {

  printf(“im child process, pid: %d, parent pid: %d ”, getpid(), getppid());

  }

  else

  {

  printf(“fork failed ”);

  }

  温馨提示:

  getpid() -获取当前进程的pid

  getppid() -获取当前进程的父进程的pid

  4、完整例子&子进程代码执行位置

  了解这些之后,我们来看一个创建子进程的完整代码示例:

  #include 《stdio.h》

  #include 《unistd.h》

  int main(int argc, char *argv[])

  {

  printf(“========== before fork ============= ”);

  pid_t pid;

  pid = fork();

  printf(“========== after fork ============= ”);

  if(pid 》 0)

  {

  printf(“im parent process, pid: %d ”, getpid());

  }

  else if(pid == 0)

  {

  printf(“im child process, pid: %d, parent pid: %d ”, getpid(), getppid());

  }

  else

  {

  printf(“fork failed ”);

  }

  printf(“========== process end ============= ”);

  sleep(1);

  return 0;

  }

  运行结果如下图:

  从上图可以看出,程序只输出了1个“before fork”,但输出了2个“after fork”,所以我们可以得出:子进程的代码执行是从fork()位置之后开始的。事实也确实是如此。

  5、循环创建子进程

  有时候,我们需要创建多个子进程,可以通过for循环来实现,代码如下:

  #include 《stdio.h》

  #include 《unistd.h》

  int main(int argc, char *argv[])

  {

  int i = 0;

  pid_t pid;

  for(i = 0; i 《 3; i++)

  {

  pid = fork();

  }

  if (pid == 0)

  {

  printf(“im child process, pid: %d, parent pid: %d ”, getpid(), getppid());

  }

  else

  {

  printf(“im parent process, pid: %d ”, getpid());

  }

  sleep(1);

  return 0;

  }

  运行结果如下图:

  咦,我们不是循环创建3个子进程吗,怎么输出了这么多次parent process和child process呢?

  这是因为子进程也创建了子进程,大家可以观察一下图中的pid。数了一下,共输出了8次,刚好是2的3次方。

  我画了一个fork步骤图,便于大家更好的理解,如下:

  

Fork

  如上图所示,子进程在第2轮、3轮,也会相当于父进程一样继续fork子进程,所以for循环3次后,刚好得到共8个进程。

  那如果我们就想通过循环3次,得到3个子进程,要怎么办呢?

  思路:不让子进程fork出新的子进程。

  代码片段如下:

  for(i = 0; i 《 3; i++)

  {

  pid = fork();

  if (pid == 0)

  {

  break;

  }

  }

  运行结果:

  

  至此,fork函数创建子进程介绍完毕。
责任编辑:YYX

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分