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

目录

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中的底行模式也可以进行相关操作

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

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

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

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

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


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

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


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

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

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


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

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

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

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

#include<iostream>    
#include<unistd.h>    
int main()    
{    
  pid_t ret=fork();    
  if(ret==0)    
  {    
    //子进程    
    std::cout<<"I am child:"<<getpid()<<" parent:"<<getppid()<<std::endl;    
  }    
  else if(ret>0)    
  {    
    //父进程    
    std::cout<<"I am parent:"<<getpid()<<" parent:"<<getppid()<<std::endl;                               
  }    
  else{    
    //创建失败    
  }    
  return 0;    
}    


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、孤儿进程

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

  • 6
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值