Linux进程概念:【环境变量】【程序地址空间】

目录

一.环境变量

1.1基本概念

1.2命令行参数

 1.3一个例子,一个环境变量

1.4环境变量的组织方式

1.5查看环境变量的方法

​编辑

 1.6从存储的角度理解环境变量

1.7环境变量最开始是从系统的配置文件里来的 

1.8认识更多的环境变量

HOME

HISTSIZE

HOSTNANE

SSH_TTY 

LS_COLORS 

OLDPWD 

1.9获得环境变量的方法

1.10代码获取环境变量 

方法一:

方法二:

 写一个只能自己执行的程序

 方法三:

 1.11补充

 二.程序地址空间

2.1地址空间回顾

2.2虚拟地址 

2.3进程地址空间

如何理解虚拟地址空间

如何理解区域划分

​编辑  

内核中: 

2.4虚拟内存管理

 2.5为什么要有虚拟地址空间

​编辑 一些问题


一.环境变量

1.1基本概念

• 环境变量(environment  variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数 

• 如:我们在编写C/C++代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪 里,但是照样可以链接成功,生成可执行程序,原因就是有相关环境变量帮助编译器进行查找。

• 环境变量通常具有某些特殊用途,还有在系统当中通常具有全局特性

1.2命令行参数

我们写的c语言代码一定要有main函数作为我们的入口函数,但其实main函数也是被调用的,它也有参数:

形成可执行文件之后: 

我们发现main函数的参数其实就是我们在命令行输入的字符串与字符串的个数,以空格为分界符。argv就是字符串数组。 

来看这样一个代码: 

所以我们就可以使用这个东西来实现不同的子功能 

 

是不是跟ls 所带的选型差不多:

所以,main的命令行参数,是实现程序不同子功能的方法 (指令选项的实现原理)

  

 1.3一个例子,一个环境变量

我们知道,要执行一个程序就必须先找到这个命令的位置。比如上面的代码我就必须加上“./”来指明程序所在的位置。而我们在使用ls的时候就不需要指明位置了,要知道我们自己写的代码翻译为二进制之后和我们系统预装的二进制文件是没有任何区别的。那么有一个方式可以让我们的代码也不需要我们自己指明位置就可以执行,像是ls不用写成/usr/bin/ls。

把我们的命令拷贝到/usr/bin/目录下: 

 但是为什么系统就可以认识/usr/bin/目录呢?因为一个环境变量:PATH(系统中默认的搜索指令的默认搜索路径)

1.4环境变量的组织方式

每个程序都会收到一张环境表,环境变量表是一个字符指针数组,每个指针指向一个以’\0’结尾的环境字符串  

1.5查看环境变量的方法

echo $NAME //NAME:你的环境变量名称

env //查看所有的

以冒号作为分隔符,分别对应路径 ,我们输入的指令就会从这里的路径里去查找

那么此时就有一个想法,我们是不是也可以把我们自己写的代码放到这里面去,那么我们在执行代码时就不需要写路径了:

注意看,PATH=$PATH:+(你要改的路径),如果直接PATH=(你要改的路径)就是直接替换

 1.6从存储的角度理解环境变量

bash内部有两张表!

在每一个用户登录系统的时候,系统都会创建一个bash,bash会帮我们形成一张表(环境变量表):

当我们输入指令的时候,bash会最先拿到我们的指令,然后会构建命令行参数表,再去我们的环境变量表里找到PATH。

1.7环境变量最开始是从系统的配置文件里来的 

在每个用户的家目录下们都会存在两个隐藏文件:

.bash_profile会加载.bashrc,而.bashrc会加载系统/etc/bashrc。

而我们上面说的如果更改了PATH,重新开启系统系统会恢复成默认的路径,那这个默认可以改吗?

如图在.bash_profile文件里的PATH后面加上我们自己的路径:

后面再去重新登录的话,默认的PATH就有了我们的路径 

1.8认识更多的环境变量

HOME

我们知道cd ~的意思就是回到家目录,那我们写的~代表的就是家目录?

当你输入cd ~时,shell会自动将~替换为$HOME的值,然后执行cd命令,将你切换到家目录。 

HISTSIZE

我们在命令行使用上下键可以看到以前的历史命令,HISTSIZE则是我们记录历史命令的最大值。

HOSTNANE

当前主机的主机名字

SSH_TTY 

这个哪一个终端设备

LS_COLORS 

配色方案

其实是一行太长了

OLDPWD 

这个会记录我们上一次的位置,所以我们使用cd -就可以回到上一次的工作目录

1.9获得环境变量的方法

1. echo:显示某个环境变量值 

2. export:设置一个新的环境变量 

3. env:显示所有环境变量

4. unset:清除环境变量

5. set:显示本地定义的shell变量和环境变量

export创建: 

unset取消:

1.10代码获取环境变量 

方法一:

我们还可以使用我们自己的程序获取环境变量(main函数的第三个参数):

所以环境变量可以被子进程继承 ,这也对应了上面说的全局特性

方法二:

getenv:

 

 写一个只能自己执行的程序

我们自己就可以执行: 

即使是root也不行: 

所以环境变量可以被子进程继承,我们就可以结合环境变量进行个性化操作

 方法三:

二级指针environ,指向全局变量表:

 1.11补充

我们可以直接在命令行里输入

这就是本地环境变量

我们直接使用env是查不到的,要使用set

bash会记录两套变量环境变量和本地变量,本地变量不会被子进程继承,只在bash内部使用。 


我们在命令行输入指令bash会创建子进程,而我们上面说的export可以创建环境变量,并且环境变量会进入到环境变量表里,这时就有问题了。bash创建子进程,但是子进程反过来修改了bash内部的环境变量表?

export是一个内键命令build-in command,比较特殊,它不需要创建子进程,而是让bash亲自执行,bash自己调用函数,或系统调用完成。

 二.程序地址空间

2.1地址空间回顾

进程地址空间(虚拟地址空间):是一个系统的概念不是语言层的概念(不是物理内存!!!)

用代码可以验证一下: 

 

上面说这不是内存,怎么体现呢? 

2.2虚拟地址 

一对父子进程: 

 

子进程的gval在改变,父进程的不变,它们的地址一样??这怎么可能?所以只有一种结论,这不是真正的地址,这是虚拟地址!! 

所以:

• 变量内容不一样,所以父子进程输出的变量绝对不是同一个变量 

• 但地址值是一样的,说明,该地址绝对不是物理地址!

• 在Linux地址下,这种地址叫做虚拟地址  

• 我们在用C/C++语言所看到的地址,全部都是虚拟地址!物理地址,用户一概看不到,由OS统一管理

OS必须负责将虚拟地址转化成物理地址 。

2.3进程地址空间

所以之前说‘程序的地址空间’是不准确的,准确的应该说成进程地址空间 ,那该如何理解呢?看 图:

• 上面的图就足矣说明问题,同一个变量,地址相同,其实是虚拟地址相同,内容不同其实是被映 射到了不同的物理地址! 

如何理解虚拟地址空间

我们可以把虚拟地址空间理解为操作系统给进程画的大饼,让每一个进程都以为自己有4GB的物理地址空间,每一个进程都认为自己在独占物理内存。

大饼:虚拟地址空间

员工:进程

老板:操作系统

要对大饼也进行管理,就需要先描述再组织的思想,所以虚拟地址空间本质上也是一个数据结构 

如何理解区域划分

  

对区域的调整实际上就值是对整数的调整:

内核中: 

2.4虚拟内存管理

描述linux下进程的地址空间的所有的信息的结构体是 mm_struct (内存描述符)。每个进程只有一个mm_struct结构,在每个进程的task_struct结构中,有一个指向该进程的结构。

struct task_struct
{/*...*/struct mm_struct *mm; //对于普通的用户进程来说该字段指向他的虚拟地址空间的⽤⼾空间部分,对于内核线程来说这部分为NULL。 struct mm_struct *active_mm; // 该字段是内核线程使⽤的。当该进程是内核线程时,它的mm字段为NULL,表⽰没有内存地址空间,可也并不是真正的没有,这是因为所有进程关于内核的映射都是⼀样的,内核线程可以使⽤任意进程的地址空间。 /*...*/
}

可以说,mm_struct结构是对整个用户空间的描述。每一个进程都会有自己独立的mm_struct,这样每一个进程都会有自己独立的地址空间才能互不干扰。先来看看由task_struct到mm_struct,进程的地址空间的分布情况:

那既然每一个进程都会有自己独立的mm_struct,操作系统肯定是要将这么多进程的mm_struct组织起来的!虚拟空间的组织方式有两种:

1. 当虚拟区较少时采取单链表,由mmap指针指向这个链表;

2. 当虚拟区间多时采取红黑树进行管理,由mm_rb指向这棵树。

linux内核使用 vm_area_struct 结构来表示一个独立的虚拟内存区域(VMA),由于每个不同质的虚 拟内存区域功能和内部机制都不同,因此一个进程使用多个vm_area_struct结构来分别表示不同类型的虚拟内存区域。上面提到的两种组织发那个式使用的就是vm_area_struct结构来连接各个VMA,方便进程快速访问。 

所以在task_struct里面有一个指向mm_struct的指针mm,在mm_struct里面还有一个指针指向vm_area_struct。vm_area_struct 是记录了每一个区域的结构体,链表的节点有多个这样的结构体组成,这也就解释了堆区不连续的问题。

 

 

 2.5为什么要有虚拟地址空间

这个问题其实可以转化为:如果程序直接可以操作物理内存会造成什么问题?

在早期的计算机中,要运行一个程序,会把这些程序全都装入内存,程序都是直接运行在内存上的, 也就是说程序中访问的内存地址都是实际的物理内存地址。当计算机同时运行多个程序时,必须保证这些程序用到的内存总量要小于计算机实际物理内存的大小。

那当程序同时运行多个程序时,操作系统是如何为这些程序分配内存的呢?例如某台计算机总的内存大小是128M,现在同时运行两个程序A和B,A需占用内存10M,B需占用内存110M。计算机在给程序分配内存时会采取这样的方法:先将内存中的前10M分配给程序A,接着再从内存中剩余的118M中划分 出110M分配给程序B。

这种分配方法可以保证程序A和程序B都能运行,但是这种简单的内存分配策略问题很多。  

• 安全风险

        ◦ 每个进程都可以访问任意的内存空间,这也就意味着任意一个进程都能够去读写系统相关内存区域,如果是一个木马病毒,那么他就能随意的修改内存空间,让设备直接瘫痪。

• 地址不确定

        ◦ 众所周知,编译完成后的程序是存放在硬盘上的,当运行的时候,需要将程序搬到内存当中去运行,如果直接使用物理地址的话,我们无法确定内存现在使用到哪里了,也就是说拷贝的实际内存地址每一次运行都是不确定的,比如:第一次执行a.out时候,内存当中一个进程都没有运行,所以搬移到内存地址是0x00000000,但是第二次的时候,内存已经有10个进程在运行了,那执行a.out的时候,内存地址就不一定了

• 效率低下

        ◦ 如果直接使用物理内存的话,一个进程就是作为一个整体(内存块)操作的,如果出现物理内存不够用的时候,我们一般的办法是将不常用的进程拷贝到磁盘的交换分区中,好腾出内存,但是如果是物理地址的话,就需要将整个进程一起拷走,这样,在内存和磁盘之间拷贝时间太长,效率较低。

存在这么多问题,有了虚拟地址空间和分页机制就能解决了吗?当然! 

• 地址空间和页表是OS创建并维护的!是不是也就意味着,凡是想使用地址空间和页表进行映射, 也一定要在OS的监管之下来进行访问!!也顺便 ,包括各个进程以及内核的相关有效数据! 保护了物理内存中的所有的合法数据

• 因为有地址空间的存在和表表的映射的存在,我们的物理内存中可以对未来的数据进行任意位置 的加载!物理内存的分配和进程的管理就可以做到没有关系。 进程管理模块和内存管理模块就完 成了解耦合

        ◦ 因为有地址空间的存在,所以我们在C、C++语言上new,malloc空间的时候,其实是在地址空间上申请的,物理内存可以甚至一个字节都不给你。而当你真正进行对物理地址空间访问的时候,才执行内存的相关管理算法,帮你申请内存,构建页表映射关系(延迟分配),这是由操作系统自动完成,用户包括进程完全0感知!! 

• 因为页表的映射的存在,程序在物理内存中理论上就可以任意位置加载。它可以将地址空间上的 虚拟地址和物理地址进行映射,在进程视角所有的内存分布都可以是有序的。

 一些问题

我们可以不加载代码和数据,只有task_struct,mm_struct,页表

因为存在缺页中断,当查找页表的映射关系时并没有关于物理空间地址的映射,只有虚拟地址,OS此时会自动的加载代码和数据

创建进程先有 task_struct,mm_struct,页表还是先加载代码和数据

根据前面的,先有 task_struct,mm_struct,页表

如何理解进程挂起 

进程挂起其实就是内存空间不足的时候,会把暂时不用的进程的代码和数据重新返回磁盘的swap分区。这个过程实际就是页表的物理内存地址全部清空,把物理内存的代码和数据放到磁盘

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

医疗集群系统中基于超融合数据库架构的应用与前景探析

一、引言 1.1 研究背景与意义 随着医疗信息化的飞速发展,医疗数据呈爆炸式增长。从日常诊疗记录、患者病历,到各类医疗影像、检查检验数据等,海量信息不断涌现。据统计,医疗数据的年增长率高达 30% 以上 ,2025 年,全球医疗数据量将达到 2314 艾字节(EB)。如此庞大的数…

【leetcode100】从前序与中序遍历序列构造二叉树

1、题目描述 给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。 示例 1: 输入: preorder [3,9,20,15,7], inorder [9,3,15,20,7] 输出: [3,9,20,nul…

【CSS入门学习】Flex布局设置div水平、垂直分布与居中

水平平均分布 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title><style>…

【ARM】解决MDK在打开工程的时候提示CMSIS的版本不对问题

1、 文档目标 解决MDK在打开使用Compiler 6的工程的时候&#xff0c;提示CMSIS 的API版本过低的报错。 2、 问题场景 客户在Pack包中打开一个示例工程&#xff0c;打算熟悉一下对应芯片的功能和软件的功能&#xff0c;但是&#xff0c;打开软件后&#xff0c;在构建信息输出框…

PyCharm接入DeepSeek实现AI编程

目录 效果演示 创建API key 在PyCharm中下载CodeGPT插件 配置Continue DeepSeek 是一家专注于人工智能技术研发的公司&#xff0c;致力于开发高性能、低成本的 AI 模型。DeepSeek-V3 是 DeepSeek 公司推出的最新一代 AI 模型。其前身是 DeepSeek-V2.5&#xff0c;经过持续的…

【PyTorch][chapter 29][李宏毅深度学习]Fine-tuning LLM

参考&#xff1a; https://www.youtube.com/watch?veC6Hd1hFvos 目录&#xff1a; 什么是 Fine-tune 为什么需要Fine-tuning 如何进行Fine-tune Fine-tuning- Supervised Fine-tuning 流程 Fine-tuning参数训练的常用方案 LORA 简介 示例代码 一 什么是 Fine-tune …

动手学图神经网络(3):利用图神经网络进行节点分类 从理论到实践

利用图神经网络进行节点分类&#xff1a;从理论到实践 前言 在之前的学习中&#xff0c;大家对图神经网络有了初步的了解。本次教程将深入探讨如何运用图神经网络&#xff08;GNNs&#xff09;来解决节点分类问题。在节点分类任务里&#xff0c;大家往往仅掌握少量节点的真实…

云原生:构建现代化应用的基石

一、什么是云原生&#xff1f; 云原生是一种构建和运行应用程序的方法&#xff0c;旨在充分利用云计算的分布式系统优势&#xff0c;例如弹性伸缩、微服务架构、容器化技术等。云原生应用程序从设计之初就考虑到了云环境的特点&#xff0c;能够更好地适应云平台的动态变化&…

springboot3 集成 knife4j(接口文档)

提示&#xff1a;文章是集成 knife4j&#xff0c;而非 swagger2 或者 swagger3&#xff0c;效果如图 文章目录 前言一、添加依赖二、如何集成1.配置文件2.注解部分1.Tag2.Operation3.Parameter4.Schema 3.使用 总结 前言 提示&#xff1a;&#xff1a;大家在开发阶段&#xff…

基于单片机的智能小区门禁系统设计(论文+源码)

1总体架构 智能小区门禁系统以STM32单片机和WiFi技术为核心&#xff0c;STM32单片机作为主控单元&#xff0c;通过WiFi模块实现与手机APP的连接&#xff0c;构建整个门禁系统。系统硬件包括RFID模块、指纹识别模块、显示屏、按键以及继电器。通过RFID绑定IC卡、APP面部识别、指…

后盾人JS--闭包明明白白

延伸函数环境生命周期 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title> <…

The just sharing principle: advice for advice givers

原文 A while ago I wrote about how Only you know what’s best for your application. That’s because only you fully understand the context within which you are making technical decisions. Any advice need to filtered through that context in order to determi…

Charles 4.6.7 浏览器网络调试指南:HTTPS抓包(三)

概述 在现代互联网应用中&#xff0c;网络请求和响应是服务交互的核心。对于开发者和测试人员来说&#xff0c;能够准确捕获并分析这些请求&#xff0c;是保证系统稳定性和性能的关键。Charles作为一个强大的网络调试工具&#xff0c;不仅可以捕获普通的HTTP请求&#xff0c;还…

安装Office自定义项,安装期间出错

个人博客地址&#xff1a;安装Office自定义项&#xff0c;安装期间出错 | 一张假钞的真实世界 卸载PowerDesigner后&#xff0c;打开“WPS文字”时出现下图错误&#xff1a; 解决方法&#xff1a; 按“WinR”快捷键&#xff0c;打开【运行】框&#xff0c;在对话框中输入“re…

图漾相机搭配VisionPro使用简易教程

1.下载并安装VisionPro软件 请自行下载VisonPro软件。 VisionPro 9.0 /9.5/9.6版本经测试&#xff0c;可正常打开图漾相机&#xff0c;建议使用图漾测试过的版本。 2.下载PercipioCameraForVisionPro软件包 使用浏览器下载&#xff1a;https://gitee.com/percipioxyz/camport…

信息系统管理工程师第6-8章精讲视频及配套千题通关双双发布,附第14章思维导图

这一周发文少&#xff0c;不是我在偷懒&#xff0c;而是在和信管的视频及千题通关“”浴血奋战 &#xff0c;特别是第8章卡了我很久&#xff0c;因为内容实在太多&#xff0c;精讲视频估计都差不多4个小时了&#xff0c;还好终于在春节前拿下&#xff0c;提供给小分队的同学&am…

RNN实现阿尔茨海默症的诊断识别

本文为为&#x1f517;365天深度学习训练营内部文章 原作者&#xff1a;K同学啊 一 导入数据 import torch.nn as nn import torch.nn.functional as F import torchvision,torch from sklearn.preprocessing import StandardScaler from torch.utils.data import TensorDatase…

ui-automator定位官网文档下载及使用

一、ui-automator定位官网文档简介及下载 AndroidUiAutomator&#xff1a;移动端特有的定位方式&#xff0c;uiautomator是java实现的&#xff0c;定位类型必须写成java类型 官方地址&#xff1a;https://developer.android.com/training/testing/ui-automator.html#ui-autom…

算法每日双题精讲 —— 二分查找(寻找旋转排序数组中的最小值,点名)

&#x1f31f;快来参与讨论&#x1f4ac;&#xff0c;点赞&#x1f44d;、收藏⭐、分享&#x1f4e4;&#xff0c;共创活力社区。 &#x1f31f; 别再犹豫了&#xff01;快来订阅我们的算法每日双题精讲专栏&#xff0c;一起踏上算法学习的精彩之旅吧&#x1f4aa; 在算法的…

macOS使用LLVM官方发布的tar.xz来安装Clang编译器

之前笔者写过一篇博文ubuntu使用LLVM官方发布的tar.xz来安装Clang编译器介绍了Ubuntu下使用官方发布的tar.xz包来安装Clang编译。官方发布的版本中也有MacOS版本的tar.xz&#xff0c;那MacOS应该也是可以安装的。 笔者2015款MBP笔记本&#xff0c;CPU是intel的&#xff0c;出厂…