Linux——进程创建和进程终止

1.进程创建

1.1fork函数初识

  • fork函数,从已存在进程中创建一个新进程,新进程为子进程,而原进程为父进程
    在这里插入图片描述
  • 进程调用fork,当控制转移到内核中的fork代码后,内核会做如下几件事:
  • 分配新的内存块和内核数据结构给子进程
  • 将父进程部分数据结构内容拷贝至子进程
  • 添加子进程到系统进程列表当中
  • fork返回,开始调度器调度

1.2 fork函数返回值(为什么两个返回值?)

在这里插入图片描述

1.3 写时拷贝(代码共享why和数据私有why)

  • 默认情况下,父子进程共享代码,数据各自私有一份
  • 代码共享:所有代码共享,一般都是从fork()函数之后开始执行,原因:代码不可以被修改,所以各自浪费私有空间
  • 数据私有原因:因为进程之间具有独立性,数据是很多的,但并不是所有的数据都立马要使用,且不是所有的数据都需要进行拷贝。如果需要立马独立,就要将数据全部拷贝,把本来可以再后面拷贝的,甚至不需要拷贝的数据全部拷贝,但是这样十分的浪费时间和空间
  • 拷贝的过程不是立马做的,父子代码共享,父子再不写入时,数据也是共享的,此时,如果任意一方试图写入,便以写时拷贝的方式各自一份副本,所以我们这里引入一个写时拷贝的概念
    在这里插入图片描述

1.4 fork常规用法和调用失败的原因

1.4.1 常规用法

  • 子进程赋值父进程,通过if、else来实现父子进程执行不同的代码段。比如父进程等待客户端请求生成子进程来进行处理
  • 一个进程要执行一个不同的程序。比如fork后,子进程调用exec函数

1.4.2调用失败的原因

  • 系统中有太多的进程
  • 实际用户的进程数超过了限制

1.5 如何理解子进程创建和fork()?

  • 子进程创建的实质是系统多了一个进程,因此OS需要将子进程也管理起来,就需要创建新的PCB,虚拟空间,页表,映射关系(这些属性自己进程都以父进程为模板拷贝过来)
  • 并且当父子进程各有一方想要写入数据时就会发生写时拷贝,将数据独立出来,比如说数据一共是10M,但写入的时候是1M,发生写时拷贝,此时拷贝的应该是1M的数据

2.进程终止

2.1进程退出场景

在这里插入图片描述
在这里插入图片描述

2.2为什么main()函数的返回值通常是0呢?

  • 因为在C/C++中的函数设计通常把0表示为正确,当main()函数执行结束的时候返回0,表示这个函数正常运行完,并且结果正确,非0表示错误,每种退出码对应一种错误。

2.3进程常见退出方法

2.3.1正常终止

  • 从main函数返回
  • 调用库函数exit()
  • _exit(接口调用)

2.3.2异常终止

  • ctrl+c,信号终止

2.4 exit,_exit,return区别

  • exit:终止整个进程,任何地方调用,都会终止进程,会刷新缓冲区
    在这里插入图片描述
    在这里插入图片描述

  • _exit:属于系统调用,不会刷新缓冲区
    在这里插入图片描述
    在这里插入图片描述

  • return退出:return是一种更常见的退出进程方法。执行return n等同于执行exit(n),因为调用main的运行时函数会将main的返回值当做exit的参数

猜你喜欢

转载自blog.csdn.net/qq_45657288/article/details/114851733