【Linux】进程>环境变量地址空间进程调度

主页:醋溜马桶圈-CSDN博客

专栏:Linux_醋溜马桶圈的博客-CSDN博客

gitee:mnxcc (mnxcc) - Gitee.com

目录

1.环境变量

1.1 基本概念

1.2 常见环境变量 

1.3 查看环境变量方法 

1.4 和环境变量相关的命令

1.5 环境变量的组织方式

1.6 通过代码如何获取环境变量

1.6.1 命令行第三个参数

1.6.2 通过第三方变量environ获取

1.7 通过系统调用获取或设置环境变量

1.8 环境变量通常是具有全局属性的 

2.程序地址空间 

2.1 研究背景

2.2 程序地址空间回顾 

2.3 进程地址空间

3.Linux2.6内核进程调度队列

3.1 一个CPU拥有一个runqueue

3.2 优先级 

3.3 活动队列 

3.4 过期队列

3.5 active指针和expired指针

3.6 总结 


1.环境变量

1.1 基本概念

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

1.2 常见环境变量 

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

1.3 查看环境变量方法 

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

1.4 和环境变量相关的命令

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

1.5 环境变量的组织方式

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

1.6 通过代码如何获取环境变量

1.6.1 命令行第三个参数

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

1.6.2 通过第三方变量environ获取

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

libc中定义的全局变量environ指向环境变量表,environ没有包含在任何头文件中,所以在使用时 要用extern声明

1.7 通过系统调用获取或设置环境变量

  • getnev
#include <stdio.h>
#include <stdlib.h>
int main()
{
	printf("%s\n", getenv("PATH"));
	return 0;
}

  • 常用getenvputenv函数来访问特定的环境变量

1.8 环境变量通常是具有全局属性的 

  • 环境变量通常具有全局属性,可以被子进程继承下去
#include <stdio.h>
#include <stdlib.h>
int main()
{
	char* env = getenv("MYENV");
	if (env) {
		printf("%s\n", env);
	}
	return 0;
}

 

 直接查看,发现没有结果,说明该环境变量根本不存在

  • 导出环境变量
    export MYENV="hello world"
  • 再次运行程序,发现结果有了!说明:环境变量是可以被子进程继承下去的!

2.程序地址空间 

2.1 研究背景

  • kernel 2.6.32
  • 32位平台

2.2 程序地址空间回顾 

C语言的时候,有这样的空间布局图

可是我们对他并不理解

来段代码感受一下 

#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
		printf("child[%d]: %d : %p\n", getpid(), g_val, &g_val);
	}
	else { //parent
		printf("parent[%d]: %d : %p\n", getpid(), g_val, &g_val);
	}
	sleep(1);
	return 0;
}

输出结果:

//与环境相关,观察现象即可
parent[2995]: 0 : 0x80497d8
child[2996] : 0 : 0x80497d8

我们发现,输出出来的变量值和地址是一模一样的,很好理解呀,因为子进程按照父进程为模版,父子并没有对变量进行进行任何修改。可是将代码稍加改动:

#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;
}

输出结果:

//与环境相关,观察现象即可
child[3046]: 100 : 0x80497e8
parent[3045] : 0 : 0x80497e8比

我们发现,父子进程,输出地址是一致的,但是变量内容不一样!能得出如下结论:

  • 变量内容不一样,所以父子进程输出的变量绝对不是同一个变量
  • 但地址值是一样的,说明,该地址绝对不是物理地址!
  • 在Linux地址下,这种地址叫做 虚拟地址
  • 我们在用C/C++语言所看到的地址,全部都是虚拟地址!物理地址,用户一概看不到,由OS统一管理

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

2.3 进程地址空间

所以之前说程序的地址空间是不准确的,准确的应该说成 进程地址空间

说明:

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

3.Linux2.6内核进程调度队列

上图是Linux2.6内核中进程队列的数据结构

3.1 一个CPU拥有一个runqueue

  •  如果有多个CPU就要考虑进程个数的负载均衡问题 

3.2 优先级 

  • 普通优先级:100~139(我们都是普通的优先级,想想nice值的取值范围,可与之对应!)
  • 实时优先级:0~99(不关心)

3.3 活动队列 

  • 时间片还没有结束的所有进程都按照优先级放在该队列
  • nr_active: 总共有多少个运行状态的进程
  • queue[140]: 一个元素就是一个进程队列,相同优先级的进程按照FIFO规则进行排队调度,所以,数组下标就是优先级!

从该结构中,选择一个最合适的进程,过程是怎么的呢? 

  1. 从0下表开始遍历queue[140]
  2. 找到第一个非空队列,该队列必定为优先级最高的队列
  3. 拿到选中队列的第一个进程,开始运行,调度完成!
  4. 遍历queue[140]时间复杂度是常数!但还是太低效了!
  • bitmap[5]:一共140个优先级,一共140个进程队列,为了提高查找非空队列的效率,就可以用5*32个比特位表示队列是否为空,这样,便可以大大提高查找效率

3.4 过期队列

  • 过期队列和活动队列结构一模一样
  • 过期队列上放置的进程,都是时间片耗尽的进程
  • 当活动队列上的进程都被处理完毕之后,对过期队列的进程进行时间片重新计算

3.5 active指针和expired指针

  • active指针永远指向活动队列
  • expired指针永远指向过期队列
  • 可是活动队列上的进程会越来越少,过期队列上的进程会越来越多,因为进程时间片到期时一直都存在的
  • 没关系,在合适的时候,只要能够交换active指针和expired指针的内容,就相当于有具有了一批新的活动进程!

3.6 总结 

  • 在系统当中查找一个最合适调度的进程的时间复杂度是一个常数,不随着进程增多而导致时间成本增加,我们称之为进程调度O(1)算法 

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

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

相关文章

最“原始”的收音机长啥样?

同学们大家好&#xff0c;今天我们继续学习杨欣的《电子设计从零开始》&#xff0c;这本书从基本原理出发&#xff0c;知识点遍及无线电通讯、仪器设计、三极管电路、集成电路、传感器、数字电路基础、单片机及应用实例&#xff0c;可以说是全面系统地介绍了电子设计所需的知识…

vs code

vs code 下载安装 https://code.visualstudio.com/https://code.visualstudio.com/ 下载完后&#xff0c;下一步下一步就安装完了&#xff0c;安装好后可以下载各种好用的插件

【前端面试3+1】03深拷贝浅拷贝、let和var、css盒模型、【有效括号】

一、深拷贝浅拷贝 深拷贝和浅拷贝都是用于复制对象或数组的概念&#xff0c;但它们之间有着重要的区别&#xff1a; 1. 浅拷贝&#xff1a; 浅拷贝是指在拷贝对象或数组时&#xff0c;只会复制一层对象的属性或元素&#xff0c;而不会递归地复制嵌套的对象或数组。因此&#xf…

2024年第十二届计算机与通信管理国际会议(ICCCM 2024)即将召开!

2024年第十二届计算机与通信管理国际会议&#xff08;ICCCM 2024&#xff09;将2024年7月19-21日在日本鹿儿岛召开。会议由鹿儿岛大学主办。此次会议旨在为业界建立一个广泛、有效的交流合作平台&#xff0c;让我们及时了解行业发展动态、掌握最新技术&#xff0c;拓宽研究视野…

修改Jupyter Notebook的默认路径,以及在PowerShell中自定义其启动路径

修改Jupyter Notebook的默认路径&#xff0c;以及在PowerShell中自定义其启动路径 设置 Jupyter Notebook 配置文件&#xff0c;修改默认路径要在PowerShell中设置自定义的启动脚本&#xff0c;以确保Jupyter Notebook能够自动定位到当前路径设置后的效果 在使用Jupyter Notebo…

【C语言】编译和链接

文章目录 一、编译环境和运行环境二、翻译环境2.1 预处理2.2 编译2.2.1 词法分析2.2.2 语法分析2.2.3 语义分析 2.3 汇编2.4 链接 三、运行环境 一、编译环境和运行环境 在ANSIC的任何一种实现中&#xff0c;存在两个不同的环境。 第1种是翻译环境&#xff0c;在这个环境中源代…

C++ STL教程

C STL教程 文章目录 C STL教程1.1 std::vector1.1.1vector的定义1.1.2vector容器的初始化1.1.3vector容器内元素的访问和修改1.1.4vector中的常用函数 1.2 std::string1.2.1string的定义1.2.2string的初始化1.2.3string中元素的访问和修改1.2.4string中连接字符串1.2.5string中…

阿里云服务器安装MySQL(宝塔面板)

只写关键步骤 1. 创建一个云服务器实例 2 修改密码&#xff0c;登录服务器 3. 安装宝塔面板 进入https://www.bt.cn/new/index.html 进入宝塔面板地址 4. 安装Mysql 5. 创建数据库&#xff08;可导入数据库&#xff09; 6. 测试连接数据库 打开Navicat&#xff08;或其他数据…

[Qt] QString::fromLocal8Bit 的使用误区

QString::fromLocal8Bit 是一个平台相关的函数。默认情况下在 Windows 下 就是 gbk 转 utf-8 ,在 Linux就应该是无事发生。因为Linux平台默认的编码方式就是 utf-8 可以通过 void QTextCodec::setCodecForLocale(QTextCodec *c)来修改 Qt默认的编码方式。如下 第一输出乱码的…

DreamPolisher、InternLM2 、AniArtAvatar、PlainMamba、AniPortrait

本文首发于公众号&#xff1a;机器感知 DreamPolisher、InternLM2 、AniArtAvatar、PlainMamba、AniPortrait DreamPolisher: Towards High-Quality Text-to-3D Generation via Geometric Diffusion We present DreamPolisher, a novel Gaussian Splatting based method wit…

kubernetes负载均衡资源-Ingress

一、Ingress概念 1.1 Ingress概念 使用NodePort类型的Service可以将集群内部服务暴露给集群外部客广端,但使用这种类型Service存在如下几个问题。 1、一个端口只能一个服务使用,所有通过NodePort暴露的端口都需要提前规划;2、如果通过NodePort暴露端口过多,后期维护成本太…

中国土壤厚度空间分布数据

土壤层次分为覆盖层 林溶层 淀积层 母质层&#xff0c;其中在林溶层中的最上面那层就是我们通常说的土壤厚度在这一层中&#xff0c;这一层也被称为腐殖层&#xff0c;是肥力性质最好的一层&#xff0c;植物根系和微生物也集中在这一层。至于覆盖层在森林土壤中比较常见&#x…

【LeetCode: 2580. 统计将重叠区间合并成组的方案数 + 合并区间】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

计算机组成原理 3 运算器

定点补码加/减法运算 补码加减法的实现 补码加法 &#xff1a; [X &#xff0b; Y] 补 [X] 补 &#xff0b; [Y] 补 和的补码 补码的和 补码减法 &#xff1a; [X−Y] 补 [X] 补 &#xff0b; [−Y] 补 [X] 补 −[Y] 补 差的补码 补码的差 求补公式 &#xff1a; [−…

qemu快速入门

1.环境 win10系统上 -》 通过vmware装 -》 CentOS 7.4 -》装qemu虚拟出一台指定cpu的CentOS 7.9 2.安装基本命令 yum install -y net-tools yum install -y wget 3.安装基础依赖 yum groupinstall Development Tools -y yum groupinstall "Virtualization Host"…

MySQL数据库高级语句

文章目录 MySQL高级语句older by 排序区间判断查询或与且&#xff08;or 与and&#xff09;嵌套查询&#xff08;多条件&#xff09;查询不重复记录distinctcount 计数限制结果条目limit别名as常用通配符嵌套查询&#xff08;子查询&#xff09;同表不同表嵌套查询还能用于删除…

Redis中的客户端(一)

客户端 概述 Redis服务器是典型的一对多服务器程序:一个服务器可以与多个客户端建立网络连接&#xff0c;每个客户端可以向服务器发送命令请求&#xff0c;而服务器则接收并处理客户端发送的命令请求&#xff0c;并向客户端返回命令回复。通过使用由IO多路复用技术实现的文件…

C++ explicit隐式类型转换

单参数构造函数支持隐式类型的转换 什么意思&#xff1f; 简单来理解就是&#xff1a; 一个类对象的构造函数的参数只有一个&#xff0c;就可以直接进行赋值传参 例如构造函数的参数为int&#xff0c;且只有一个int 就可以直接将int类型的整型数据转换成类对象 也就是说从int类…

MySQL中的日历/时间/时间戳

一&#xff0c;日历 MySQL 使用通常所说的 proleptic 阳历。 每个将日历由朱利安改为阳历的国家在改变日历期间都不得不删除至少10天。 为了了解其运作&#xff0c;让我们看看1582年10月&#xff0c;这是由朱利安日历转换为阳历的第一次: 周一 周二 周三 周四 周五 周六…

海外媒体宣发:企业最牛出海最巨有“料”的几个新闻媒体

海外媒体宣发&#xff1a;企业最牛出海最巨有“料”的几个新闻媒体 1.雅虎财经&#xff08;Yahoo Finance&#xff09;雅虎网&#xff08;英文名字&#xff1a;Yahoo&#xff0c;NASDAQ&#xff1a;YHOO&#xff09;是美国有名的互联网技术门户网&#xff0c;都是20世纪初互联…