Linux进程概念2

news2024/11/25 8:15:45

前言

1. Linux真实的调度算法

在这里插入图片描述
首先cpu中有一个叫做runqueue的东西,这个东西就是去弄进程的调度的,里面有很多东西,这里我们就写这些了

其中task_struct*这个数组指向的是140个元素,其中0~99就是系统默认的进程,后面的四十个才是我们用的,这也是为什么进程优先级只有四十的区间了

在这里插入图片描述
这个就是一个哈希桶

这里task_struct和nr_active和bit_map共同组成了一个结构体queue,然后这样的结构体还有两个,构成了一个数组,queue[0],queue[1],struct queueactive指向一个,expired指向另一个
active指向的那一个,就是正在运行的那一堆进程,运行完了,或者时间片到了,就运到expired,或者有新的也运到expired
其中nr_active是记录active里面的进程数量的
当nr_active为0时,才切换active为expired,然后继续运行
然后bit_map这个是位图,是用来看这些地方还有没有进程,不然挨着挨着遍历看有没有进程,速度有点慢
bit_map每个元素是int,然后int是32个比特位,这样325=160,就足以覆盖那140个了
遍历是否有进程的时候,就可以这样,先看一个int类型是否为0,为0就跳下一个,不为0,就把int的32个比特位挨着遍历,就知道哪里有进程了
在这里插入图片描述
一个arr元素,后面连着很多task_struct,然后task_struct中又是这样连的
在这里插入图片描述
task_struct里面有一个link,它只有两个指针,一个pre,一个next
通过这个来相连,然后通过局部的next指针,就可以访问其他属性了
(task_struct
)0->pre这个pre的偏移量x,然后真正的pre减去x就可以了

(task_struct*)(pre-x)->就可以访问了

2. 命令行参数

在这里插入图片描述
其实我们在写main函数的时候,还可以增加这两个参数
注意如果版本没有达到C99的话,是不能使用for里面定义变量的,
在这里插入图片描述
在$^的后面加上-std=c99就可以了

在这里插入图片描述
看这个我们就知道了,我们在输入命令的时候,有几个参数,argc就为几,空格与空格间为一个,然后这些命令会存在argv中,这也是为什么一个命令常常后面跟一些选项了,比如ls -l -a因为它就可以通过argv来进行不同的操作了

如果argc为0,那么就执行main()
不为0,就执行main(argc,argv)

3. 环境变量

除了前面两个参数,还可以加第三个参数
在这里插入图片描述

在这里插入图片描述
这就是环境变量,因为环境变量最后一个是以NULL结尾,所有可以这样干

在这里插入图片描述
或者命令行直接输入env,这样也可以查看环境变量

3.1 PATH

接下来我们来讲一下为什么我们要./test才能执行呢,为什么不可以直接test呢,这是因为,命令都是要去bin路径那里去找的,你输入test就是默认去bin找了,所有不行

所有的命令都是这样的,有一个默认的查找路径,就是PATH
如何查看PATH呢
在这里插入图片描述
第一种不行,因为会默认为打印这个PATH字符串
第二种就可以了
这就查找路径
每种路径之间用冒号分隔开

如何修改路径呢
在这里插入图片描述
直接PATH=就可以修改路径了
修改完之后,好多指令都不可以用了,但是还是有些可以用的

因为路径被全覆盖了,但是没有影响的,我们把机器关掉再打开,就和原来一样了

在这里插入图片描述

这样一来就覆盖不了了
而且还可以使用我们的程序,不用./,但是要注意一下,因为系统默认有test的指令,所有我们的还不行暂时

改一下名字就可以了

为什么一关掉xshell,路径就恢复了呢,因为这个PATH是内存级别的,所以你关掉程序就没了,只有文件级别的,关掉才会继续有

其实是这样的,shell里面有一个和环境变量相关的配置文件,一启动程序xshell,就才会去配置环境变量

所以我们只需要改配置文件,PATH就会不变了,关掉xshell也不会变

在这里插入图片描述
我们回到我们的家目录

在这里插入图片描述
注意这两个,这两个就是配置文件

在这里插入图片描述
在这里插入图片描述
在pash_profile中你就会发现,PATH就在这里面

修改就可以了,而且下次登陆还是一样的

3.2 USER

记得我们原来讲进程的时候说过,进程有一个属性就是uid,是用来看它是哪一个用户创建的
这是怎么判断的呢,其实也是环境变量,环境变量记录了uid
在这里插入图片描述
最底下有个USER=ck这个就是得到uid的来源,每个用户的环境变量都不同,uid也不同

3.3 HOME

在这里插入图片描述
在这里插入图片描述
我们切换用户,用户的HOME环境变量就变了说白了就是变成了家目录
HOME就是查看家目录

这些环境变量都是存在bash中的,bash也是一个进程,每个用户都有一个bash

然后这也是bash的工作路径,然后所有的进程都是bash进程的子进程,然后所以进程都会继承bash,所以说所有的进程的工作路径肯定都是属于bash的进程的工作路径的,都是在它里面的

在这里插入图片描述
这个是查看我们shell这个版本的

3.4 PWD

pwd是查看当前进程的路径的
在这里插入图片描述

3.5 getenv

在这里插入图片描述

在这里插入图片描述

getenv这个函数也可以获得环境变量,去搜索的,传入PWD字符串,然后就会返回PWD字符串对应的环境变量后面=的内容

在这里插入图片描述
注意如果没有找到的话就会返回NULL

3.6 LOGNAME

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

看些我们可以知道,USER和LOGNAME是一样的,su -会切换到超级用户,su也会切换到超级用户,两个的区别是什么呢,区别就是su不会改变环境变量,只会改变用户,su -就会切换环境变量
然后logout就会退出当前用户,返回上一次的用户,也会改变环境变量
logout对应su -,,,,su对应exit

3.7 OIDPWD

在这里插入图片描述

在这里插入图片描述
这个OLDPWD就是用来记录上一次的路径的,这也是cd -的实现原理

3.8 本地变量

环境变量其实就是一个具有全局属性的变量
因为所有的进程都会继承它,同样也会继承它的环境变量,所以所以进程都有一样的环境变量

而在命令行创建的本地变量,只属于bash,是无法被子进程继承的

在这里插入图片描述
i=10
这个i就是本地变量
echo $i这个不是打印i,而是打印i里面的内容

本地变量必须是什么=什么的形式

3.9 set

set就是用来显示我们的环境变量和本地变量的

在这里插入图片描述

3.10 export

这个就是用来直接把一个本地变量打入环境变量的

在这里插入图片描述
有两种打印方式

在这里插入图片描述

3.11 unset

这个就是用来删除某个环境变量的
在这里插入图片描述
这样里面就没有这两个环境变量

3.12 全局性

在这里插入图片描述

这个就是bash进程,这个是由操作系统创建的,它里面有几个表,有环境变量表,有命令行参数,还有本地变量

在这里插入图片描述

但是由它创建的子进程就没有本地变量表了,就不能使用本地变量了
只有打入了环境变量,才可以使用

3.13 environ

在这里插入图片描述
下面我们来介绍这个函数,不,这不是一个函数,这是一个指针,指向的是环境变量表,是一个二级指针

使用这个前要声明

在这里插入图片描述
在这里插入图片描述

就这样我们利用这个指针也可以访问环境变量了

4. 进程地址空间

4.1 现象

先看一个现象

在这里插入图片描述
在这里插入图片描述
看这个现象我们就有疑问了,因为以前说过,子进程和父进程的数据是各自有一份的,但是为什么会地址相同呢,这个就不科学了
其实这个根本不是物理地址,而是虚拟地址,如果是物理地址的话,肯定不科学啊

4.2 空间布局

在这里插入图片描述

正文代码就是放代码的地方

为什么有共享区呢,因为栈和堆是会变大的,栈向下扩展(函数调用),堆向上扩展(开辟空间)
在这里插入图片描述

在这里插入图片描述
内存是如何划分区间的呢,其实只需要记录那个区间的起始地址和末尾的地址就可以了

4.3 解释原因

在这里插入图片描述
先解释一下,task_struct中有一个指针,指向一个task_mm_struct结构体,这个结构体就是虚拟地址,它记录了每个物理地址区间的起始位置和末尾位置,这样就可以按照不同类型来存了

在这里插入图片描述
然后每次创建变量的时候就会在区间里面取一个地址,然后指向一个页表的东西,指向的就是页表的虚拟地址那一行,然后对应页表物理地址那一行才会去指向实际的物理地址

比如gval,task_mm_struct里面的虚拟地址0x1111,对应实际的物理地址0x1234

又因为子进程会继承父进程,会继承所有
task_struct会继承,task_mm_struct会继承,页表也会继承,也是一模一样的

如果不修改gval的话,继承过来,子进程的虚拟地址和父进程一模一样的,物理地址也是一样的,如果要修改的话,那么子进程就会修改物理地址,自己重新去指向一个空间,这就是写时修改

所以我们程序打印的是虚拟地址,所以才是一样的,但其实物理地址是不不一样的

所以这里我们完善一下,进程=内核数据结构+自己的代码和数据
内核数据结构包括task_struct+task_mm_struct+页表
因为每个东西基本都是各自有一份,所以是独立的,代码共享不影响独立,数据开始共享,修改的话就分开,所以很独立

4.4 页表

在这里插入图片描述
页表中,还有一些标志位,这里我们只举出两个

一个是对物理地址的读写权限

char *str="hello bit";
*str="H";

比如这个,我们这样写,编译阶段不会报错,但是进程运行的时候就会报错,这个是因为"hello bit"这个在已初始化区域,这个是只有读的权限,没有修改的权限,这里的报错是系统报错的

const char *str="hello bit";
*str="H";

这个就是在编译阶段就会报错了

接下来我们来讲一下第二个isexists
在此之前我们先说明一些事情
首先我们很早就说过了,可执行程序是在磁盘中的
当可执行程序很大的时候,就会分批加载,意思是只加载一部分
或者挂起状态的时候,把可执行程序加载到磁盘的swap分区了

这样的话,可执行程序就可能没有完全加载到内存中,那么在代码区通过页表访问物理内存的时候就会访问不到,就会出错,有了isexists的话,取访问的时候,就会告诉你不可访问,然后就会去磁盘中加载到内存,其实就是一个需要才去加载的操作

4.5 task_mm_struct的初始化

task_mm_struct是怎么初始化的呢

首先,肯定是先创建task_struct和task_mm_struct,再加载代码的
然后也是先销毁代码

我们先讲一下exe可执行程序,这里面不仅包含了代码,还有一些属性,比如每个区域所占大小,那么就可以根据这个属性来初始化task_mm_struct,就不用先加载代码了,然后就是边运行变加载代码
在这里插入图片描述
这个命令就可以查看每个区域的属性了,什么大小,什么都有

4.6 为什么要有进程地址空间

第一可以保护内存,万一你要访问一个野指针,但是对应没有这个虚拟地址,那么就会报错了

第二因为有了页表,所以进程管理和内存管理就不会直接关联,那么这就有利于解耦合

第三就是让进程以统一的视角看待物理内存
意思就是代码和数据按理说可以加载到物理内存的任何位置,因为虚拟地址和物理地址是一一对应的,所以不管怎么放,都能找到,但是一般是连续存放的,因为这样访问效率高,就和链表一样,你访问链表的效率比数组低的原因一样

总结

上面这些就是我们讲的进程的一些基本知识,下一讲会将一些进程的一些实操,当然也少不了知识点

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

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

相关文章

ARM assembly: lesson 11

在之前,我们提到,当函数的参数小于等于4个时,我们会把它存放于寄存器中,但是如果函数参数大于4个,我们就需要通过stack去进行参数的存储,这毫无疑问,将增加代码操作的复杂性,因为我们需要对于栈…

国外透明代理IP解析:匿名性的全貌

网络世界中,透明代理IP是一个广受关注的话题。究竟什么国外透明代理IP?以及它的匿名性如何?本文将深入解析透明代理IP的定义及其匿名性,为您呈现一个清晰的认识。 1. 概念 透明代理IP是指在进行网络请求时,客户端&am…

(数据结构与算法)哈希表

哈希表把他当成一个key-values表

鸿蒙harmonyos next flutter混合开发之开发plugin(获取操作系统版本号)

创建Plugin为my_plugin flutter create --org com.example --templateplugin --platformsandroid,ios,ohos my_plugin 创建Application为my_application flutter create --org com.example my_application flutter_application引用flutter_plugin,在pubspec.yam…

梯度下降学习

前言:初步学习梯度下降, 不断根据梯度修改我们的参数,经过多次轮次得到使得我们损失函数最小的时候参数,后续我们可以通过类似的道理,更新我们的参数 假设我们的损失函数是 y x 1 2 x 2 2 y x1^2 x2^2 yx12x22,我…

什么是 HTTP Get + Preflight 请求

当在 Chrome 开发者工具的 Network 面板中看到 GET Preflight 的 HTTP 请求方法时,意味着该请求涉及跨域资源共享 (CORS),并且该请求被预检了。理解这种请求的背景,主要在于 CORS 的工作机制和现代浏览器对安全性的管理。 下面是在 Chrome …

常用排序算法(下)

目录 2.5 冒泡排序 2.6 快速排序 2.6 1 快速排序思路 详细步骤 2.6 2 快速排序递归实现 2.6 3快速排序非递归: 快排非递归的优势 非递归思路 1. 初始化栈 2. 将整个数组的起始和结束索引入栈 3. 循环处理栈中的子数组边界 4. 单趟排序 5. 处理分区后的子…

Linux驱动开发(速记版)--热插拔

第九十六章 热插拔简介 热插拔是指在设备运行时安全地插入或拔出硬件,无需关闭或重启系统。 它提供了方便性和灵活性,允许快速更换或添加硬件而无需中断任务。 以下是一些应用场景及支持热插拔所需的条件: 应用场景: USB设备&…

python中,try-except捕获异常的意义(通过ai智库学习)

python中,不但可以用try-except捕获异常, 还可以自定义异常提示字符串,更可以自定义捕获异常后的处置。 (笔记模板由python脚本于2024年10月03日 06:47:06创建,本篇笔记适合喜欢研究python的coder翻阅) 【学习的细节是欢悦的历程】…

交叠型双重差分法

交叠型双重差分法(Staggered Difference-in-Differences, Staggered DiD)是一种扩展的双重差分(Difference-in-Differences, DiD)方法,用于处理多个时间点的政策干预或处理组(treatment group)并…

每日读则推(四)

Whats this...? | An invitation letter n.邀请函 n.邀请(invite v.邀请) Can a tool grasp the meaning in a song? v. 握紧,理解 n.紧握,理解(力) Can it feel the melody, where emotions belong? …

C++ union的运用

// // Created by 徐昌真 on 2024/10/5. // #include <iostream> #include <cstring> using namespace std;//定义一个结构体(类) struct Info{char _name[20];int _role; //老师是0 同学是1union { //用union存放score和course 节省内存int score;char course[2…

全球十大独角兽(完整榜单),你猜中国占几席?

全球十大独角兽 10月3日&#xff0c;OpenAI 宣布已完成 66 亿美元融资&#xff0c;估值达 1570 亿美元&#xff0c;成为全球第三的独角兽。 给新来的读者重温一下"独角兽"的定义&#xff1a;估值超过10亿美元的未上市企业。 你可能会好奇&#xff0c;OpenAI 是第三&a…

Linux·进程概念(下)

1. 进程优先级 优先级就是获得某种资源的先后顺序&#xff0c;因为CPU资源是有限的&#xff0c;因此各个进程之间要去争取CPU的资源。 那么针对Linux操作系统下的PCB中&#xff0c;也就是task_struct结构体中&#xff0c;使用了int类型的变量记录了每个进程的优先级属性&#x…

WIFI网速不够是不是光猫的“路由模式”和“桥接模式”配置错了?

光猫&#xff08;光纤调制解调器&#xff09;是一种用于将光纤信号转换为数字信号的设备&#xff0c;通常用于家庭或企业网络中。光猫可以在不同的工作模式下运行&#xff0c;其中最常见的两种模式是“路由模式”和“桥接模式”。以下是这两种模式的详细解释及其优缺点。 一、路…

python实现单例模式的常用三种方法-基于__new__/使用装饰器以及Python中的值类型、引用类型以及类的静态变量、读取进程和线程ID

一、python实现单例模式的常用三种方法-基于__new__,使用装饰器 涉及到类的使用就会有类的实例化&#xff0c;就会有类单例实现的需求&#xff0c;因为重复实例化会浪费资源。python中的单例模式与别的语言相比&#xff0c;单例实现的方法更丰富。虽然python实现单例的模式的方…

MobaXterm使用

Linux连接工具MobaXterm详细使用教程-CSDN博客

Elasticsearch学习笔记(五)Elastic stack安全配置二

一、手动配置http层SSL 通过前面的配置&#xff0c;我们为集群传输层手动配置了TLS&#xff0c;集群内部节点之间的通信使用手动配置的证书进行加密&#xff0c;但是集群与外部客户端的http层目前还是使用的自动配置&#xff0c;集群中HTTP的通信目前仍然使用自动生成的证书ht…

【韩顺平Java笔记】第7章:面向对象编程(基础部分)【227-261】

文章目录 227. 重载介绍228. 重载快速入门229. 重载使用细节230. 重载课堂练习1231. 232. 重载课堂练习2,3233. 可变参数使用233.1 基本概念233.2 基本语法233.3 快速入门案例 234. 可变参数细节235. 可变参数练习236. 作用域基本使用237. 作用域使用细节1238. 作用域使用细节2…

Docker安装部署和常用命令

Docker 是一种开源的平台&#xff0c;旨在帮助开发者和运维人员更轻松地创建、部署和运行应用程序。通过将应用程序及其依赖项打包到一个名为容器的标准化单位中&#xff0c;Docker 提供了一种轻量级的虚拟化解决方案。与传统虚拟机相比&#xff0c;Docker 容器可以在同一主机上…