当前位置:   article > 正文

深入理解fork、进程状态(9)_fork进程

fork进程

目录

1、fork创建子进程

1、如何理解fork创建子进程

1、子进程的内核数据结构与代码和数据

2、如何让父子进程做不一样的事?

3、如何理解fork创建成功有两个返回值?

4、如何理解fork的返回值设置?

5、fork之后父子进程谁先运行?

2、进程状态

1、R状态

2、S状态和D状态

3、T状态、t状态

4、X状态、Z状态

5、孤儿进程


1、fork创建子进程

Linux中man fork,查看fork的相关信息

 注意:vim中的底行模式也可以进行相关操作

  1. #include<iostream>
  2. #include<unistd.h> int main()
  3. {
  4. fork();
  5. std::cout<<"hello file.c:"<<getpid()<<"hello parent:"<<getppid()<<std::endl;
  6. return 0;
  7. }

 从上述结果可以看到,fork之后的代码被执行了两次,接下来将深入理解fork。

1、如何理解fork创建子进程

1、子进程的内核数据结构与代码和数据

fork的本质是创建进程,意味着系统中多了一个进程,也就是多了与该进程相关的内核数据结构和该进程的代码和数据。


fork创建的子进程,它的代码和数据从哪里来?

默认情况下,子进程会继承父进程的代码和数据,子进程的内核数据结构task_struct也会以父进程为模板来初始化子进程的task_struct。


fork之后,子进程和父进程的代码是共享的,也包括fork之前的代码,只不过执行流已经到达fork,往后执行。

因为代码是不可以被修改的,所以父子代码就只有一份。(不可能说运行之后,原本往屏幕上个打印hello world,变成了打印其他内容,所以代码是不可被修改的)

对于数据:默认情况下也是共享的,当父或子对数据要进行修改时,会发生“写时拷贝”。因为进程之间具有独立性。


2、如何让父子进程做不一样的事?

从上面,我们已经知道了fork创建子进程,子进程的代码和数据从哪里来,以及父子进程要对数据进行修改时,会发生“写时拷贝”,问题来了,费这么大劲创建子进程就是为了让父子干一样的事?答案当然是否定的,如何让父子做不一样的事?

通过fork的返回值来完成,创建失败:返回值<0

                                        创建成功:给父进程返回子进程的pid,给子进程返回0

  1. #include<iostream>
  2. #include<unistd.h>
  3. int main()
  4. {
  5. pid_t ret=fork();
  6. if(ret==0)
  7. {
  8. //子进程
  9. std::cout<<"I am child:"<<getpid()<<" parent:"<<getppid()<<std::endl;
  10. }
  11. else if(ret>0)
  12. {
  13. //父进程
  14. std::cout<<"I am parent:"<<getpid()<<" parent:"<<getppid()<<std::endl;
  15. }
  16. else{
  17. //创建失败
  18. }
  19. return 0;
  20. }


3、如何理解fork创建成功有两个返回值?

fork是Linux中的系统调用接口,而Linux的内核是用C语言写的,所以fork就是一个C函数,如图:


4、如何理解fork的返回值设置?

因为父与子是1:n,给父进程返回子进程pid,是为了父进程更好的管理子进程。


5、fork之后父子进程谁先运行?

答:不确定。

2、进程状态

进程状态信息在task_struct里,也就是pcb中。

进程状态的意义:方便操作系统快速判断进程,完成特定的功能,比如调度,本质就是分类。

注意:S+,这个加号说明进程在前台运行,就是./myproc,如果要在后台跑,可以./myproc &

1、R状态

R状态——运行状态

问:R状态一定正在占有cpu吗?

答:不一定。一个进程是R状态,说明该进程已经放入运行队列中,随时可以被cpu调度。

2、S状态和D状态

当我们想完成某种任务时,任务条件不具备,需要进程进行某种等待,就是S和D。

 进程在运行的时候,有可能因为运行的需要,会在不同的队列中,在不同的队列里进程所处的状态是不一样的。

我们把从运行状态的task_struct交到等待队列中,称为挂起等待(阻塞)。

从等待队列放到运行队列,被cpu调度,称为唤醒。

S状态:浅度睡眠或者可中断睡眠(等待状态),休眠状态,Sleeping。

D状态:不可中断睡眠或者深度睡眠。如果进程处于D状态,不可被杀掉,操作系统也无权杀掉。

3、T状态、t状态

T(stopped):暂停。与S状态类似,S状态下进程相关的数据可能会更新。T状态是彻底的暂停,不会有数据的更新。

t(tracing step):追踪状态。类似于vs、gdb中的调试。、

4、X状态、Z状态

X(dead):死亡状态。回收进程资源=进程相关内核数据结构+代码和数据。

Z(zombie):僵尸状态。

僵尸状态是为了辨别进程退出,也就是死亡原因,获取进程退出信息(数据)(task_struct)。

当一个进程退出时,它的所有资源并不是立即被释放,而是先进入僵尸状态,系统将进程退出信息写在pcb中,供父进程或OS来读取。

5、孤儿进程

一个进程的父进程先于子进程一步退出,那么这个进程就会被操作系统领养——孤儿进程

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/210423
推荐阅读
相关标签
  

闽ICP备14008679号