• linux进程——fork()函数


    1、fork()函数简介

    (1)函数原型

    #include <sys/types.h>
    #include<unistd.h>
    
    pit_t fork(void)
    

    (2)功能

    • fork用于在已存在的进程中创建一个新的进程。
    • 创建的新进程我们称之为子进程,原进程我们称为父进程。

    (3)返回类型及返回值

    fork()函数的返回类型为 pid_t 类型,这时基本系统数据类型,它的实际类型是一个int类型。

    1)创建子进程成功,返回两次(父进程和子进程各返回一次,后面解释为什么返回两次):

    • 子进程返回0
    • 父进程返回新创建子进程的进程id(pid_t类型)。

    2)创建子进程失败,返回-1。

    2、fork 函数是如何创建一个子进程的

    内核为子进程创建了一个新的task_struct结构。子进程几乎是父进程的克隆体,它将获得父进程数据空间pc指针等资源的副本。

    父子进程虽几乎一样,但是仍有些差别,例如

    • process id 进程ID
    • 父进程ID
    • 子进程ID 等

    3、父子进程的具体在内存中的结构如下图所示

    在这里插入图片描述
    可以看出,父进程和子进程在物理内存中的代码段是共享的,但是堆栈内存是独立的( 图中只画出了栈内存,但是堆内存也是独立的)。

    4、调用fork函数一次,为什么返回两次?

    (1)返回两次的原因是:

    子进程复制时复制了父进程的堆栈段,也包括pc指针,而pc指针就是正要执行的程序,所以两个进程都停留在fork函数中,等待返回。因此fork函数会返回两次,一次是在父进程中返回,另一次是在子进程中返回,这两次的返回值是不一样的(fork 的两次返回是内核帮我们实现的)。

    (2)两次返回的区别

    fork被调用一次,但返回两次,子进程和父进程各返回一次,并且子进程里返回值是0,而在父进程里其返回值是子进程的进程ID。

    (3)两次返回有区别的原因

    函数返回时pid所在栈段被复制并填写了不同的返回值,也就是两个进程拥有不同的堆栈区,函数执行完成后,返回到各自栈区的值是不同的。

    5、fork出来的子进程,它和父进程执行的先后顺序?

    我们无法确定fork之后是子进程先运行还是父进程先运行,这依赖于系统的(schedule算法,即内核调度算法)实现。

    • 如果父进程先运行完,那么子进程就会变成孤儿进程。此时系统会遍历属于回收的父进程的子进程,并将这些进程交由init进程 来接管,init进程就成为它的父进程。
    • 如果子进程,在父进程结束前先结束,且父进程一直不退出。那么子进程就会变成僵尸进程

    6、 我们在写程序时,父进程死掉后,一般不让它退出,为什么?

    因为父亲死了,init进程就将会成为其子进程的父亲。为了避免init被塞进太多的进程,则需要父进程不退出。

    7、 为什么需要僵尸状态?

    因为子进程的退出状态很重要,它可以返回子进程的死亡状态。因为,只有回收了子进程的退出状态,才能清理僵尸状态进程的资源(代表进程的struct 结构)。

    8、新建一个进程的函数为什么起名为fork?

    fork 单词的中文意思是叉子,而新创建一个进程,就像是一个叉子。如下图:
    在这里插入图片描述

  • 相关阅读:
    蓝牙4.0BLE抓包(二) – 广播包解析
    蓝牙4.0BLE抓包(一)
    蓝牙4.0 BLE 广播包解析
    蓝牙学习笔记之实例广播数据的解析
    Android ConstraintLayout详解
    Android ConstraintLayout的基本使用
    使用EasyBCD完美实现Windows7与Linux双系统
    使用MbrFix.exe修复MBR分区表
    C#中的Delegate
    C# 设置程序开机自动运行(+注册表项)
  • 原文地址:https://www.cnblogs.com/lasnitch/p/12764154.html
Copyright © 2020-2023  润新知