[Linux从无到有]进程的创建、终止、等待、替换

进程是如何创建的?他又如何终止呢?进程等待又是如何等呢?替换进程还可以替换?如果你有这些问题那么这篇文章会为你解答

在这里插入图片描述







进程的创建

要创建一个进程有一下的方式

  1. 直接运行(Linux下./ 运行,windows,mac下鼠标点击运行)
  2. 程序中调用fork()函数创建子进程

那么我们这次看fork()函数是底层是如何创建进程的

知识回顾:

fork()函数的作作用就是创建子进程,父进程返回值是创建出来进程的pid,而子进程为0

为啥同一个变量会有俩个不同的值呢?

这涉及到了底层,那么就看fork()底层的逻辑吧

fork底层的逻辑

在这里插入图片描述

提问

当fork()执行到return pid时进程(子进程)是否创建完毕??

当然是创建完毕不然哪里来的pid呢,那么当他返回pid的时,那么就会出现一个问题,那么就是父子进程的数据,代码是共有的,因为进程之间是相互独立的那么这里就会发生写时拷贝,所以这里返回值不同,且子进程是看不到(执行不到fork()前包括fork()的代码)

如图所示:

在这里插入图片描述

写实拷贝的作用???

  1. 保证父子进程的独立性
  2. 节省系统内存资源(子进程不一定会修改父进程的数据)
  3. 提高fork的成功率

解释

或许1,2俩点都好理解但3为啥会提高效率呢?因为fork是向os申请资源的创建进程,假如没有写实拷贝,那么确保进程的独立性,就会为子进程开辟一块空间,申请资源越多则失败的几率越大哦




进程的终止

一个进程的退出方式

  1. 正常运行到return,或者exit,_exit
  2. 代码逻辑有问题,运行崩溃
  3. 外部信号终止进程(后面信号博客在说目前就是 kill -9 )

被称为学C,C++时的众多谜团之一(return 0 到底return 给了谁)

retuen 0 ,其实是在程序退出码,且这个是个父进程看的,父亲进程要知道子进程的退出情况(也可以不用知道)

如果我也想退出码咋办?

需要在命令上输入 echo $?,就可以获得最近一次的退出码

在这里插入图片描述

知识补充

计算机善于处理的是数字,但人擅长处理的是字符串,数字与字符之间对应的关系(人为的规定) 如图所示:

在这里插入图片描述


正常的退出的方式

  1. return
  2. exit
  3. _exit

return 与eixt的区别

return 是用于函数的结束,只有在main函数的时候才会让程序退出,但是exit与_exit不管在程序的那个位置只要执行到这个语句程序就会退出

exit 与 _exit的区别

exit 会做后续工作而_exit不会,后续工作(调用析构函数,刷新流到显示器上……)如代码所示:


退出码的的作用

其实可以看做assert 当作一个预判,哪里逻辑错了就可以直接终止




进程等待

子进程父进程没有回收资源的话子进程就是一个僵尸进程,会占用系统资源,那么等待就是处理僵尸进程的

进程等待函数

  1. wait
  2. waitpid

接口介绍

在这里插入图片描述


阻塞与非阻塞

阻塞没有可以过多的介绍,毕竟在生活中也是时常会发生(堵车),但是非阻塞却有些不同,就可以理解定期抽查,不会卡在哪里

非阻塞运行图:
在这里插入图片描述

不难看出这就是一个循环的过程,父进程定期去查看子进程的状态,完成就继续执行自己代码或者结束进程 (类似你爸爸叫你好好写作业,害怕你玩游戏就定期过来看一下

代码:
在这里插入图片描述

结果显而易见,阻塞式等待不会执行waitpid后面的代码,而非阻塞会和子进程并发执行


获取退出码(status)

status是int类型的,但是只有低16位为有效位 如图所示:

在这里插入图片描述

获取退出码的方式

//位运算
cout<<(status>>8)& 0xff

//宏
WEXITSTATUS(status)

获取终止信号的方式

//位运算
cout<<status & 0x7f;

//宏
WIFEXITED(status);

问:

如果被信号所杀那么进程的退出码还重要吗?

不重要,因为程序都没有正常执行完,那么他的退出码又啥意义呢?是吧




进程替换

一般fork()后你想子进程一起执行父进程的代码,其实意义不大,还有一种就是执行其他进程的代码,那么就要使用exec函数进行程序替换


exec系列的接口
在这里插入图片描述

在这里插入图片描述

  • l=list (列表)
  • v=vector (数组)
  • p=path(环境变量)

替换案例:
在这里插入图片描述

问:

为啥haha~~没有打印了呢???

exec系列的函数是程序替换,那么就是直接把数据和代码全部替换,那么之前的代码当然看不到了

如图所示:
在这里插入图片描述




内存池

        在语言层面上,如c,c++中,如果是就申请几字节,不频繁申请的话那还好。但是总会有需要一下子申请巨大内存和频繁申请的情况所以才会有内存池。


生活中的例子(银行贷款)

假如你要开始创业,需要去贷款,你会是需要钱的时候去申请相对的钱,还是会先申请一笔大款,以防不时之需呢?其实人都是嫌麻烦的,能一次性搞定不会选择多次。


父进程等待子进程成功后,子进程的数据真的是被抹除了吗?

某种意义上来说是的,但是又不是,如果把这一块数据抹除会消耗很多系统资源,所以一般情况下是把数据设为无用,然后用一种数据结构链接起来,

如图所示在这里插入图片描述

结尾

这些就是本章的全部内容,谢谢你的观看
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Legwhite/article/details/122987890