【解锁创意之门:环境变量引领你的编程奇思妙想】(上)

简介: 【解锁创意之门:环境变量引领你的编程奇思妙想】

【本节重点】


  • 了解进程调度,Linux进程优先级,理解进程竞争性与独立性,理解并行与并发
  • Linux的调度与切换,了解Linux2.6内核中进程队列的数据结构
  • 理解环境变量,熟悉常见环境变量及相关指令, getenv/setenv函数
  • 理解C内存空间分配规律,了解进程内存映像和应用程序区别, 认识地址空间。


1.进程优先级


前提:进程要访问某种资源,进程进行通过一定的方式(排队),确认享受资源的先后顺序。


1.1.基本概念


  • cpu资源分配的先后顺序,就是指进程的优先权(priority)。
  • 优先权高的进程有优先执行权利。配置进程优先权对多任务环境的linux很有用,可以改善系统性能。
  • 还可以把进程运行到指定的CPU上,这样一来,把不重要的进程安排到某个CPU,可以大大改善系统整体性能。


提问:优先级 vs 权限


       权限绝对的是能不能的问题,而优先级决定的是你先还是我先的问题,说白了,只要到了优先级,大概率一定是你拥有享受这个资源的权限了,只不过需要通过优先级确定先后的问题。


为什么要有优先级呢?


我们可以想一想,如果我们在食堂打饭的时候,打饭的人比学生多,那么学生就不用排队,可是现在打饭的人明显少于学习,所以学生就要排队,进程也是如此,因为系统的资源过少!但是这是一个相对概念,只有在中午去食堂买饭就需要排队,而在下午三四点去买饭就不用排队!这也就解释了CPU为什么有运行队列,因为CPU只有一个,资源过少,每个进程想获取CPU就必须要排对,进程需要通过队列确认优先级去获得CPU的访问,如果我们电脑的CPU很多,那就不需要队列了,直接运行进程就行啦。


1.2.查看系统进程



我们先写一份上面的代码,然后执行一下,同时输入在右侧输入:ps -al


ps -al 是一个用于显示进程信息的命令,常用于Linux。下面是对该命令的解释:


  • ps: 这是进程状态的缩写,是一个用于报告当前进程状态的命令。
  • -a: 显示所有终端上的进程,而不仅仅是与当前用户相关的进程。
  • -l: 以长格式显示输出。长格式包括更多的列,提供更详细的信息。


我们很容易注意到其中的几个重要信息,有下:

  • UID : 代表执行者的身份
  • PID : 代表这个进程的代号
  • PPID :代表这个进程是由哪个进程发展衍生而来的,亦即父进程的代号
  • PRI :代表这个进程可被执行的优先级,其值越小越早被执行
  • NI :代表这个进程的nice值


这里我就要插几句话啦!不要把优先级想象的特别复杂,它在sturck task_struct里面就是一个整型变量,而且上面我们观察到Linux下默认优先级是80,但是Linux的优先级是可以被修改的,但是Linux优先级是有区间的,其范围是[60,99],一共40个。Linux优先级本质就是整型变量数字,数字越小,优先级越高!


1.3.PRI and NI


  • PRI也还是比较好理解的,即进程的优先级,或者通俗点说就是程序被CPU执行的先后顺序,此值越小 进程的优先级别越高
  • 那NI呢?就是我们所要说的nice值了,其表示进程可被执行的优先级的修正数值
  • PRI值越小越快被执行,那么加入nice值后,将会使得PRI变为:PRI(new)=PRI(old)+nice
  • 这样,当nice值为负值的时候,那么该程序将会优先级值将变小,即其优先级会变高,则其越快被执行
  • 所以,调整进程优先级,在Linux下,就是调整进程nice值
  • nice其取值范围是-20至19,一共40个级别。


1.4.PRI vs NI


  1. 需要强调一点的是,进程的nice值不是进程的优先级,他们不是一个概念,但是进程nice值会影响到进程的优先级变化。
  2. 可以理解nice值是进程优先级的修正修正数据


1.5.用top命令更改已存在进程的nice:


       Linux系统允许用户调整优先级,但是不能直接让你修改PRI,而是通过修改nice值,它不是优先级,而是进程优先级的修正数据!现在我们来演示一下优先级的修改。


结果展示:


根据这个公式:PRI(new)=PRI(old)+nice,我们再恢复出原来的优先级


咦!这是什么情况!!!


nice值是通过覆盖式的写入的,但是我们的PRI不应该是80 = 90 + (-10)嘛,为什么是70呢?其实这是正常的,你想想如果我们的PRI是80,那我们的nice就是-10了,而其他进程nice值是0,这样系统的数据就不一致了,所以PRI在每一次设置的时候,PRI(old)都是80。


我们再来测试一下nice其取值范围


首先我们将nice值干到100。


然后我们将nice值干到-100。


总结:nice其取值范围是-20至19,一共40个级别,Linux优先级是有区间的,其范围是[60,99],一共40个,两个相互对应。


提问:Linux为什么调整优先级是受收限制的?


       如果允许任意进程调整优先级,用户可能会将自己的进程提升到高优先级,自己的进程抢占系统资源,使其他进程无法正常运行,无法享受到CPU等其他资源,此时其他进程很难得到资源,此时就被称为进程饥饿问题。任何得分时操作系统,调度上,都要具有较为公平的进行调度,所以就要求优先级是受收限制的。


2.Linux的调度与切换


概念准备:


  1. 进程在运行的时候,放在CPU上,必须直接把代码跑完,才行吗???不行,这很明显,如果我们写一个死循环的代码,那么CPU永远都跑不完,其他进程也就永远得不到调度,那么此时系统就卡死了。所以现代操作系统都是基于时间片轮转进行轮转执行的!!!  
  2. 竞争性: 系统进程数目众多,而CPU资源只有少量,甚至1个,所以进程之间是具有竞争属性的。为了高效完成任务,更合理竞争相关资源,便具有了优先级
  3. 独立性: 多进程运行,需要独享各种资源,多进程运行期间互不干扰
  4. 并行: 多个进程在多个CPU下分别,同时进行运行,这称之为 并行
  5. 并发: 多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为 并发


2.1.进程切换



我们可以在struct task_struct查看到这些硬件上下文。


所以进程切换的过程就是:进程在CPU上运行 -> 时间片用完,保存硬件上下文 -> 运行队列进程阻塞 ->时间片轮转到该进程,恢复硬件上下文。这也就是一个进程在CPU一整个周期的情况。


2.2.进程调度


前提:Linux实现进程调度算法需要考虑优先级,考虑饥饿,还要考虑效率


上图是Linux2.6内核中进程队列的数据结构,我们先不看,后面我会基于上面的画一个。


2.2.1.一个CPU拥有一个runqueue


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


2.2.2.优先级


  • 普通优先级适用于一般用户进程,它们不需要对实时性有极高的要求。这些进程的调度是基于时间片轮转的,并且由操作系统决定它们在CPU上运行的时间。普通优先级:100~139(我们都是普通的优先级,想想nice值的取值范围,可与之对应!)
  • 实时优先级是为具有严格时间要求的任务设计的,这些任务需要在确定的时间内完成。实时优先级:0~99(不关心)


2.2.3.活动队列


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


1. 从0下表开始遍历queue[140]

2. 找到第一个非空队列,该队列必定为优先级最高的队列

3. 拿到选中队列的第一个进程,开始运行,调度完成!

4. 遍历queue[140]时间复杂度是常数!但还是太低效了!

  • bitmap[5]:一共140个优先级,一共140个进程队列,为了提高查找非空队列的效率,就可以用5*32个 比特位表示队列是否为空,这样,便可以大大提高查找效率!


2.2.4.过期队列


  • 过期队列和活动队列结构一模一样
  • 过期队列上放置的进程,都是时间片耗尽的进程
  • 当活动队列上的进程都被处理完毕之后,对过期队列的进程进行时间片重新计算
  • 如果我们的一个进程的时间片已经轮转完,它就应该从活跃队列中剥离出来,而成为新进程进入来过期队列中。


2.2.5.active指针和expired指针


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


上图是Linux2.6内核中进程队列的数据结构,之间关系也已经给大家画出来,方便大家理解。


2.2.6.总结


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


补充:参考文档 


3.环境变量


3.1.mian参数 --- 命令行参数 --- 掌握


我们知道main函数是有形参的,只不过我们一直没有使用过,今天我们来看一下main函数的参数,看看main函数的参数是什么意思?它和密命令行参数有什么关系?


首先我们知道argv是一个指针数组,数组元素有argc个,它里面的元素类型都是char*的,而我们知道char*指向的是字符串的首地址,我们来看一下argv里面的每个char*都指向了那个字符串?


我们发现随之我们的程序执行,当我们以空格作为分隔符传入-a,-b,-c,程序按照空格为分隔符,依次传入一个一个子串到argv这个指针数组里面,同时每传入一个字串,argc的个数就会加一。现在我再来解释一下输出内容。


所以我们在命令行上输入以空格为分隔符输入的字符串,会被bash解析一个一个子串,维护成指针数组argv,同时还维护了一个计数器argc,只要是函数它就会被调用,main函数也不例外,main函数由系统调用,bash会把参数传入给main函数,所以我们的main函数就拿到了命令行上输入以空格为分隔符输入的字符串和计数器argc,然后就输出了上述的结果。整个传入main函数的参数我们可以称之为一张表,我们称之为命令行参数表,把这张表就传给当前进程,而且整张表必须以NULL为结尾。那么我们的程序还可以这样写:


【解锁创意之门:环境变量引领你的编程奇思妙想】(中):https://developer.aliyun.com/article/1425753

相关文章
|
7月前
|
机器学习/深度学习 人工智能 Java
学会用AI:释放创意,解放双手,工作再多也不慌
随着人工智能(AI)技术日渐成熟,AI在软件开发领域的应用也更加广泛。以前我们谈到AI时,常常会想到复杂的算法和深奥的理论,但如今,AI正在悄然改变着程序员的日常工作方式。从AI代码生成模型到AI编程助手应用,它们不仅仅是一小部分,更是未来程序开发的新趋势。
|
3月前
|
存储 Shell Linux
【解锁创意之门:环境变量引领你的编程奇思妙想】(下)
【解锁创意之门:环境变量引领你的编程奇思妙想】
|
3月前
|
Shell Linux 编译器
【解锁创意之门:环境变量引领你的编程奇思妙想】(中)
【解锁创意之门:环境变量引领你的编程奇思妙想】
|
2月前
|
自然语言处理 搜索推荐 程序员
【创意坊】​ChatDev震撼登场!开源狂潮席卷​​,释放无限可能!
【创意坊】​ChatDev震撼登场!开源狂潮席卷​​,释放无限可能!
49 2
【创意坊】​ChatDev震撼登场!开源狂潮席卷​​,释放无限可能!
|
7月前
|
人工智能 算法 数据可视化
使用AI焕发那场亚运的精彩--给回忆增添色彩,对未来充满期待
1974年9月1日,第七届亚洲运动会在伊朗首都德黑兰的阿里亚梅尔体育中心的主体育场开幕,这是新中国首次参加亚运会。而今正值亚运110周年,第19届杭州亚运会即将举办。本次通过参与“历久弥新——用 AI 修复亚运会珍贵史料”活动,使用阿里云的 AI 技术对亚运会历史老照片进行修复,重燃亚运经典,为亚运助威。
595 8
|
3月前
|
人工智能 前端开发 JavaScript
【利用AI让知识体系化】解锁异步编程的新世界!
【利用AI让知识体系化】解锁异步编程的新世界!
|
算法 Java PyTorch
代码补全快餐教程(1) - 30行代码见证奇迹
# 代码补全快餐教程(1) - 30行代码见证奇迹 下面是我用30多行代码,包含了很多空行和注释的代码写成的代码补全模型。我们先看看效果吧。 ## 补全效果案例 ### 先来看个比较普通的(Python, Keras) 已知: ``` y_train = keras.utils.to_categorical(y_train, num_classes)\ny_test =
1153 0
|
机器人
奇葩设计师贾伟打开你的想象力经济
云栖TechDay活动第30期中,洛可可集团创始人&洛客(LKKER)创始人贾伟带来题为“想象力经济下的智能美学”的演讲。想象力经济时代已到来,本文从什么是想象力开始谈起,讲到想象力打造新消费生活,以及想象力打造绿色创新平台,最后也谈了想象力打造美学文化等。
591 0
|
测试技术 程序员 信息无障碍
【晒出你的第83行代码】十年全栈编程,视障工程师@蔡勇斌带我们走进他的代码视听世界
作为一个拥有10年PC开发经验的盲人程序员,他不仅参与了钉钉无障碍版本的测试,还编写过很多帮助盲人使用电脑之类的软件。他带我们走进了属于他的代码视听世界,让更多盲人看见。
4411 0