进程优先级+环境变量++地址空间+虚拟地址空间

news2024/11/18 19:35:20

索引

  • 一.进程优先级
  • 二.环境变量
      • 1.通过代码如何获取环境
        • 1.通过第三个命令行参数获得
        • 2.根据第三方变量environ获取
        • 3.通过系统调用获取环境变量
      • 2.验证环境变量可以被子进程继承下去
  • 三.验证地址空间
      • 1.验证程序地址空间
      • 2.证明地址空间不是物理地址
  • 四.虚拟地址空间
      • 虚拟地址空间存在的好处

一.进程优先级

什么是进程的优先级?
优先级是进程获取资源的先后顺序
为什么会存在优先级?
因为系统永远都进程占大多数,此时资源对应就很少,操作系统就需要根据进程的优先级来决定哪个进程先被执行,哪个进程后执行。
优先级如何表示?
PRI:表示这个进程可被执行的优先级,其值越小越早被执行
如何修改进程的优先级?
通过nice值修改,nice取值范围是-20 至 19
PRI(new) = PRI(old) + nice
因此在Linux下调整进程的优先级就是调整nice的值
在这里插入图片描述

二.环境变量

在这里插入图片描述
为什么系统的指令不用带路径,但我们自身的程序却每次都要带./表示运行当前程序的路径?
因为在Linux中,可以直接执行的指令通常是系统的内置命令,或者是已经在$PATH环境变量中定义的可执行文件,而这些命令或文件的路径已经被系统定义,运行这些进程的时候,可以直接在路径中个搜索,所以不用带./,但是我们编译后生成的二进制可执行文件默认不是在 $PATH中的,所以需要带路径。
所以什么是环境变量?

环境变量是一般是指在操作系统中用来指定操作系统运行环境的一些参数。
eg:我们在编写C/C++代码的时候,链接的时候,编译器会自动通过环境变量去帮我寻找动静态库的位置然后链接。

常见环境变量
PATH:定义可执行文件的搜索路径
HOME:指定主目录的路径
LANG:指定系统的语言
SHELL:指定用户的默认shell
PS1:定义shell提示符的格式

查看环境变量:env

在这里插入图片描述

显示PATH的内容:echo $PATH

在这里插入图片描述
在这里插入图片描述
我们所写的环境变量都是具有临时性的,系统重启之后又会重新恢复,为什么?涉及到环境变量的性质
在Linux系统中,环境变量是由shell进程管理的,当一个进程启动时,他会继承其父进程的环境变量,并可以在自己的环境变量中添加,删除或修改键值对。而系统每次重启,都会重新加载配置文件,bash会根据上下文导出环境变量,然后每次env就可以查看环境变量了,如果需要永久性修改,就修改配置文件,但不建议
在这里插入图片描述

1.通过代码如何获取环境

先了解什么是命令行参数?
指命令行中给的那个的参数
在这里插入图片描述
理解选项的含义
在这里插入图片描述
在这里插入图片描述

1.通过第三个命令行参数获得

argc:表示命令行参数的个数
argv:指向命令行参数的指针
env:指向环境变量(字符串)的字符指针

 #include<stdio.h>
W>  2 int main(int argc,char*argv[],char*env[])
    3 {
    4 
    5   int i = 0;                                                                                                                    
    6   for(i = 0;env[i];i++){
    7     printf("%s\n",env[i]);
    8   }
    9   return 0;
   10 }

2.根据第三方变量environ获取

 #include<stdio.h>
W>  2 int main(int argc,char*argv[])
    3 {
    4 
    5   extern char**environ;
    6   int i = 0;
    7   for(i = 0;environ[i];i++){
    8     printf("%s\n",environ[i]);
    9   }
   10   return 0;                                                                                                                     
   11 }
  ~

3.通过系统调用获取环境变量

 #include<stdio.h>
  2 #include<stdlib.h>                                                                                                                
  3 int main()
  4 {
  5   printf("%s\n",getenv("PATH"));
  6   return 0;
  7 }

2.验证环境变量可以被子进程继承下去

1 #include<stdio.h>
  2 #include<stdlib.h>
  3 int main()
  4 {
  5 
  6     char *env = getenv("MYENV");
  7     if(env){
  8       printf("MYENV = %s\n",env);
  9       printf("PATH = %s\n",getenv("PATH"));
 10     }                                                                                                                             
 11 //   printf("%s\n",getenv("PATH"));
 12   return 0;
 13 }
~

在这里插入图片描述
在bash导出MYENV后才可以打印出环境变量,而我们创建的进程自然就是bash的子进程,验证完毕

三.验证地址空间

先回答一个问题:程序地址空间是内存吗?不是,是进程的虚拟地址空间
之前了解过每一个程序其地址空间如图所示
在这里插入图片描述

1.验证程序地址空间

  7    printf("code addr           : %p\n",main);
  8   printf("init global addr    : %p\n",&g_val);
  9   printf("uninit global addr  : %p\n",&un_g_val);
 10   char*m1 = (char*)malloc(100);
 11   char*m2 = (char*)malloc(100);
 12   char*m3 = (char*)malloc(100);
 13   char*m4 = (char*)malloc(100);
 14   char*m5 = (char*)malloc(100);
 15   char*m6 = (char*)malloc(100);
 16   printf("heap addr           : %p\n",m1);
 17   printf("heap addr           : %p\n",m2);
 18   printf("heap addr           : %p\n",m3);
 19   printf("heap addr           : %p\n",m4);
 20   printf("heap addr           : %p\n",m5);
 21   printf("heap addr           : %p\n",m6);                                                                                        
 22   printf("statck addr         : %p\n",&m1);
 23   printf("statck addr         : %p\n",&m2);
 24   printf("statck addr         : %p\n",&m3);
 25   printf("statck addr         : %p\n",&m4);
 26   printf("statck addr         : %p\n",&m5);
 27   printf("statck addr         : %p\n",&m6);
 28   for(int i = 0;i < argc; i++)
 29   {
 30     printf("argc addr         : %p\n",argv[i]);
 31   } for(int i = 0;env[i];i++)
 33   {
 34     printf("env addr          : %p\n",env[i]);
 35   }

 

在这里插入图片描述

2.证明地址空间不是物理地址

#include<stdio.h>
  2 #include<unistd.h>
  3 #include<stdlib.h>
  4 int g_val = 100;
  5 int main()
  6 {
  7   pid_t id = fork();
  8   if(id == 0)
  9   {
 10     //child
 11     int flag = 0;
 12     while(1)
 13     {
 14       printf("我是子进程:%d,ppid:%d,g_val:%d,&g_val:%p\n\n",getpid(),getppid(),g_val,&g_val);
 15       sleep(1);
 16       flag++;
 17       if(flag == 5)
 18       {
 19         g_val = 200;
 20         printf("我是子进程,全局数据已经修改了,请注意查看!\n");
 21       }                                                                                                                           
 22     }
 23 
 24   }
 25   else
 26   {
 27       //parent
 28       while(1)
 29       {
 30         
 31          printf("我是父进程:%d,ppid:%d,g_val:%d,&g_val:%p\n\n",getpid(),getppid(),g_val,&g_val);
 32         sleep(2);
 33       }
 34   }
 35 
 36   return 0;
 37 }

在这里插入图片描述

由运行结果可知
当父子进程没有人修改数据的时候,父子是共享数据的,数据的值和地址显示也都是一样的,但是当子进程修改值后,发现打印出父子进程的地址显示还是一样的,得出一个结论:我们在C/C++中使用的地址,绝对不是物理地址,如果是物理地址,这种现象是不可能产生的。

既然地址空间不是物理地址,那是什么地址?是虚拟地址,是线性地址

四.虚拟地址空间

什么是虚拟地址空间?
虚拟地址空间是指每个进程独立的内存地址空间,是OS系统给每个进程分配给进程的,是虚拟的,相当于是OS给进程花了一个大饼,告诉每个进程我都有4g的空间可以让你使用,然后这个4g空间上有特定的位置存储特定类型的数据。
总结:每个进程都认为自己是独占系统中所有资源的,实际上每个进程根本用不了那么多资源,在虚拟地址空间和物理地址中间加一层映射就可以了,如何加映射?下面讲
每一个进程都会有自己的task_struct(进程控制块)控制调度进程,而在task_struct内部还有一个
指针struct mm_struct *指向进程的地址,其在源码中的部分结构在下面展示

在这里插入图片描述

每个虚拟地址空间都有自己对应的区域,区域的大小无非就是改变分界线的值罢了,不放猜测每个区域的范围,都是有对应的区域编号的,就好比是这样的

struct mm_struct{
	long code_satrt;
	long code_end;
	long init_start;
	long init_end;
	long uninit_start;
	long uninit_start;
	long heap_start;
	long heap_end;

在这里插入图片描述
两个问题:

  1. 程序被编译出来,没有被加载的时候,程序内部,有地址吗?

程序在被编译完成的时候,代码其实就有一套逻辑地址。

  1. 程序被编译出来,没有被加载的时候,程序内部,有区域吗?

磁盘中是有区域划分的,那么可执行程序在编译完成之后也是有区域划分的。

理解虚拟地址到物理地址的转化

  1. 编译程序的时候,虚拟地址就认为程序是按照0000~FFFF进行编译的
  2. 磁盘中是有区域划分的,那么可执行程序在编译完成之后也是有区域划分的,加载之后将内存中的代码和数据地址全部转化为我们认为的从0开始的地址,加载到内存后,操作系统会给每一个进程创建PCB,每一个PCB中都有一个指针指向进程地址空间,地址空间再经过映射到物理内存,映射到物理内存之后程序就开始读取你代码中的数据,但他读取你代码的时候,因为你的代码已经转化为虚拟地址,所以你的CPU读到全部的都是虚拟地址,然后再进过寻址转化的时候也一定会经过页表的转化转化成物理地址。
    在这里插入图片描述
    所以为什么此时地址一样,但是指向的内容却不一样?
    在这里插入图片描述

子进程的代码和数据基本上是继承自父进程的,所以最初父子进程的虚拟进场以及页表的映射都是一样的,但此时子进程修改了数据,此举可能会影响到父进程逻辑的运行以及判断,所以此时内存会重新开辟一段空间给子进程,并将原来的数据拷贝给子进程,子进程的虚拟地址是不变的,但是经过页表的映射所转化的物理地址发生了改变,因此会出现上述现象。

关于上述的现象称为写实拷贝:
如果父子进程中但凡有一个进程可能涉及到数据的修改,那么内存便会重新开辟一份内存并将数据拷贝,但此时修改的只是页表的映射关系,对应的虚拟地址是不会发生改变的。

虚拟地址空间存在的好处

  1. 保护内存,避免程序员直接接触物理内存,造成不可控的伤害
  2. 允许多个进程共享同一份代码和数据,节省资源,提高OS效率性能
  3. 让进程或者程序可以以一种统一的视角看待内存,方便以统一的视角看待内存,以统一的方式加载所有的可执行性程序

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

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

相关文章

BI财务智能分析,让企业管理更上一层楼

智能财务建设既可以看作是财务管理工作在经济社会数字化转型的全面开启&#xff0c;也可以看作是财务职能在以数字化技术为支撑&#xff0c;形成对内提升单位管理水平和风险管控能力、对外服务财政管理和宏观经济治理的会计职能拓展&#xff0c;究其本质则是在财务数字化转型升…

简单介绍之隔离级别与分布式事务

一&#xff0c;分布式系统与环境问题 概念 系统可以笼统分为集中式系统和分布式系统。 集中式系统就是由一台或多台主计算机组成中心节点&#xff0c;系统所有功能均由其集中处理。 分布式系统是硬件和软件组件分布不同的网络计算机上&#xff0c;彼此之间仅仅通过消息传递进…

植被参数光学遥感反演方法(Python)及遥感与生态模型数据同化算法技术应用

传统的地面实测方法能够得到比较准确的植被参数&#xff08;如叶面积指数、覆盖度、生物量、叶绿素、干物质、叶片含水量、FPAR等&#xff09;&#xff0c;但其获取信息有限&#xff0c;难以满足大范围提取植被参数的需求&#xff0c;尤其在异质地表区域。遥感技术的发展为植被…

C++学习day--07 字符串

1、黑客攻击系统-用户输入的优化 第 1 节 项目需求 1. 用户登录时&#xff0c;用户可能输入很长的用户名。 2. 使用 char 类型和 int 类型&#xff0c;表示用户名和密码&#xff0c;不安全。 第 2 节 项目实现 #include <iostream> #include <Windows.h> …

MacBook重置与推荐软件配置

Mac OS 12.6.5 前言重置初始化配置说明 GitJava 8 & Maven & MysqlJava 8mavenMySQL配置 MotrixDBeaver添加aliyun的maven至DBeaver添加MySQL VS CodeSteamTyporaiStas Menus 前言 用了一年的机械革命游戏本,机器加外设20斤的重量背过几次出门后就再也不想带出门了,运行…

PyYaml反序列化漏洞

0x01 HDCTF 遇到预期解是考的yaml了&#xff0c;前来学习下 语法 语法就不贴了&#xff0c;其他文章有介绍 语法和 yml配置文件的 语法差不多 就不一一介绍 漏洞成因与利用 PyYaml < 5.1 在python 中 pyyaml是提供 python 和Yaml 两种语言的转换&#xff0c;与pickle 类…

C++20协程

简介 ​ C20协程只是提供协程机制&#xff0c;而不是提供协程库。C20的协程是无栈协程&#xff0c;无栈协程是一个可以挂起/恢复的特殊函数&#xff0c;是函数调用的泛化&#xff0c;且只能被线程调用&#xff0c;本身并不抢占内核调度。 ​ C20 提供了三个新关键字(co_await…

【DRF配置管理】如何建立swagger风格api接口文档

原文作者&#xff1a;我辈李想 版权声明&#xff1a;文章原创&#xff0c;转载时请务必加上原文超链接、作者信息和本声明。 DRF应用和管理 【DRF配置管理】Django安装和使用DRF框架 【DRF配置管理】如何在视图函数配置参数(一) 【DRF配置管理】如何在视图函数配置参数(二) 【…

C. Enlarge GCD(内存的限制 + 数组的访问速度)

Problem - C - Codeforces Mr. F 有 n 个正整数 a1,a2,…,an。 他认为这些整数的最大公约数太小了。所以他想通过删除其中一些整数来扩大它。 但是这个问题对他来说太简单了&#xff0c;所以他不想自己做。如果你帮他解决这个问题&#xff0c;他会给你一些奖励分数。 你的任…

AntDB数据库携手金蝶Apusic应用服务器, 共促信创产业繁荣发展

日前&#xff0c;湖南亚信安慧科技有限公司&#xff08;简称&#xff1a;亚信安慧&#xff09;与深圳市金蝶天燕云计算股份有限公司&#xff08;简称&#xff1a;金蝶天燕&#xff09;完成AntDB数据库与金蝶Apusic服务器软件V9.0、V10产品的兼容互认&#xff0c;兼容性良好&…

不是吧,3 : 00 面试,还没10分钟就出来了,问的也太...

从外包出来&#xff0c;没想到死在另一家厂子 自从加入这家公司&#xff0c;每天都在加班&#xff0c;钱倒是给的不少&#xff0c;所以也就忍了。没想到2月一纸通知&#xff0c;所有人不许加班&#xff0c;薪资直降30%&#xff0c;顿时有吃不起饭的赶脚。 好在有个兄弟内推我去…

Android WebRtc+SRS/ZLM视频通话(3):安装ZLMediaKit

Android WebRtcSRS/ZLM视频通话&#xff08;3&#xff09;&#xff1a;安装ZLMediaKit 来自奔三人员的焦虑日志 接着上一章内容&#xff0c;继续来记录ZLMediaKit的安装&#xff0c;这里的ZLMediaKit实际上和SRS的功能差不多&#xff0c;都是国内流媒体服务框架使用人数比价多&…

【SpringBoot】MyBatis与MyBatis-Plus分页查询问题

笔者写这篇博客是因为近期遇到的关于两者之间的分页代码差距&#xff0c;其实之前也遇见过但是没有去整理这篇博客&#xff0c;但由于还是被困扰了小一会儿时间&#xff0c;所以还是需要加深记忆。其实会看前后端传参解决这个问题很快、不麻烦。关于这两个框架的分页代码问题主…

物联网|整体介绍|蓝牙4.0BLE信道分析与拓扑分析|物联网之蓝牙4.0 BLE基础-学习笔记(1)

文章目录 课程整体介绍1、蓝牙4.0自身的优点2、开设这门课的重要性3课程的总体规划4.课程目的5.培训对象 蓝牙4.0BLE信道分析与拓扑分析蓝牙4.OBLE信道分析柘扑分析星型拓扑结构:扮演角色广播结构;星型结构的建立过程: 课程整体介绍 为什么我们要开设这么课程呢? 1、蓝牙4.0…

JDK17新特性之--JDK9到JDK17 String 新增的新方法

JDK9之后对String底层存储数据结构进行了重大的修改1&#xff0c;同步也增加了许多新的方法&#xff0c;主要有Text Blocks、chars()、codePoints()、describeConstable()、formatted()、indent()、isBlank()、isEmpty()、lines()、repeat()、strip()、stripLeading()、stripIn…

判断大小端的错误做法

这里不详细讲解大小端的区别&#xff0c;只讲解判断大小端的方法。 1.大端&#xff0c;小端的区别 0x123456 在内存中的存储方式 大端是高字节存放到内存的低地址 小端是高字节存放到内存的高地址 2.大小端的判断 1.错误的做法 int main() {int a0x1234;char c(char)a;if(…

CSS-Flex布局

01-标准流 标准流也叫文档流&#xff0c;指的是标签在页面中默认的排布规则&#xff0c;例如&#xff1a;块元素独占一行&#xff0c;行内元素可以一行显示多个。 02-浮动 基本使用 作用&#xff1a;让块元素水平排列。 属性名&#xff1a;float 属性值 left&#xff1a;…

全志H3-nanopi-duo2开发板GPIO驱动开发

1:获取对应开发板duo2的内核源码 从官网获取 [friendlyarm的nanopi-duo2](https://wiki.friendlyelec.com/wiki/index.php/NanoPi_Duo2/zh#.E5.AE.9A.E5.88.B6.E5.91.BD.E4.BB.A4.E8.A1.8C.E7.9A.84.E6.AC.A2.E8.BF.8E.E4.BF.A1.E6.81.AF.EF.BC.88.E6.96.87.E5.AD.97LOGO.EF.B…

使用开源项目管理系统 Redmine 的优缺点

redmine是什么软件&#xff1f;Redmine是一款基于Ruby on Rails框架开发的开源项目管理软件&#xff0c;具有丰富的功能和高度可定制性。主要功能包括项目管理、问题跟踪、文档管理、时间跟踪以及多种报表。要安装使用Redmine&#xff0c;首先需要搭建Ruby on Rails运行环境&am…

网页和原生程序的交互方案

1 ActiveX和BHO是微软开发且闭源的&#xff0c;仅适用于IE 这里就不讨论了&#xff0c;这种方式会给用户带来很大的安全风险。而且也不符合html5标准&#xff0c;现在已经被市场抛弃。 2 搜索挂接&#xff08;URL SEARCHHOOK) 在window系统中&#xff0c;通过在注册表中&…