首页 » JavaScript » 正文

fork()函数子进程复制了父进程的哪些东西?(未完待续)

发表于: PHP,JS,Golang,Shopify学习交流博客 – 咪啪咪啪的小木屋 · 2021-2-9 ·  582 views  ·  0 replies 

这是一篇整理的资料,内容来源于个人博客,如果内容有误,请留言,谢谢

子进程是父进程的副本,它拥有父进程数据空间、堆和栈的副本。 两个进程之间的副本是不共享的,它们只是数据一样,但父子进程共享程序的正文段。
资料参考:http://note.huangz.me/os/apue/chp8.html#

具体什么是数据空间,什么又是堆和栈,可以参考下面这篇文章:

可以看到一个可执行程序在存储(没有调入内存)时分为代码区,数据区,未初始化数据区三部分。
(1)代码区存放CPU执行的机器指令。通常代码区是共享的,即其它执行程序可调用它。代码段(code segment/text segment)通常是只读的,有些构架也允许自行修改。
(2)数据区存放已初始化的全局变量,静态变量(包括全局和局部的),常量。static全局变量和static函数只能在当前文件中被调用。
(3)未初始化数据区(Block Started by Symbol,BSS)存放全局未初始化的变量。BSS的数据在程序开始执行之前被初始化为0或NULL。
代码区所在的地址空间最低,往上依次是数据区和BSS区,并且数据区和BSS区在内存中是紧挨着的。
text段和data段在编译时已分配了空间,而bss段并不占用可执行文件的大小,它是由链接器来获取内存的。
bss段(未手动初始化的数据)并不给该段的数据分配空间,只是记录数据所需空间的大小。
data(已手动初始化的数据)段则为数据分配空间,数据保存在目标文件中。
数据段包含经过初始化的全局变量以及它们的值。BSS段的大小从可执行文件中得到 ,然后链接器得到这个大小的内存块,紧跟在数据段后面。当这个内存区进入程序的地址空间后全部清零。包含数据段和BSS段的整个区段此时通常称为数据区。
可执行程序在运行时又多出了两个区域:栈区和堆区。
(4)栈区。由编译器自动释放,存放函数的参数值,局部变量等。每当一个函数被调用时,该函数的返回类型和一些调用的信息被存储到栈中。然后这个被调用的函数再为它的自动变量和临时变量在栈上分配空间。每调用一个函数一个新的栈就会被使用。栈区是从高地址位向低地址位增长的,是一块连续的内在区域,最大容量是由系统预先定义好的,申请的栈空间超过这个界限时会提示溢出,用户能从栈中获取的空间较小。
(5)堆区。用于动态内存分配,位于BSS和栈中间的地址位。由程序员申请分配(malloc)和释放(free)。堆是从低地址位向高地址位增长,采用链式存储结构。频繁地malloc/free造成内存空间的不连续,产生碎片。当申请堆空间时库函数按照一定的算法搜索可用的足够大的空间。因此堆的效率比栈要低的多。
资料来源:https://www.cnblogs.com/zhangchaoyang/articles/1820787.html

用代码举例说明:

#include <stdio.h>
#include <stdlib.h>

int a=0; // a在全局已初始化 数据区

char *p1; // p1在BSS区(未初始化全局变量)

int main()
{

    int b = 1; //b为局部变量,在栈区

    char s[]="abd"; //s为局部数组变量,在栈区

    //"abc"为字符串常量,存储在已初始化数据区

    char *p1,*p2; //p1,p2为局部变量,在栈区

    char *p3="123456"; //p3在栈区,123456\0在已初始化数据区

    static int c=0; //c为局部(静态)数据,在已初始化数据区

    //静态局部变量会自动初始化(因为BSS区自动用0或NULL初始化)
    p1=(char*)malloc(10); //分配得来的10个字节的区域在堆区

    p2=(char*)malloc(20); //分配得来的20个字节的区域在堆区

    free(p1);

    free(p2);

    p1=NULL; //显示地将p1置为NULL,避免以后错误地使用p1

    p2=NULL;

    printf("%d, %s, %d, %s", b, p3, c, s);
    return 0;
}
«上一篇: :下一篇»

0 thoughts on “fork()函数子进程复制了父进程的哪些东西?(未完待续)”

  1. 还没有任何评论,你来说两句吧

Leave a reply