Linux中的fork()函数

fork函数

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

#include <unistd.h>
pid_t fork(void);

返回值:

  • 子进程中返回0
  • 父进程返回子进程id
  • 出错返回-1

那么为什么要这样设返回值呢?

  • 将子进程id返回给父进程:原因很简单,一个父亲可以有多个儿子,所以儿子很容易就能找到父亲(调用getppid()),但父亲很难找到所有的儿子,没有一个函数使一个进程可以获得所有子进程的Id。

进程调用fork,当控制转移到内核中的fork代码后,内核做:

  1. 分配新的内存块和内核数据结构给子进程
  2. 将父进程部分数据结构内容拷贝至子进程
  3. 添加子进程到系统进程列表当中
  4. fork返回,开始调度器调度

当一个进程调用fork之后,就有两个二进制代码相同的进程。而且它们都运行到相同的地方。但每个进程都将可以开始它们自己的旅程。

int main()
{
	int i;
    for(i=0;i<2;i++)
    {
    	if(fork()==0)
        {
  	      printf("A\n");
  	    }
        else
        {
          printf("B\n");
        }
    }
}

fork 之后会产生父子进程,相当于父进程拷贝了一份给子进程,其中包括缓冲区中的数据。对于fork之后的代码会继续执行.。所以结果是三个A,三个B。
在这里插入图片描述

int main()
{
	int i;
    for(i=0;i<2;i++)
    {
    	if(fork()==0)
        {
  	      printf("A");
  	    }
        else
        {
          printf("B");
        }
    }
}

在这里插入图片描述

  • fork之后,i=0,产生父子进程,没有遇到\n,程序也没有结束,那么父进程得到的A和子进程得到的B都会在缓冲区先呆着,i=1时,又fork一次,父子进程会把自己的在拷贝一份给他们各自的子进程,那么拷贝的时候就包含了呆在缓冲区里的东西,所以i=2,程序结束,输出缓冲区里的东西,就是4个A,4个B
  • fork之后父子进程谁先执行完全由调度器来决定。
  • 注意:
  • 第二个代码中的printf 语句中没有了 \n,这涉及到printf输出缓冲区的问题,缓冲区中的数据只有在以下几种可能会输出:① 遇到\n ② fflush(stdout) 刷新缓冲区 ③程序结束(exit或return)④ 缓冲区满。( 注意:_exit 程序结束时不刷新缓冲区 )

写时拷贝

通常,父子代码共享,父子再不写入时,数据也是共享的,当任意一方试图写入,便以写时拷贝的方式各自一份副本。(类似C++String类中的写时拷贝)

fork常规用法

  • 一个父进程希望复制自己,使父子进程同时执行不同的代码段。例如,父进程等待客户端请求,生成子进程来处理请求。
  • 一个进程要执行一个不同的程序。例如子进程从fork返回后,调用exec函数。

fork调用失败的原因

  • 系统中有太多的进程
  • 实际用户的进程数超过了限制
发布了161 篇原创文章 · 获赞 52 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/qq_42837885/article/details/101950162