Linux进程概念(下)

前言

上文介绍了进程的基本概念,进程=内核数据结构+可执行程序,查看进程的方式ps 和/proc指令。

又熟悉常见的进程状态,状态修改的本质就是将PCB标志位更改,然后放到指定的队列中。

本文继续介绍进程的概念,将介绍进程的优先级、O(1)调度算法、环境变量、进程地址空间等等。


进程的优先级

为什么要有优先级?


因为CPU资源是少数的,系统内的进程是多数的,所以进程之间会存在竞争CPU资源,就要对进程进行排队,这个排队的过程就是确定进程的优先级。

查看系统的优先级

ps -al 查看系统默认的优先级

 PRI和NICE

  • linux下利用PRI和NICE同时确认系统的优先级
  • PRI是默认优先级,每一次都会被设置为80,而NICE是调整值。
  • 如果NICE是-10, 优先级=80-10=70。如果NICE=15,优先级=80+15=95。
  • 优先级的范围是60-99,不在这个范围的优先级会被调整为边界。

为什么要限定优先级的范围?
本质就是让CPU调度的时候,能够较为均衡的把每一个进程都调度,防止进程饥饿问题。

修改系统的优先级

TOP+R指令

进程的上下文切换 

CPU只有一套寄存器,进程是独立的,也就是说每一个进程都能使用这一套寄存器。

进程的上下文数据会被保存在寄存器中,上下文数据就是产生的临时数据等等。

进程的时间片结束时候,会将寄存器中的上下文数据保存到进程PCB当中,当该进程的时间片再次到来,会将保存在PCB中的上下文数据恢复到寄存器当中。这个过程就叫做上下文切换。


Linux内核2.6下的O(1)调度算法

处于运行队列的PCB都会等待CPU调度。

运行队列会维护俩份队列和位图,活跃进程指针和过期队列进程指针。

调度进程时候,会先到通过活跃进程的bitmap找到哪一位上不为0,然后到活跃队列的对应下标去取PCB来调度。而调度完的PCB和后来的PCB都应该被放到过期队列中。

当活跃队列为空时,就交换活跃队列和过期队列的指针。

 所谓的插队就是将后来的进程放到活跃队列中,而不是放到过期队列中。

  • 提高效率的操作是bitmap:5*32=160位,就可以32位一起判断,而不是遍历整个队列。
  • 保证均衡调度的是:维护双队列,后来的放到过期队列,不影响先来正在调度的进程。

命令行参数

命令行参数是main函数中的参数,可以在执行前通过命令行可执行程序+选项的方式,被进程获取。

测试简单的命令行参数

注意:

  • 命令行参数是以字符串的形式组织起来。
  • 在最后一个参数结束后,会以nullptr结尾。

 命令行参数的意义?
支持各种指令级别选项设置。

实际上,我们在linux下输入的各种指令就是可执行进程,如果输入选项字段,就是命令行参数。


环境变量

linux各种指令的本质就是可执行程序,这一点是可以被验证的。

模拟touch创建一个文件

  1 #include<stdio.h>2 #include<stdlib.h>3 int main(int argc,char * argv[]){4     if(argc!=2){5         printf("command error!\n");6         exit(0);7     }8     FILE * fp;9     fp=fopen(argv[1],"w+");10 11     fclose(fp);12     return 0;13 }

与linux下不同的是,我们需要指明路径,而OS的程序就不用。

主要是因为OS会通过环境变量的方式内保留可执行程序的搜索路径

环境变量的概念

环境变量是指操作系统用来指定操作系统运行环境的一些参数。

比如在链接动静态库的时候,不用指明具体路径,照样可以链接成功。

环境变量通常有特定的功能,具有全局属性。

常见的环境变量

通过env查看全部的环境变量

常见的环境变量:

  • PATH:默认的搜索路径
  • PWD:当前目录
  • LOGNAME:日志名称
  • HOME:家目录,用户登录到linux下的目录。

查看环境变量

通过echo  $(环境变量)的方式查看莫一个环境变量

echo &PATH

测试环境变量 

将之前撰写的mytouch添加进行PATH搜索路径环境变量

  • 1.将mytouch添加进行指定的目录
  • 2.为PATH添加路径

验证一:

验证二:
通过指令为PATH添加mytouch的路径

 PATH=$PATH:/home/lyh/proctest

获取环境变量

通过miai函数传参

其实main函数的第三个参数是一张环境变量表

通过main函数的第三个参数就能获取到环境变量表,这个环境变量表和env指令看到的是一样的。

当环境变量作为参数传递给main函数,实际上是以字符串数组的形式,末尾是NULL结尾

通过getenv

系统调用getenv获取指定的环境变量

环境变量是从父进程继承过来的,但是bash进程的环境变量是从哪里来的?

从配置文件中读取而来的。

在home目录中存在一个/profile 文件,配置着环境变量

我们也可以自主添加环境变量,比如:变量名=值

 但是这样添加的,只能称为本地变量,如果想成为环境变量,就必须通过export导入

删除导入的环境变量:unset

注意:
即使通过export导入的环境变量,在shell重新登录时候,都会被清空,因为shell会读取配置文件的环境变量,除非你把自定义的环境变量导入到配置文件中。 

获取环境变量的第三种方式

通过environ全局参数,用法和main函数的参数一致。

 int main(){//这里只是声明一下extern char **  environ;for(int i=0;environ[i];i++){ printf("environ[%d]:%s\n",i,environ[i]);} return 0;}   

环境变量具有全局属性,会随着子进程一直继承下去。

本地变量vs环境变量

本地变量只在当前会话的bash中有效,并且不会随着进程继承下去。环境变量会在所有的子进程中继承。

linux下指令分类:常规的进程(fork子进程程序替换实现)。2.内建命令:由bash提供的函数。


进程地址空间 

实验:在父进程中创建全局变量值为100,fork创建子进程。五秒后,子进程将值修改为200。观察父子进程的值是否一致。

最后发现父进程的值为100,子进程的值为200。val的值是不一致的,但是同一个值的地址确不同。

说明我们这个地址肯定不是内存上的地址。到达是什么?是虚拟地址。本文就来探讨一下进程地址空间的相关内容。


每一个进程都有一个虚拟地址空间的存在

当进程被启动的时候,会创建PCB建立地址空间。操作系统必然会对这些地址空间管理,所以地址空间就是内核的数据结构。会被记录在进程的PCB中。

进程地址空间就是(struct mm_struct)

进程间不会共享同一个地址空间,因为要保证进程的独立性。让进程知道自己有机会获取到所有的物理空间。

页表:(空间映射)

每个进程都存在自己的地址空间,当磁盘上的数据被加载到内存上时,会先建立虚拟地址和物理地址的映射。并且将这种映射关系保存到页表上,用于从虚拟地址,找到实际内存上的地址。

什么是地址空间

回答这个问题前,先了解一下区域划分。在一根直尺上,如果最小刻度是cm。

那么假设区域1的起始地址是0cm,结束地址是10cm。区域2的起始地址是 11cm,结束是30cm。

那对于区域1中,我们也可以继续划分,我们可以按照mm划分,划分成为更小的刻度。

所以区域划分的本质就是用start和end标志你的空间。

进程地址空间的划分也是如此

struct destop_area{_size,字符常量区_start,_end,代码区 _start,_end,栈区 _start,_end......
}

看一看内核中的定义

asmlinkage int
osf_set_program_attributes(unsigned long text_start, unsigned long text_len,unsigned long bss_start, unsigned long bss_len)
{struct mm_struct *mm;lock_kernel();mm = current->mm;mm->end_code = bss_start + bss_len;mm->brk = bss_start + bss_len;
#if 0printk("set_program_attributes(%lx %lx %lx %lx)\n",text_start, text_len, bss_start, bss_len);
#endifunlock_kernel();return 0;
}

内核中就是由start和end组成

所以进程地址空间就是struct结构体,维护了start和end指针对物理地址做了虚拟的空间划分。

页表是被保存在寄存器上的,也可以通过指针找到页表。

页表的地址是虚拟还是物理地址?物理地址。


回答实验的问题

为什么一个变量,有俩个值。

当一个进程被启动时,就会创建pcb结构体,创建mm_struct地址空间。同时保存页表,对必要的数据做物理内存到虚拟地址上的映射,也就是说假设变量的地址为0x00003344那么物理地址映射的可能就是0x22334455。这时创建子进程,子进程就会以父进程的PCB为模板创建子进程的PCB,同时也会复制一份父进程的地址空间,以及页表映射。

上图有点小错误,应该指向的是已经初始化的全局区。

当子进程对全局变量修改时,由于进程间的独立性,就会发生写时拷贝。

子进程会重写开辟物理内存,将父进程的值拷贝进去,然后进行修改,重新建立页表的映射。

所以我们看到的地址就是虚拟地址,同一个虚拟地址在不同的进程下,就有了俩个值。


为什么要有进程地址空间

1.让进程可以以统一的视角看待内存。任意一个进程 通过地址空间+页表将乱序的内存变得井然有序。

2.可以对访问内存进行安全检查。比如我们不能修改代码区的字段。

实际上,页表还存在第三列,就是权限位。比如字符常量区的权限就是r,栈区的就是rw

当我们要修改字符常量区时,就会被权限位拦住,不让你访问。

缺页中断:
页表还存在一列表示内存是否已经分配。

当程序被加载到内存时候,不需要把整个代码+数据全部加载,而是加载一部分。但是会先建立页表的左边部分,然后确定第4列数据是否分配。如果访问到尚未分配的地址时候,就会暂停进程,加载资源,修改页表,再去执行进程。

这一个过程就叫做缺页中断。

3.实现进程管理和内存管理的解耦:进程只需要负责去访问地址读取资源,加载资源由OS自动完成。


写时拷贝

什么时候进行写时拷贝?
当父进程fork创建子进程时候,就会将父进程的页表权限位全部修改位只读。然后为子进程创建PCB,地址空间,页表等等。

当用户进行读写的时候,就会被页表的权限位拦住出错:1.真的出错了,访问到真的只读区,直接不访问。2.同一份资源,就会重新申请物理内存,拷贝旧内容到新地址处。这就是写时拷贝。

关于进程概念暂时到此为止了,后续也会进行补充,进程的概念是庞大的,涉及到的知识点也比较复杂。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网络安全学习(四)渗透工具msf

本文简要介绍metasploit framework&#xff0c;是一款渗透工具。官网地址&#xff1a;Metasploit | Penetration Testing Software, Pen Testing Security | Metasploit msf是一个框架&#xff0c;可以加载各种模块&#xff0c;这是它的最强大之处。 kali中有此工具。 点击即…

maya的重命名物体和材质工具(带ai过程)

对材质同样也有效 被AI干失业的卖衣服的小姐姐&#xff0c;开的士的小哥哥都可以再就业的易上手教程&#xff0c; 先看效果&#xff01; 对物体命名也是&#xff0c;相当的美观 先提出需求我想在maya中批量重命名物体怎么办&#xff1f;AI给你弄个短代码 &#xff0c;放进AI进…

音视频入门基础:AAC专题(5)——FFmpeg源码中,判断某文件是否为AAC裸流文件的实现

一、引言 通过FFmpeg命令&#xff1a; ./ffmpeg -i XXX.aac 可以判断出某个文件是否为AAC裸流文件&#xff1a; 所以FFmpeg是怎样判断出某个文件是否为AAC裸流文件呢&#xff1f;它内部其实是通过adts_aac_probe函数来判断的。从《FFmpeg源码&#xff1a;av_probe_input_for…

3. 进阶指南:自定义 Prompt 提升大模型解题能力

怎么判断 Prompt 的好坏&#xff0c;有什么问题有着标准答案么&#xff1f; 答&#xff1a;让大模型求解数学问题。 李宏毅老师的 HW4 正好提到了有关数学问题的 Prompt&#xff0c;所以我决定中间插一篇这样的文章。通过本文你将&#xff1a; 了解各种 Prompt 如何影响大型语言…

无人机飞手培训机构组建及市场分析

飞手培训机构是专门为培养无人机飞行员&#xff08;飞手&#xff09;而设立的教育机构。这些机构通过提供专业的培训课程&#xff0c;帮助学员掌握无人机飞行技术、了解相关法规、提升实战能力&#xff0c;并最终获得相关证书&#xff0c;以便在航拍摄影、农业植保、物流配送、…

图新地球-将地图上大量的地标点批量输出坐标到csv文件【kml转excel】

0.序 有很多用户需要在卫星影像、或者无人机航测影像、倾斜模型上去标记一些地物的位置&#xff08;如电线杆塔、重点单位、下水盖等&#xff09; 标记的位置最终又需要提交坐标文本文件给上级单位或者其他部门使用&#xff0c;甚至需要转为平面直角坐标。 本文的重点是通过of…

【Go开发】Go语言基本语法入门:数据类型与方法定义

文章目录 环境准备一、引言二、Var关键字三、数据类型1. 整型符号表示值的范围 2. 浮点型精度范围性能 3. 布尔型4. 字符串 三、变量声明1. 指定变量类型2. 自动推导类型3. 批量声明 四、方法定义五、总结 环境准备 开发环境&#xff1a;MacOS Go版本&#xff1a;go version g…

单线程与2个线程的简易理解

前言 有个需要10个步骤完成的任务&#xff0c;假设每个步骤需要1秒 单线程耗费10秒完成任务 2根线程可能耗费6秒&#xff0c;也可能更少 单线程程序 单线程下&#xff0c;步骤按照次序顺序执行&#xff0c;共计耗费10秒 2个线程的程序 有步骤可以在同一时刻同时运行&…

python-素数中的等差数列

题目描述 质数是在数论中很有意思的数&#xff0c;有很多题都可以围绕它来出&#xff0c;就如你眼前所见的这道题。 给定一个闭区间 [a,b] ,将此范围内的所有素数进行从小到大排序&#xff0c;对于连续的素数&#xff0c;我们可以发现很多等差数列(元素个数大于等于 3 )&#x…

【Leetcode:1184. 公交站间的距离 + 模拟】

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

第十一章 【后端】商品分类管理微服务(11.1)——创建父工程

第十一章 【后端】商品分类管理微服务 11.1 创建父工程 项目名称:EasyTradeManagerSystem:Easy 表示简单易用,Trade 表示交易,Manager 表示管理,System 表示系统,强调系统在商品交易管理方面的便捷性,简称 etms。 新建工程 yumi-etms yumi-etms 作为所有模块的父工程,…

汽车免拆诊断案例 | 沃尔沃V40 1.9TD断续工作

故障现象 一辆04款的沃尔沃V40 1.9 TD&#xff0c;发动机代码D4192T3&#xff0c;使用博世EDC15C发动机管理。客户说车子断续工作&#xff0c;怀疑是正时皮带出现问题。卸下上皮带盖&#xff0c;检查发现皮带仍然在原来的位置上并且没有出现松动。起动发动机&#xff0c;车辆能…

整数在内存中的存储原码反码补码

目录 1.整数在内存中以二进制的形式存在 1.1&#xff08;正数存储情况&#xff09; 1.2 负数存储情况 1.3整数的补码如何得到原码 2.无符号整数的原反补码 小心&#xff01;VS2022不可直接接触&#xff0c;否则&#xff01;没这个必要&#xff0c;方源面色淡然一把抓住&am…

使用原生HTML的drag实现元素的拖拽

HTML 拖放&#xff08;Drag and Drop&#xff09;接口使应用程序能够在浏览器中使用拖放功能。例如&#xff0c;用户可使用鼠标选择可拖拽&#xff08;draggable&#xff09;元素&#xff0c;将元素拖拽到可放置&#xff08;droppable&#xff09;元素&#xff0c;并释放鼠标按…

vue3使用provide和inject传递异步请求数据子组件接收不到

前言 一般接口返回的格式是数组或对象&#xff0c;使用reactive定义共享变量 父组件传递 const data reactive([])// 使用settimout模拟接口返回 setTimeout(() > {// 将接口返回的数据赋值给变量Object.assign(data, [{ id: 10000 }]) }, 3000);provide(shareData, dat…

C++第五十一弹---IO流实战:高效文件读写与格式化输出

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】 目录 1. C语言的输入与输出 2. 流是什么 3. CIO流 3.1 C标准IO流 3.2 C文件IO流 3.2.1 以写方式打开文件 3.2.1 以读方式打开文件 4 stringstre…

「数组」十大排序:精讲与分析(C++)

概述 截止目前&#xff0c;我们已经讲解并分析了十种最常见的排序算法&#xff0c;下附对应文章链接和全体Code。 链接 「数组」冒泡排序|选择排序|插入排序 / 及优化方案&#xff08;C&#xff09; 「数组」归并排序 / if语句优化|小区间插入优化&#xff08;C&#xff09…

在k8s中,客户端访问服务的链路流程,ingress--->service--->deployment--->pod--->container

ingress是一个API资源。 其核心作用是nginx网页服务器。 当客户端访问服务器不同的url时, 用不同的location提供服务。 在k8s之外&#xff0c;nginx的配置一般如下&#xff1a; http {server {listen 80;server_name localhost;location / {root html; …

HarmonyOS开发之(下拉刷新,上拉加载)控件pulltorefresh组件的使用

效果图&#xff1a; 一&#xff1a;下载安装&#xff08;地址&#xff1a;OpenHarmony-SIG/PullToRefresh&#xff09; ohpm install ohos/pulltorefresh 二&#xff1a;使用lazyForEarch的数据作为数据源 export class BasicDataSource implements IDataSource{private l…

外卖会员卡是不是一个骗局?

大家好&#xff0c;我是鲸天科技千千&#xff0c;大家都知道我是做小程序开发的&#xff0c;平时会给大家分享一些互联网相关的创业项目&#xff0c;感兴趣的可以跟我关注一下。 首先就是要搭建一个自己的外卖会员卡系统小程序&#xff0c;我们自己的工作就是把这个小程序推广…