fork函数创建子进程&僵尸进程&孤儿进程详讲

目录

1、创建子进程

1.1 fork()

1.2 fork()的返回值

1.3、fork的原理

1.4既然父子进程的代码是相同的,那么子进程是从哪行代码开始执行的? 

1.5针对fork的返回值,让父子进程执行不一样的代码块(重点)

2、僵尸进程&僵尸状态

2.1什么是僵尸进程

 2.2我们模拟僵尸进程的状态

2.3原因

2.4僵尸进程的危害

2.5僵尸进程的解决方案:

2.6kill命令

3、孤儿进程

3.1什么是孤儿进程

3.2模拟代码:

3.3原因

3.4孤儿进程的退出信息由谁回收呢?

3.5孤儿进程有危害吗?


  • 1、创建子进程

    • 1.1 fork()

      • 首先他是一个系统调用函数fork函数创建子进程&僵尸进程&孤儿进程详讲_第1张图片
      • 作用:谁调用fork函数,调用成功之后,谁就创建出来一个子进程。
    • 1.2 fork()的返回值

      • 创建成功:(创建子进程成功之后他和父进程是抢占式执行的)
      • fork函数创建子进程&僵尸进程&孤儿进程详讲_第2张图片
        • fork会返回两次在父进程中返回一次,在创建的子进程中返回一次。
        • >0返回给父进程(返回子进程的pid)
        • ==0返回给子进程
      • 创建失败:
        • 返回-1
    • 1.3、fork的原理

      • 子进程拷贝父进程的PCB        
      • 父子进程代码共享(父子进程拥有的代码是一样的)
      • fork函数创建子进程&僵尸进程&孤儿进程详讲_第3张图片
      • 数据独有(各自有各自的进程地址空间)
      • 进程独立性:多个进程运行,需要独享各种资源,各自用有自己的进程地址空间,互相在执行的时候数据不会窜,互不干扰,即使两者的代码都一样。
    • 1.4既然父子进程的代码是相同的,那么子进程是从哪行代码开始执行的? 

      • 因为子进程是复制的父进程的PCB,此时父进程的PCB中程序计数器里保存的是fork执行的fork之后的下一条的汇编指令。所以子进程创建出来之后就会执行fork吓一条的命令。
    • 1.5针对fork的返回值,让父子进程执行不一样的代码块(重点)

      • fork函数创建子进程&僵尸进程&孤儿进程详讲_第4张图片
      • 那我们为什么要创建子进程并且让父子进程执行不同代码呢?
        • 因为在某些场景中我们的代码可能会让程序崩溃,一旦程序崩溃就可能影响重大所以我们创建出来子进程让子进程帮我们来执行这些危险的代码,父进程可以不影响继续维持业务。
      • 那么正常启动的进程他的父进程是谁呢?
        • 我们可以看到父进程也有它的父进程        
        • fork函数创建子进程&僵尸进程&孤儿进程详讲_第5张图片
        • 我们查看他的父进程,可以看到,他是由bash启动的,也就是说我们在终端中启动的进程都是由bash创建的子进程。

        • 所以我们就可以理解,bash为什么不执行我们写的代码呢?

        • 这是因为我们程序员写的代码可能有bug,可能会吧程序搞崩溃,所以就创建一个子进程来执行我们的代码。在我们启动程序时都要输入一个./mytest这里就是告诉bash我们的程序在哪里。通过./告诉我们的bash在当前目录。

  • 2、僵尸进程&僵尸状态

    • 2.1什么是僵尸进程

      • 子进程先于父进程退出, 子进程就会变成僵尸进程;
    •  2.2我们模拟僵尸进程的状态

    • fork函数创建子进程&僵尸进程&孤儿进程详讲_第6张图片
    • 我们运行之后查看子进程状态,可以发现已经变成僵尸进程
    • 2.3原因

    • 子进程在退出的时候,会告知父进程 (信号:后续会涉及到),父进程忽略处理,父 进程并没有回收子进程的退出状态信息,也就是说:
      • 子进程在退出的时候,会告诉父进程
      • 父进程也收到了来自子进程的通知
      • 父进程时忽略处理(不处理)
      • 导致子进程的退出状态信息,一直没有得到回收
      • 所以子进程在内核当中的PCB一直没有回收
      • 所以子进程就变成了僵尸进程(子进程的状态就是僵尸进程)
    • 2.4僵尸进程的危害

    • 子进程的PCB没有被释放,导致内存泄漏。
    • 2.5僵尸进程的解决方案:

      • 杀死父进程:杀死父进程后僵尸进程就会变成孤儿进程,然后被一号进程领养,状态信息被一号进程回收(不推荐)
      • 重启操作系统,重启操作系统所有进程都会被杀死然后重新启动。(不推荐)
      • 父进程进行进程等待(推荐)
    • 2.6kill命令

      • 可以终止一个进程
      • kill [pid]:普通终止
        • 我们对父进程使用kill命令fork函数创建子进程&僵尸进程&孤儿进程详讲_第7张图片
        • 可以看到就是普通终止
        • kill -9 [pid]:强杀
        • 对父进程使用kill-9
        • fork函数创建子进程&僵尸进程&孤儿进程详讲_第8张图片
        • 可以看到进程被杀死
        • fork函数创建子进程&僵尸进程&孤儿进程详讲_第9张图片
        • 对僵尸进程使用kill命令
          • 可以看到kill命令无法终止僵尸进程
          • fork函数创建子进程&僵尸进程&孤儿进程详讲_第10张图片
          • 对僵尸进程使用强杀,可以看到僵尸进程依然存在。
          • fork函数创建子进程&僵尸进程&孤儿进程详讲_第11张图片
        • 总结:程序员对于僵尸进程是无法用kiil命令杀死的。
  • 3、孤儿进程

    • 3.1什么是孤儿进程

      • 父进程先于子进程退出, 子进程就会变成孤儿进程
    • 3.2模拟代码:

    • 没有孤儿状态! ! ( 切记)
      • 我们让子进程不退出然后让父进程
      • fork函数创建子进程&僵尸进程&孤儿进程详讲_第12张图片
      • 让程序运行起来,我们可以发现在父进程还未退出的时候子进程的父进程的pid还是当前他的父进程,在他的父进程退出之后,子进程被1号进程领养。
      • fork函数创建子进程&僵尸进程&孤儿进程详讲_第13张图片
      • 什么是一号进程?
      • 操作系统启动的第一个进程,后续有许多进程是由该进程创建出来的,或者是由该进程的子孙创建出来的,做操作系统初始化的一些工作,操作系统就是一个软件(一堆代码)。
      • 如果你试着运行这个代码你就会发现,在子进程打印的同时你还可以在bash命令行输入命令进行操作,这是因为,当我们查看他的进程状态,发现是一个S。
      • fork函数创建子进程&僵尸进程&孤儿进程详讲_第14张图片
      • fork函数创建子进程&僵尸进程&孤儿进程详讲_第15张图片
      • 我们要想结束孤儿进程的话直接找到孤儿进程的进程号杀死即可。
      • fork函数创建子进程&僵尸进程&孤儿进程详讲_第16张图片
    • 3.3原因

    • 父进程先于子进程退出之后,既定回收子进程的父进程不在了,所以子 进程就变成孤儿了,所以称之为孤儿进程。
    • 3.4孤儿进程的退出信息由谁回收呢?

    • 由一号进程回收。
    • 3.5孤儿进程有危害吗?

    • 孤儿进程因为被1号进程收养所以没有危害。

都看到这里了,不如点个赞再走吧,这对我真的很重要!!!
fork函数创建子进程&僵尸进程&孤儿进程详讲_第17张图片

 fork函数创建子进程&僵尸进程&孤儿进程详讲_第18张图片

你可能感兴趣的:(linux,学习笔记,bash,开发语言)