【linux 多进程并发】0201 Linux进程fork内存空间,父子进程变量内存地址居然是一样的

news2024/10/11 10:16:23

0201 Linux进程fork方式详解

专栏内容

  • postgresql使用入门基础
  • 手写数据库toadb
  • 并发编程

个人主页:我的主页
管理社区:开源数据库
座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物.

文章目录

  • 0201 Linux进程fork方式详解
  • 一、概述
  • 二、创建进程
    • 2.1 测试程序
    • 2.2 查看进程信息
  • 三、进程内存空间
    • 3.2 变量空间用例
    • 3.2 验证分析
  • 四、总结
  • 结尾

一、概述


在Linux系统中提供了多个创建进程的API接口,以不同的方式来创建进程,

比如fork, vfork, exe系列接口,还有clone,使用之前博文《linux 进程创建的五种方法fork/vfork/execv/clone》之中已经介绍,

本文对于常用的fork方式,从进程的内存空间,生命周期,资源管理等方面详细分析,有更深的理解,在设计并发任务时有更加清晰的架构选择。

二、创建进程


通过fork创建进程,经过fork调用之后,就非常有意思了,程序被分叉为两个进程了,形成了父子两个进程,而fork会在父子进程中返回不同的值。

在这里插入图片描述

在父进程中返回子进程的pid,而在子进程中返回值为0。

2.1 测试程序

下面我们写一个测试程序,通过前面介绍的查看进程的方法来看一下进程的情况。

/*
 * ex020101_fork.c
 */
#include <stdio.h>

#include <sys/types.h>
#include <unistd.h>

#include <errno.h>
#include <string.h>

int main(int argc ,char *argv[])
{
        int pid = -1;

        pid = fork();
        if(pid == 0)
        {
                // in child
                printf("here in child ,my pid is %d\n", getpid());
                sleep(10);
        }
        else if(pid > 0)
        {
                // in parent
                printf("here in parent, my pid %d, child pid is %d\n", getpid(), pid);
                sleep(10);
        }
        else
        {
                // error
                printf("fork error[%s]\n",strerror(errno));
        }

        return 0;
}

2.2 查看进程信息

事先打开两个终端,一个用于运行测试程序,一个用于查看进程信息。

  • 在终端一上运行程序。
[senllang@hatch ex_0201]$ gcc ex020101_fork.c -o ex020101
[senllang@hatch ex_0201]$ ./ex020101
here in parent, my pid 56657, child pid is 56658
here in child ,my pid is 56658

程序运行后,可以看到进入了父子进程中,分别打印了信息,之后为睡眠10秒的时间,如果来不及查看,可以调大时间。

  • 在终端二上查看
[senllang@hatch ex_0201]$ ps -ef|grep ex0201|grep -v grep
senllang   56657   55956  0 08:28 pts/0    00:00:00 ./ex020101
senllang   56658   56657  0 08:28 pts/0    00:00:00 ./ex020101

通过ps命令可以查看两个进程,第二列是PPID 父进程PID,第三列是当前进程的PID。

第一行是子进程,它的进程号为55956, 第二行为父进程,也就是主程序运行的进程,进程号为 56657, 它的父进程为当前的终端进程。

三、进程内存空间


内存空间在进程之间是完全独立的,通过fork创建的父子进程也是这样吗?

这里通过一组测试来看一下,在上面的例子中增加变量查看内存空间变化。

3.2 变量空间用例

在上一例子中,增加了全局变量和动态分配内存的变量,观察如下内容:

  • 分别在父子进程中查看它们的值和地址;
  • 修改变量的值,观察它们在父子进程中的变化;

3.2 验证分析

验证代码如下:

/*
 * ex020102_forkvar.c
 */
#include <stdio.h>

#include <sys/types.h>
#include <unistd.h>

#include <errno.h>
#include <string.h>
#include <stdlib.h>

#define MAX_PROMPT_LEN 64

int g_flag = 1;

int main(int argc ,char *argv[])
{
        int pid = -1;
        char *prompt = NULL;

        prompt = (char*)malloc(MAX_PROMPT_LEN);
        if(NULL == prompt)
        {
                printf("memory maybe not enogh.\n");
                return -1;
        }

        strncpy(prompt, "I am a starting process.", MAX_PROMPT_LEN);

        printf("g_flag:%d, addr:%p; prompt:%s , addr:%p\n", g_flag, &g_flag, prompt, prompt);

        pid = fork();
        if(pid == 0)
        {
                // in child
                printf("here in child ,my pid is %d\n", getpid());
                printf("[pid:%d] g_flag:%d, addr:%p; prompt:%s , addr:%p\n", getpid(), g_flag, &g_flag, prompt, prompt);
                g_flag = 2;
                free(prompt);
                prompt = NULL;

                sleep(10);
        }
        else if(pid > 0)
        {
                // in parent
                printf("here in parent, my pid %d, child pid is %d\n", getpid(), pid);
                printf("[pid:%d] g_flag:%d, addr:%p; prompt:%s , addr:%p\n", getpid(), g_flag, &g_flag, prompt, prompt);

                sleep(10);
        }
        else
        {
                // error
                printf("fork error[%s]\n",strerror(errno));
        }

        printf("[pid:%d] g_flag:%d, addr:%p; prompt:%s , addr:%p\n", getpid(), g_flag, &g_flag, prompt, prompt);
        if(NULL != prompt)
                free(prompt);
        return 0;
}

  • 运行结果

编译生成可执行文件

[senllang@hatch ex_0201]$ gcc ex020102_forkvar.c -o ex020102

运行测试程序

[senllang@hatch ex_0201]$ ./ex020102
g_flag:1, addr:0x60106c; prompt:I am a starting process. , addr:0x9372a0
here in parent, my pid 57198, child pid is 57199
[pid:57198] g_flag:1, addr:0x60106c; prompt:I am a starting process. , addr:0x9372a0
here in child ,my pid is 57199
[pid:57199] g_flag:1, addr:0x60106c; prompt:I am a starting process. , addr:0x9372a0
[pid:57198] g_flag:1, addr:0x60106c; prompt:I am a starting process. , addr:0x9372a0
[pid:57199] g_flag:2, addr:0x60106c; prompt:(null) , addr:(nil)

分析结果

在这里插入图片描述

从运行结果可以看到如下信息:

  • 父进程的PID为57198,而子进程的PID为 57199;
  • 全局变量 g_flag 的地址为 0x60106c, 而指针变量 prompt的地址为 0x9372a0;
  • 子进程中修改变量 g_flag 值为2 ,同时释放 prompt 指向的内存,并赋值为空;

可以看到一个有意思的现象,在子进程中,继承于父进程的变量地址,与父进程中的变量地址一模一样,值也一样;

而修改子进程中的变量值时,父进程并没有改变;

  • 子进程在创建时,会完全拷贝父进程的内存内容,所以它们有一模一样的内存部局;当然,这里为了加速创建性能,采用了写时拷贝的策略;
  • 我们看到的进程内存地址,其实是虚拟内存地址,它由基地址开始,所以每个进程的基址一样,使得父子进程中内存地址可能相同;
  • 虽然虚拟地址相同,实际对应的是不同的物理内存;
  • 在32位机器上,进程虚拟地址空间是4GB,而64位上就非常大了;

四、总结


在多任务并发编程中,使用多进程架构时,在使用fork创建的父子进程时,子进程得到与父进程相同的内存空间内容。

进程的内存空间由虚拟地址描述,在使用时会映射到物理地址。

结尾


非常感谢大家的支持,在浏览的同时别忘了留下您宝贵的评论,如果觉得值得鼓励,请点赞,收藏,我会更加努力!

作者邮箱:study@senllang.onaliyun.com
如有错误或者疏漏欢迎指出,互相学习。

注:未经同意,不得转载!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2204665.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

学习记录:js算法(五十七):二叉树中所有距离为 K 的结点

文章目录 二叉树中所有距离为 K 的结点思路一思路二 二叉树中所有距离为 K 的结点 给定一个二叉树&#xff08;具有根结点 root&#xff09;&#xff0c; 一个目标结点 target &#xff0c;和一个整数值 k &#xff0c;返回到目标结点 target 距离为 k 的所有结点的值的数组。&…

matlab002

新建工程test001 例如&#xff1a; 脚本&#xff08;Script&#xff09; 概念 脚本是一系列按顺序执行的 MATLAB 命令的集合。它就像是一个记录了你在命令行中输入的一系列指令的文件。用途 适用于简单的任务&#xff0c;例如数据处理、可视化等一次性的操作。例如&#xff0c…

重学SpringBoot3-集成Redis(四)之Redisson

更多SpringBoot3内容请关注我的专栏&#xff1a;《SpringBoot3》 期待您的点赞&#x1f44d;收藏⭐评论✍ 重学SpringBoot3-集成Redis&#xff08;四&#xff09;之Redisson 1. 添加 Redisson 依赖2. 配置 Redisson 客户端3. 使用 Redisson 实现分布式锁4. 调用分布式锁5. 为什…

Java 获取热搜并生成图片

效果图如下&#xff1a; 第一步获取热搜 public List<String> getHotNews4(Integer size) {if (size < 0 || StringUtils.isEmpty(size)) {return null;}try {//set 转listreturn new ArrayList<>(getHotNews(size));} catch (Exception e) {logger.error(&qu…

如何基于审批实现文件外发管控,阻断数据违规外流?

FTP可以说是实际中企业运用最广泛的文件传输方式&#xff0c;很多企业不仅内部传输文件使用FTP&#xff0c;在与外部合作伙伴协作时&#xff0c;也多采用FTP进行文件的外发和收取。例如半导体行业&#xff0c;默认的都是使用FTP进行文件外发&#xff0c;这时候&#xff0c;替换…

卷积神经网络细节问题及知识点

一、Batch Normalization Batch Normalization&#xff08;BN&#xff0c;批归一化&#xff09; 是深度学习中的一种技术&#xff0c;主要用于加速神经网络的训练过程&#xff0c;同时提高网络的稳定性和收敛速度。它通过对每一层的输出进行归一化&#xff0c;减少梯度消失和梯…

本地部署Docsify生成文档网站并实现公网环境远程访问

文章目录 前言1. 本地部署Docsify2. 使用Docsify搭建个人博客3. 安装Cpolar内网穿透工具4. 配置公网地址5. 配置固定公网地址 前言 本文主要介绍如何在Windows环境本地部署 Docsify 这款以 markdown 为中心的文档编辑器&#xff0c;并即时生成您的文档博客网站&#xff0c;结合…

ubuntu22.04 安装wine9.0 全网首发

wine官网推荐安装方式&#xff1a;https://gitlab.winehq.org/wine/wine/-/wikis/zh_CN/Debian-Ubuntu 博主按照这种方式是失败的&#xff0c;虽然开启了“低调上网”&#xff0c;貌似代理对于终端不起作用&#xff0c;后面会介绍替代方案&#xff0c;一样完美。 一、官网的安…

Pycharm里设置关于designer.exe以及pyuic5.exe的外部工具

文章目录 1.Pycharm与Pyuic5介绍(1)Pycharm(2)Pyuic5 2.Pycharm里设置外部工具(1)切换到外部工具(2)designer创建外部工具(3)pyuic5创建外部工具(4)使用designer和pyuic5 3.本章总结 1.Pycharm与Pyuic5介绍 (1)Pycharm Pycharm是专门用于python编程语言的编辑软件&#xff0c;…

QT的核心机制 对话框资源

案例 1、键盘按下w&#xff0c;s&#xff0c;a&#xff0c;d键分别为标签向上&#xff0c;下&#xff0c;左&#xff0c;右移动 鼠标按下获取本地坐标&#xff0c;全局坐标 鼠标双击获取本地坐标&#xff0c;全局坐标 鼠标移动获取本地坐标&#xff0c;全局坐标 让鼠标跟踪…

C语言 ——— oj题:有效的括号

目录 题目要求 代码实现 题目要求 给定一个只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff0c;] 的字符串 s &#xff0c;判断字符串是否有效 有效字符串需满足&#xff1a; 左括号必须用相同类型的右括号闭合。左括号必须以正确的顺序闭合。每个…

【靶点Talk】为什么联合用药喜欢用VEGF+VEGFR?

血管生成对肿瘤发生、发展的重要影响的发现&#xff0c;使肿管生成变为肿瘤研究的热点之一。今天给大家带来VEGF、VEGFR相关介绍&#xff0c;更多靶点科普视频请关注义翘神州B站和知乎官方账号。 1、VEGFR的“简历” VEGFR包括VEGFR-1、VEGFR-2和VEGFR-3。VEGFR-2可与多种VEGF…

leetcode hot100_part03_滑动窗口

滑动窗口是有一个基本的模版的&#xff0c;不要自己想当然哦~ 滑动窗口算法思想&#xff08;附经典例题&#xff09;_滑动窗口的思想-CSDN博客 滑动窗口也叫同向双指针&#xff1b;可以先看一下灵山视频&#xff1a;滑动窗口【基础算法精讲 03】_哔哩哔哩_bilibili 3.无重复字…

springboot如何自动生成mybatis映射文件、dao、pojo层文件?

背景&#xff1a;以前一直是直接cv一个项目中现成的xml文件&#xff0c;然后再去自己配置mapper等数据。自己准备做一个单独的例子试一下。 步骤1&#xff1a;在pom.xml文件中插入mybatis-generator插件&#xff0c;这里选的版本是1.3.2&#xff0c;然后指定的generator文件是在…

ChatGPT 4o with Canvas — 新特性详解

# ChatGPT 4o with Canvas — 新特性详解 最近猫哥也感受到 Canvas 的强大&#xff0c;顺手开了个会员体验了一天&#xff0c;今天给大家简单分享一下&#xff0c;有想体验的伙伴可以文末名片私信我哈&#xff01; 关键词&#xff1a; #ChatGPT4o #Canvas新特性 #AI写作工具 …

[论文笔记]DAPR: A Benchmark on Document-Aware Passage Retrieval

引言 今天带来论文DAPR: A Benchmark on Document-Aware Passage Retrieval的笔记。 本文提出了一个基准&#xff1a;文档感知段落检索(Document-Aware Passage Retrieval,DAPR)以及介绍了一些上下文段落表示的方法。 为了简单&#xff0c;下文中以翻译的口吻记录&#xff0c…

Best HTTP V3

Best HTTP是Unity的权威网络解决方案,专为需要多功能性和强大功能的开发人员而设计。它与Unity 2021.1及更高版本无缝兼容,提供无与伦比的跨平台支持,包括桌面、移动设备、UWP和Web浏览器。凭借其高级功能集,它超越了基本的HTTP请求,支持HTTPS、HTTP/2,并通过传统的回调、…

2024年10月11日历史上的今天大事件早读

1038年10月11日李元昊称帝&#xff0c;国号大夏&#xff0c;西夏建立 1086年10月11日北宋政治家、史学家司马光逝世 1889年10月11日英国物理学家焦耳逝世 1900年10月11日李鸿章开始与八国联军的艰难谈判 1937年10月11日淞沪战线大场之战爆发 1944年10月11日日军包围桂林 …

The 2024 ICPC Kunming Invitational Contest K. Permutation(交互 期望)

在知乎内查看 题目 思路来源 题解 首先特判n1的情况&#xff0c;其实也不用问 分治&#xff0c;假设当前解决到[l,r]&#xff0c;要递归的vector是x&#xff0c; 维护两个vector L、R&#xff0c;代表下一步要在[l,mid]和[mid1,r]分治的vector 每次将x random_shuffle后&a…

网络安全 IP地址防泄漏指南

IP地址作为每个上网人的“门牌标识号”&#xff0c;如果产生泄露&#xff0c;可能会导致个人行踪曝光、数据被窃取甚至遭受网络攻击&#xff0c;要防止IP地址不被窃取&#xff0c;我们可以尝试以下方法&#xff1a; 利用专用网络加强隐私保护 通过加密在公共网络上创建一条安全…