进程概念[下]

news2025/1/18 7:38:51

一、 进程优先级

0x01 什么叫进程优先级

CPU资源分配的先后顺序

0x02 为什么要有进程优先级

因为资源不足,是分配资源的一种方式,优先权高的进程有优先执行权利

0x03 查看更加详细的进程信息

 ①运行代码

#include<iostream>    
#include<unistd.h>    
using namespace std;    
    
int main()    
{    
    while(1)    
    {    
      cout << "PID:" << getpid() << " " << "PPID:" << getppid() << endl;               
      sleep(1);    
    }    
    return 0;    
} 

 ②ps -al 查看更加详细的进程信息

③几个重要信息

UID : 代表执行者的身份
PRI :代表这个进程可被执行的优先级,其值越小越早被执行
NI :代表这个进程的 nice值,是优先级的一个修正数据,取值范围是 -20 19 ,一共 40 个级别

0x04 调整优先级

①运行程序
②输入top命令,输入r ,输入进程号
③输入nice值

 如果我们再进行一次调整会是什么样的呢?

 我们知道PRI(new)=PRI(old)+nice,但是为什么不是在90上再加5呢?

因为旧的优先级默认为80

0x05 nice值为何要是一个相对较小的范围呢?

因为优先级再怎么设置,也只能是一种相对的优先级,不能出现绝对的优先级,否则会出现很严重的饥饿问题,即某一个进程长时间得不到调度。而调度器的作用就是:较为均衡的让每个进程享受到CPU资源

0x06 小结

①系统进程数目众多,具有竞争性,而CPU资源只有少量,甚至只有1个,所以进程之间是具有竞争属性的。为了高效完成任务,更合理金正相关资源,便具有了优先级
②独立性: 多进程运行期间,互不干扰
③并行: 多个进程在多个CPU下同时运行
④并发: 多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进

二、环境变量

0x01 引入

./test,为什么用"./ " ?

因为要帮系统确认对应的程序在哪里

那为何系统的命令不用路径呢?

因为环境变量:指在操作系统中用来指定操作系统运行环境的一些参数
PATH : 指定命令的搜索路径

查看环境变量:

 0x02 那么我们可以不用./,就能将程序运行起来吗?

当然可以,我们可以将路径导入到环境变量中去(只要没有改配置文件,那么重启时就会恢复默认).

 三种方法:

①可以将程序test放入/usr/bin目录中
②如果想让导入的环境变量长期有效,可以在vim ~/.bash_profile中去修改
③export PATH=$PATH: 路径,将路径导入环境变量(建议)

0x03  HOME(常用环境变量)

HOME : 指定用户的主工作目录 ( 即用户登陆到 Linux 系统中时 , 默认的目录 )

0x04 SHELL (常用环境变量)

SHELL : 当前 Shell版本或者Shell命令,它的值通常是/bin/bash

0x05 与环境变量相关的命令

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

0x06 小结

①环境变量的本质是操作系统在内存或者磁盘文件中开辟的空间,用来保存系统相关的数据
②环境变量 = 变量名 + 变量内容
③系统上还存在一种变量,是与本次登录有关的变量,只在本次登录有效(本地变量)

④可以将本地变量导入环境变量(重启也会释放掉这个变量)

 三、main函数参数

0x01  argc&argv

#include<stdio.h>

int main(int argc,char* argv[])    
{    
  for(int i = 0;i < argc;i++)    
  {    
    printf("argv[%d] -> %s\n",i,argv[i]);    
  }     
  return 0;
} 
[wh@bogon lesson10]$ ./test -a -b -c -d
argv[0] -> ./test
argv[1] -> -a
argv[2] -> -b
argv[3] -> -c
argv[4] -> -d

 0x02 命令行参数的作用

 同一个程序我们可以给他带入不同参数的方式来让他呈现出不同的表现形式 ,即输入不同的选项呈现出不同的结果

#include<stdio.h>    
#include<unistd.h>    
#include<string.h>    
int main(int argc,char* argv[])    
{    
  if(argc != 2)    
  {    
    printf("Usage: %s -[a|h]\n",argv[0]);    
    return 1;                                                                                       
  }    
  if(strcmp(argv[1],"-h") == 0 )    
  {    
    printf("hello -h\n");    
  }    
  else if(strcmp(argv[1],"-a") == 0)    
  {    
    printf("hello all\n");    
  }    
  else    
  {    
    printf("hello world\n");    
  }    
}   

 

指令有很多选项,用来完成同一个命令的不同子功能,选项底层使用的就是我们的命令行参数

0x03 环境变量的组织方式

当然main函数的参数也可以是环境变量env

  #include<stdio.h>    
  #include<unistd.h>    
  #include<string.h>    
  int main(int argc,char* argv[],char* env[])    
  {    
      for(int i = 0;env[i]; i++)    
      {    
        printf("%d -> %s\n",i,env[i]);                                                              
      }   
   return 0; 
  }

当然也可以不用main函数的第三个参数的方式,查看环境变量,也可以通过第三方变量environ来获取


  #include<stdio.h>    
  #include<unistd.h>    
  #include<string.h>    
  int main(int argc,char* argv[])    
  {    
      extern char** environ;    
      for(int i = 0;environ[i]; i++)    
      {    
        printf("%d -> %s\n",i,environ[i]);                                                          
      } 
    return 0;
  }

0x04 getenv()

 用来获取环境变量

  #include<stdio.h>    
  #include<stdlib.h>    
  #include<string.h>    
  int main(int argc,char* argv[])    
  {    
      printf("PATH: %s\n",getenv("PATH"));    
      return 0;   
  }

 四、环境变量通常具有全局属性

0x01  启动进程的父进程是什么呢?

#include<stdio.h>    
#include<sys/types.h>    
#include<unistd.h>    
#include<string.h>    
int main()    
{    
  while(1)    
  {    
     printf("PID:%d,PPID:%d\n",getpid(),getppid());    
     sleep(2);                                                                                                                                                                                                     
  }    
  return 0; 
}

命令行上启动进程,父进程都是bash

0x02 环境变量是可以被继承的

 ①开始设置的my_env是本地变量,所以使用子进程./test找不到

 ②之后将其导入环境变量,既可以进行env查询,也可以通过./test查询
 ③可以说明,将my_env导成环境变量,其实是导给了bash中的列表
 ④而我们的子进程test就是继承父进程的环境变量,所以./test可以查询到此环境变量
 ⑤从而说明环境变量是可以被子进程继承的
小结:
 环境变量具有全局属性,可以被子进程继承下去,影响了整个用户系统

五、程序地址空间&进程地址空间

0x01 程序地址空间布局

  #include<stdio.h>    
  #include<stdlib.h>    
      
  int g_unval;    
  int g_val = 100;    
  int main()    
  {    
    const char* s = "hello world";    
    printf("code addr: %p\n",main);    
    printf("Character constant addr: %p\n",s);    
    printf("uninit addr: %p\n",&g_unval);                                                           
    printf("init addr: %p\n",&g_val);    
    char* heap = (char*)malloc(10);    
    printf("heap addr: %p\n",heap);    
    printf("stack addr: %p\n",&s);    
    printf("stack addr: %p\n",&heap);    
    int a = 10;    
    int b = 30;    
    printf("stack addr: %p\n",&a);    
    printf("stack addr: %p\n,%b");    
    return 0;    
  }  

 0x02 虚拟地址引入

#include<stdio.h>    
#include<stdlib.h>    
#include<unistd.h>    
    
int g_val = 100;    
    
int main()                                                                                                                                                                                                         
{    
  if(fork() == 0)    
  {    
    //child     
    
    int cnt = 5;    
    while(cnt)    
    {    
      printf("I am child,times: %d,g_val = %d,&g_val = %p\n",cnt,g_val,&g_val);    
      cnt--;    
      sleep(1);    
      if(cnt == 3)    
      {    
          printf("############child change before!##############\n");    
          g_val = 200;    
          printf("############child change  after!##############\n");    
      }    
    }    
  }    
  else    
  {    
    //parent    
    while(1)    
    {    
        printf("I am parent,g_val = %d,&g_val = %p\n",g_val,&g_val);    
        sleep(1);    
    }    
  }    
  return 0;    
}

从上述结果来看,因为写时拷贝,俩个进程互不干扰,所以当子进程修改值时,父进程并没有影响,但是我们也可以发现他们的地址是完全一样的。

但是地址怎么会没有变化呢?

如果C/C++打印出来的地址是物理内存的地址,这种现象可能存在吗?
当然不可能,所以我们使用的地址,绝对不是物理地址,即不是内存地址空间,而是进程虚拟地址空间
所以说,我们之前说的程序地址空间是有些不准确的,准确的应该说是进程地址空间
我们用c/c++语言所看到的的地址,全部都是虚拟地址,物理地址用户是看不到的,有操作系统统一管理,将虚拟地址转化成物理地址

 0x03 进程虚拟地址空间

①进程&操作系统

操作系统相当于大富翁
物理内存相当于大富翁的所有钱,可以看作大富翁的银行
进程地址空间相当于大富翁画的大饼
进程相当于大富翁的私生子

接下来,我们就可以将其串联起来:
假如大富翁有100亿,都存在银行中,大富翁给三个私生子都画了个大饼,因为私生子之间互不认识,所以大富翁说,你们每个人都可以使用100亿,所以私生子们就都在规划这100亿该怎么使用,而三人之间又互不影响,都认为自己独占100亿

这将其换成进程与操作系统就更加贴切了:
操作系统掌控着所有物理内存空间,给每一个进程都画了一个进程地址空间(独占物理内存)这样的大饼,而每个进程之间又互不影响,都认为自己独占物理内存

 此时又出现了一个问题:

② 每个进程都有一个地址空间,而系统中又存在大量的地址空间,那么操作系统应该怎样去管理这些地址空间呢?

先描述,再组织,而先描述其实用的是结构体mm_struct来描述地址空间
每个进程都认为mm_struct代表整个内存,都认为进程地址空间是按照4GB划分的

③那么我们该如何划分区域呢?

struct mm_struct
{
        unsigned int code_start;
        unsigned int code_start;
        .....
        unsigned int stack_start;
        unsigned int stack_end;
}

 地址空间上进行区域划分时,对应的线性位置虚拟地址

 ④为什么要有地址空间?

①通过添加一层软件层,完成有效的对进程操作内存进行风险管理(权限管理),本质目的是为了,保护物理内存以及各个进程的数据安全(如果进程直接和物理进程进行交互,那么怎么能保证这个进程不去访问或修改物理内存中不属于他的部分,所以增加地址空间可以对进程操作内存进行风险管理)

②将内存申请和内存使用的概念在时间上划分清除,通过虚拟地址空间,来屏蔽底层申请内存的过程,达到进程读写内存和操作系统进行内存管理操作,进行软件上面的分离(如果申请1000字节,进程其实是在地址空间上进行开辟的,但是当进程要使用这1000字节的空间,那么操作系统会让进程等一等,通过映射,在物理内存上申请好这1000字节的空间,而这样的申请也是基于缺页中断的物理内存的申请,然后再供进程进行使用)

③站在CPU和应用层的角度,进程可以看作统一使用4GB空间,而且每个空间区域的相对位置是比较确定的(程序的代码和数据可以被加载到物理内存的任一位置,因为页表可以通过映射,将地址空间上连续的地址,映射到物理内存中随意的位置,可以减少内存管理的负担)
 

操作系统这样设计的目的:每个进程都认为自己是独占系统资源的

⑤此时我们就可以解释一下为什么父子进程中值不同,但是地址相同的原因:

 


①因为子进程是以父进程为模板创建的,所以开始子进程物理地址也是指向父进程g_val位置,所以这也是前3秒,父进程和子进程打印的值相同的原因。

②之后子进程的值改成了200,又因为进程是具有独立性的,父进程与子进程之间互不干扰,所以此时就发生了写时拷贝,在物理内存中重新开辟了一块空间,给子进程进行使用,然后再重新进行虚拟地址与物理地址之间的映射(写时拷贝的原因)
③所以父进程与子进程打印的地址是一样的,是虚拟地址没有改变
④父子进程一般代码是共享的,此时就可以知道,都是通过映射关系,指向了同一块物理空间中的代码,所以只读的数据,一般可以只有一份,因为这是操作系统维护成本最低的

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

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

相关文章

Cesium 空间量算——方位角量测

文章目录 需求分析需求 实现对方位角的量测功能 分析 可以通过Cesium API提供的方法手动实现方位角测量。下面是一个可以帮助你开始实现方位角测量的代码示例: // 初始化Cesium Viewer var viewer = new Cesium.Viewer(cesiumContainer);// 创建材质

第六章redux的使用(餐饮版)

文章目录 一、redux的使用1、redux原理图解析 二、同步计算器案例2、创建src/redux/constant.js&#xff08;食材库&#xff09;3、创建src/redux/store.js&#xff08;厨房&#xff09;3-1、安装redux3-2、store.js 4、count_reducer.js&#xff08;厨师&#xff09;5、count_…

如何从SEO角度写好原创文章并吸引人

不会写原创文章的站长&#xff0c;不能算是好的站长哦。SEO原创文章对于网站优化来说&#xff0c;就像吃饭对于人的生存一样重要。如果一个SEO博客全是复制粘贴别人的文章&#xff0c;那这个博客还有多少意义呢&#xff1f;这就好比别人辛苦种田&#xff0c;你却轻易地把人家的…

Profinet转Modbus RTU网关连接PLC与多功能电表modbus通讯配置案例

Profinet是一种工业以太网通讯协议&#xff0c;广泛用于工业自动化系统中。而Modbus RTU是一种串行通信协议&#xff0c;常用于PLC和仪表之间的通讯。Profinet转Modbus RTU网关(XD-MDPN100)的作用就是将Profinet协议转换为Modbus RTU协议&#xff0c;从而实现PLC和多功能电表之…

zabbix-agnet连接zabbix-proxy

先配置好zabbix-proxy zabbix-proxy配置http://t.csdnimg.cn/RpaCI 在zabbix-proxy服务器上 [rootcloudserver ~]# grep ^[a-Z] /etc/zabbix/zabbix_agentd.conf PidFile/var/run/zabbix/zabbix_agentd.pid LogFile/var/log/zabbix/zabbix_agentd.log LogFileSize0 Server19…

Java 常用类(包装类)

目录 八大Wrapper类包装类的分类 装箱和拆箱包装类和基本数据类型之间的转换常见面试题 包装类方法包装类型和String类型的相互转换包装类常用方法&#xff08;以Integer类和Character类为例&#xff09;Integer类和Character类的常用方法 Integer创建机制&#xff08;面试题&a…

ims-ui项目搭建

node版本&#xff1a; npm版本&#xff1a; 创建vite项目&#xff1a; npm create vitelatest 使用的vite版本为&#xff1a; 安装router4,安装命令如下&#xff1a; npm install vue-router4 安装pinia&#xff0c;安装命令如下&#xff1a; npm install pinia 安装Pinia持…

SLAM从入门到精通(利用数据集来离线制图)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 前面我们的测试大部分都是基于仿真来实现的。但是很多时候&#xff0c;我们其实希还是望自己的算法能够跑在真实场景的数据上。可问题来了&#xf…

MinIO (二) .net core中实现上传下载

这篇文章里&#xff0c;我们介绍在.net core webapi项目中操作MinIO。 首先要创建一个桶&#xff0c;命名为demo 英文文档看不太顺畅&#xff0c;在网上找了一个api中文文档&#xff0c;可供参考 .NET Client API参考文档 - MinIO 帮助文档 - 开发文档 - 文江博客 创建桶 点…

偏偏不信文心大模型4.0比肩GPT-4!我为它们安排了一场龙虎斗!

作者 | 卖萌酱 大家好&#xff0c;我是卖萌酱。盲猜点进本文的不少小伙伴也看了昨天的百度世界大会&#xff0c;百度创始人、董事长兼CEO李彦宏官宣文心大模型4.0发布&#xff0c;其中一句话让卖萌酱印象深刻&#xff1a;文心大模型4.0综合水平与GPT-4相比已经毫不逊色&#xf…

python二次开发Solidworks:画砂轮

先根据输入参数计算出绘制砂轮需要的数据&#xff0c;然后绘制草图&#xff0c;完全标注后生成旋转体&#xff0c;具体代码如下&#xff1a; import sympy as sy import numpy as np import matplotlib.pyplot as pltx1,y1为第一条直线端点坐标(-10,0),theta_l1为角度,取5*np.…

C语言实现用弦截法求 f(x)=x^3-5*x^2+16*x-80=0 的根

完整代码: //用弦截法求 func(x)x^3-5*x^216*x-800 的根 //弦截法就是用函数上两点&#xff0c;连线的斜率近似代替f(x) //公式为Xn1Xn−(Xn−Xn−1)*func(Xn)/(func(Xn)−f(Xn−1))#include<stdio.h> #include<math.h>//求f(x)的值 double func(double x){return…

博客后台模块

一、后台模块-准备工作 1. 前端工程启动 前端工程下载链接 https://pan.baidu.com/s/1TdFs4TqxlHh4DXyLwYuejQ 提取码&#xff1a;mfkw 项目sql文件下载链接 链接&#xff1a;https://pan.baidu.com/s/1DQCGN4wISSDlOkqnVWYwxA 提取码&#xff1a;mfkw 命令行进入keke-vu…

工业4.0时代数字化工厂的几个特点

随着工业4.0时代的到来&#xff0c;数字化工厂成为了制造业的重要组成部分。数字化工厂管理系统是一种应用数字化、自动化和物联网等技术与产业融合的全新生产方式&#xff0c;旨在提高生产效率、降低成本、提升产品质量&#xff0c;并增强企业的核心竞争力。 数字化工厂的核心…

用友GRP-U8 SQL注入漏洞复现

0x01 产品简介 用友GRP-U8R10行政事业财务管理软件是用友公司专注于国家电子政务事业&#xff0c;基于云计算技术所推出的新一代产品&#xff0c;是我国行政事业财务领域最专业的政府财务管理软件。 0x02 漏洞概述 用友GRP-U8的bx_historyDataCheck jsp、slbmbygr.jsp等接口存…

链上房产赛道项目 ESTATEX 研报:以 RWA 的方式释放房产市场的潜力

在上个世纪初&#xff0c;随着全球人口的指数型增长以及城市化趋势加速&#xff0c;全球房地产行业逐渐进入到发展的爆发期与红利期。一方面人口的暴增与城市化进程的的加速&#xff0c;让住宅和商业房地产逐渐形成了刚需&#xff0c;另一方面全球经济飞速发展&#xff0c;让越…

Leetcode.4 寻找两个正序数组的中位数

题目链接 Leetcode.4 寻找两个正序数组的中位数 hard 题目描述 给定两个大小分别为 m m m 和 n n n 的正序&#xff08;从小到大&#xff09;数组 n u m s 1 nums1 nums1 和 n u m s 2 nums2 nums2。请你找出并返回这两个正序数组的 中位数 。 算法的时间复杂度应该为 O…

Pinia学习-存储数据、修改数据以及持久化实现

Pinia是什么&#xff1f; Pinia 是 Vue 的存储库&#xff0c;实现全局变量的定义 这里定义的变量信息&#xff0c;任何页面都可以使用&#xff0c;代替原来的VueX 官网&#xff1a;https://pinia.web3doc.top/ 4.2 Pinia存储数据 4.2.1获取存储数据 实现步骤&#xff1a;…

比例夹管阀及其高精度压力和流量控制解决方案

摘要&#xff1a;针对卫生和无菌流体系统中柔性管路内的压力和流量控制&#xff0c;本文介绍了采用电控夹管阀的高精度控制解决方案。解决方案基于反馈控制原理&#xff0c;采用压力传感器或流量传感器进行测量并反馈给程序控制器&#xff0c;控制器驱动夹管阀来改变柔性管路的…

双目视觉实战--单视图测量方法

目录 一.简介 二、2D变换 1. 等距变换&#xff08;欧式变换&#xff09; 2. 相似变换 3. 仿射变换 4. 射影变换&#xff08;透视变换&#xff09; 5. 结论 三、影消点与影消线 1. 平面上的线 2. 直线的交点 3. 2D无穷远点 4. 无穷远直线 5. 无穷远点的透视变换与仿…