Linux-3 进程概念(三)

1.环境变量

1.1基本概念

环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数
如:我们在编写C/C++代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪里,但是照样可以链接成功,生成可执行程序,原因就是有相关环境变量帮助编译器进行查找。
环境变量通常具有某些特殊用途,还有在系统当中通常具有全局特性

环境变量彼此之间其实没有关系,一般是具有特殊用途的变量                                                       定义变量的本质,其实是开辟空间;在运行期间我们的程序也能开辟空间                                     操作系统/bash是用C语言写的程序,也可以在运行中开辟空间

1.2常见的环境变量

env 可以查看系统环境变量

  • PATH : 指定命令的搜索路径
  • HOME : 指定用户的主工作目录(即用户登陆到Linux系统中时,默认的目录)
  • SHELL : 当前Shell,它的值通常是/bin/bash。
  • USER:用户

1.3和环境变量相关的命令

  1. echo: 显示某个环境变量值
  2. export: 设置一个新的环境变量
  3. env: 显示所有环境变量
  4. unset: 清除环境变量
  5. set: 显示本地定义的shell变量和环境变量

set 可以查到几乎所有的变量 

当 PATH 的内容被覆盖之后 XShell断开登陆重新连接后 PATH又回到了默认了

登陆系统时,环境变量从磁盘中来(脚本或某些配置文件夹) 系统启动后环境变量从磁盘->内存 

所有的环境变量都是内存级的,在进程(bash)的上下文当中的                                                          当bash进程退出,环境变量自然就没了

1.4环境变量PATH

$PATH: 

 当我们 ls 显示当前路径文件时,和运行自己写的代码时,有没有想过:                                         为什么我们的代码运行要带路径,而系统的指令不用带路径?                                                           如果我们直接输入我们的可执行程序,会显示 bash: process: command not found

可以用echo查看PATH环境变量

 为什么系统命令(程序)“不用”绝对路径就能执行?                                                                           系统在环境变量PATH默认路径找,系统命令都能找到

 那么如何让自己的程序不用绝对路径就能用呢?                                                                               1.拷到默认搜索路径下(这就相当于把软件安装到系统里)                                                                   2.把程序所属路径添加到默认搜索路径下

pwd查看当前路径,把当前路径添加到环境变量中:export PATH=$PATH:路径

1.5获取环境变量

main函数有3个参数

前两个参数叫作命令行参数,第三个叫作环境变量参数。

  • 第一个参数:int argc是个整型变量,表示命令行参数的个数(含第一个参数)。
  • 第二个参数:char *argv[ ]是个存放字符指针的数组,每一个元素一个字符指针,指向一个字符串。这些字符串就是命令行中的每一个参数(字符串)。
  • 第三个参数:char *envp[ ]也是存放字符指针的数组,数组的每一个原元素是一个指向一个环境变量(字符串)的字符指针。
#include <stdio.h>    
#include <unistd.h>    
#include<stdlib.h>    
      
int main(int argc,char *argv[],char *env[])    
{    
  for(int i=0;env[i];i++)    
  {    
    printf("-----------env[%d]->%s\n",i,env[i]);                                                                                                                                                                
  }    
      
  return 0;    
}    

环境变量是当你 进入系统这个环境给你准备的变量

bash进程创建子进程时会帮我们维护两张表:命令行参数表、环境变量表(environ)

而这个表就是我们main函数的第三给参数char* env[]指向的表,环境变量可以被子进程继承下去

还可以用第三方变量environ获取

另外还能直接通过变量名获取环境变量

 

 2.进程地址空间

2.1引入

怎么理解这张图呢?

我们来验证一下

#include <stdio.h>    
#include <unistd.h>    
#include <stdlib.h>    
                                                                                                                                                                                                                  
int g_unval;    
int g_val = 100;                                         
int main()                                               
{                                                        
  printf("code addr:%p\n",main);                         
  printf("init data addr:%p\n",&g_val);//已初始          
  printf("uninit data addr:%p\n");                          
  char *heap = (char*)malloc(20);                           
  printf("heap addr:%p\n",heap);//堆                        
  printf("stack addr:%p\n",&heap);//栈                      
  return 0;                                      
}   

已初始化数据和未初始化数据会在进程运行期间一直存在

#include <stdio.h>    
#include <unistd.h>    
#include <stdlib.h>    
   
int main()    
{      
  char *heap1 = (char*)malloc(20);    
  char *heap2 = (char*)malloc(20);    
  char *heap3 = (char*)malloc(20);    
  printf("heap1 addr:%p\n",heap1);//堆    
  printf("heap2 addr:%p\n",heap2);    
  printf("heap3 addr:%p\n",heap3);    
  printf("stack1 addr:%p\n",&heap1);//栈    
  printf("stack2 addr:%p\n",&heap2);    
  printf("stack3 addr:%p\n",&heap3);                                                                                                                                                                              
  return 0;    
}  

 可以看出堆向上增长     栈向下增长

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int g_val = 0;
int main()
{
    pid_t id = fork();
    if(id < 0)
    {
        perror("fork");
        return 0;
    }
    else if(id == 0)
    { //child,子进程肯定先跑完,也就是子进程先修改,完成之后,父进程再读取
        g_val=100;
        printf("child[%d]: %d : %p\n", getpid(), g_val, &g_val);
    }
    else
    { //parent
        sleep(3);
        printf("parent[%d]: %d : %p\n", getpid(), g_val, &g_val);
    }
    sleep(1);
    return 0;
}

可以发现值不一样但是地址却是一样的   那么这个地址不可能是物理地址

我们所用到的所有的地址全都不是物理地址

所以刚才那个内存不是物理内存,叫进程地址空间

平时在用时访问的是地址空间的地址(虚拟内存),最终的数据是一定要存到物理内存当中的

那么地址空间怎么找到内存中的值呢?

引入一个区域划分的概念

为什么要进行区域划分?1.可以判断是否越界;2可以进行扩大或者缩小范围

区域划分的本质就是:区域内的各个地址都可以使用

可是我们的地址空间不具备对我们的代码和数据的保存能力,需要在物理内存中存放

需将地址空间上的(虚拟/线性)地址转化到物理内存中,系统给我们的进程提供一张映射表——页表

 

 回到刚才值不一样地址一样的问题:

每个进程都有task_struct、进程地址空间、映射关系,子进程也要有,而且子进程会继承父进程的地址空间、大部分属性、映射关系,所以会指向同一地址

那么值不一样是怎么修改的呢?因为进程是有独立性的(不能直接修改,会影响父进程)

子进程的值不一样改的是映射关系,同样的虚拟地址映射关系不同,那么指向的物理内存就不同     在物理内存重新开辟一块空间,修改映射关系指向这块空间

之前我们用id进行分流(为父/子进程)怎么可能一个id既大于0又等于0,就是同一个虚拟内存映射到不同的物理内存

2.2什么是进程地址空间

进程地址空间是指每个进程在计算机内存中所占用的地址空间。地址空间是指能被访问的内存地址 范围,它由若干个连续的内存块组成。每个进程都有自己的地址空间,这意味着每个进程都有自己 的内存地址范围,不会与其他进程冲突

系统给每个进程划分了很大的一块虚拟空间,所有的进程都认为自己会独占系统资源(实际上,这只是操作系统给进程画的饼)。等到进程真正申请的资源和空间的时候系统再到物理内存分配空间给进程

既然进程地址空间是一张”饼“,那么”饼“要管理吗?OS要不要堆地址空间做管理呢?自然是要的

怎么管理?先描述,再组织

所以进程地址空间的本质就是数据结构,具体到进程中就是特定数据结构的对象

2.3为什么要有地址空间+页表

地址空间:

1.进程地址空间会识别不安全的命令,并拒绝,可以阻止地址非法访问

2.通过页表将物理内存从无序变有序,让进程以统一的视角看内存(比如:正文区域,在物理内存申请的空间是一块一块的,通过页表可以把它们集中在正文区域)

3.进程地址空间的存在,可以更方便的进行进程和进程的数据代码之间的解耦合(减少模块与模块直接的关联性,以前说过开发要尽量:低耦合,高内聚)保证了进程的独立性

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【教学类-46-05】吉祥字门贴5.0(华光彩云_CNKI 文本框 空心字涂色 ,繁简都可以,建议简体)

作品展示 背景需求&#xff1a; 1、制作了空心字的第1款 华光通心圆_CNKI &#xff0c;发现它不能识别某些简体字&#xff0c;但可以识别他们的繁体字&#xff08;繁体为准&#xff09; 【教学类-46-01】吉祥字门贴1.0&#xff08;华光通心圆_CNKI 文本框 空心字涂色&#xf…

怎么把几百M大小的视频做成二维码?扫码播放视频在线教程

怎么把几百M大小的视频做成一个二维码展示呢&#xff1f;通过二维码来作为视频的载体是现在很常用的一种手段&#xff0c;通过这种方式不仅成本比较低&#xff0c;而且传播速度也比较快&#xff0c;通过访问云端数据就可以播放视频。 视频二维码生成的方法一般会通过二维码生成…

蓝桥杯----凑算式

这个算式中A~I代表1~9的数字,不同的字母代表不同的数字。 比如: 68/3952/714 就是一种解法, 53/1972/486 是另一种解法. 这个算式一共有多少种解法? 注意:你提交应该是个整数,不要填写任何多余的内容或说明性文字。

RPA财务机器人之UiPath实战 - 自动化操作Excel进行财务数据汇总与分析之流程建立与数据读取、处理、汇总、分析

一、案例介绍&#xff1a; A公司共有13个开在不同银行的帐户&#xff0c;分别用于不同的业务分部或地区分部收付款。公司总部为了核算每月的收支情况&#xff0c;查看银行在哪个月交易量频繁&#xff0c;需要每月汇总各个银行的帐户借方和贷方金额&#xff0c;并将其净收支&am…

springboot 拦截器

定义 拦截器类似于javaweb中filter 功能 注意: 只能拦截器controller相关的请求 作用 举一个例子&#xff0c;例如我们在Controller中都有一段业务逻辑&#xff0c;这样我们就可以都统一放在拦截器中 因此拦截器的作用就是将controller中共有代码放入到拦截器中执行,减少co…

Leetcode02.05:链表求和

一、题目描述 给定两个用链表表示的整数&#xff0c;每个节点包含一个数位。 这些数位是反向存放的&#xff0c;也就是个位排在链表首部。 编写函数对这两个整数求和&#xff0c;并用链表形式返回结果。 示例&#xff1a; 输入&#xff1a;(7 -> 1 -> 6) (5 -> 9 -…

UML之在Markdown中使用Mermaid绘制类图

1.UML概述 UML&#xff08;Unified modeling language UML&#xff09;统一建模语言&#xff0c;是一种用于软件系统分析和设计的语言工具&#xff0c;它用于帮助软件开发人员进行思考和记录思路。 类图是描述类与类之间的关系的&#xff0c;是UML图中最核心的。类图的是用于…

【MATLAB】交叉验证求光滑因子的广义神经网络回归预测算法

有意向获取代码&#xff0c;请转文末观看代码获取方式~也可转原文链接获取~ 1 基本定义 交叉验证求光滑因子的广义神经网络回归预测算法是一种用于选择模型超参数并提高泛化性能的方法。下面将对该算法进行详细介绍&#xff1a; 广义神经网络回归模型&#xff1a; 广义神经网络…

地下停车场智慧监查系统:科技让停车更智能

随着城市化进程的加速&#xff0c;停车难成为了许多城市居民的痛点。而地下停车场作为解决停车难问题的重要手段&#xff0c;其安全性和便捷性也成为了人们关注的焦点。为了解决这一问题&#xff0c;山海鲸可视化搭建的地下停车场智慧监查系统应运而生&#xff0c;为车主们提供…

单向循环链表——插入、删除、实现约瑟夫环、排序

2024年2月3日 1.请编程实现单向循环链表的头插&#xff0c;头删、尾插、尾删 自定义头文件&#xff1a; #ifndef __head_h__ #define __head_h__ #include<stdio.h> #include<stdlib.h> #include<string.h> typedef int datatype; typedef struct Node {da…

React进阶 - 15(React 中 ref 的使用)

本章内容 目录 一、e.target 获取事件对应“元素”的DOM节点二、ref三、ref 和 setState 合用 上一节我们了解了 React中的”虚拟DOM“中的”Diff算法““ &#xff0c;本节我们来说一说 React中 ref的使用 一、e.target 获取事件对应“元素”的DOM节点 打开之前工程中的 To…

摘录笔记——2024年2月5日

美团三年&#xff0c;总结的10条血泪教训在美团的三年多时光&#xff0c;如同一部悠长的交响曲&#xff0c;高高低低&#xff0c;而今离开已有一段时间。闲暇之余&#xff0c;梳理了三年多的收获与感慨&#xff0c;既是对过去一段时光的的一个深情回眸&#xff0c;也是对未来之…

XAI:探索AI决策透明化的前沿与展望

文章目录 &#x1f4d1;前言一、XAI的重要性二、为什么需要可解释人工智能三、XAI的研究与应用四、XAI的挑战与展望 &#x1f4d1;前言 随着人工智能技术的快速发展&#xff0c;它已经深入到了我们生活的方方面面&#xff0c;从智能手机、自动驾驶汽车到医疗诊断和金融投资&…

网桥与网关

文章目录 概要网桥网关联系与区别参考文章 概要 网桥和网关的理解 网桥 几个名词的概念 网关 联系与区别 参考文章 如何通俗地解释什么是网桥&#xff1f; 网关到底是什么求通俗易懂讲解? 网桥&#xff1a;网桥也叫桥接器&#xff0c;是连接两个局域网的一种存储/转发…

探索设计模式的魅力:外观模式简化术-隐藏复杂性,提供简洁接口的设计秘密

设计模式专栏&#xff1a;http://t.csdnimg.cn/U54zu 目录 引言&#xff1a;探索简化之路 一、起源和演变 二、场景案例分析 2.1 不用模式实现&#xff1a;用一坨坨代码实现 2.2 问题 2.3 外观模式重构代码 定义 界面 接口 利用外观模式解决问题步骤 外观模式结构和说明 重构…

07、全文检索 -- Solr -- Solr 全文检索 之 为索引库添加中文分词器

目录 Solr 全文检索 之 为索引库添加中文分词器添加中文分词器1、添加中文分词器的 jar 包2、修改 managed-schema 配置文件什么是 fieldType 3、添加 停用词文档4、重启 solr5、添加【*_cn】动态字段&#xff0c;并为该字段设置中文分词器6、演示分词器的区别演示 text_cjk 这…

智能优化算法 | Matlab实现飞蛾扑火(MFO)(内含完整源码)

文章目录 效果一览文章概述源码设计参考资料效果一览 文章概述 智能优化算法 | Matlab实现飞蛾扑火(MFO)(内含完整源码) 源码设计 %%%% clear all clc SearchAgents_no=100; % Number of search ag

【技能树学习】Git入门——练习题解析

前言 本篇文章给出了Git入门技能树中部分的练习题解析&#xff0c;包括分支管理&#xff0c;Git标签&#xff0c;在Mac和Windows上使用GitVSCode的步骤。强调了git cherry-pick不直接支持从标签中选择提交&#xff0c;git tag -d只能删除本地标签&#xff0c;Mac系统的终端可以…

C/C++ 回调函数 callback 异步编程

一、C语言的回调函数 1.小试牛刀 #include <iostream> using namespace std; #include <memory> #include <stdlib.h>int add(int a, int b) {return a b; }void test01() {// 函数指针可以指向任何类型的函数&#xff0c;只要函数的参数列表和返回值类型…

单片机串口 奇偶校验 配置问题

一、问题描述 使用GD32单片机串口进行通信测试&#xff0c;单片机的串口配置的是偶校验(Even)、数据位为8、停止位为1、波特率为9600。串口测试软件用的格西烽火&#xff0c;软件的配置如下&#xff1a;   单片机通过串口和串口测试软件进行通信交互&#xff0c;软件收到的数…