文章目录
- 进程间的切换
- Linux2.6内核进程调度队列
- 一个CPU拥有一个runqueue
- 优先级
- 活跃进程
- 过期队列
- active指针和expired指针
- 环境变量
- 基本概念
- 常见环境变量
- 查看环境变量的方法
- 测试PATH
- 测试HOME
- 和环境变量相关的命令
- 通过代码如何获取环境变量
- 通过系统调用获取环境变量
进程间的切换
我们知道在CPU进行调度的时候,并不是一个进程结束后才取消调度,而是不停地在多个进程之间进行调度。
那么我们引入几个问题
1、没运行完的进程的数据在哪???
2、当一个进程被取下时它在CPU的数据是否会被删除???
- 第一个问题
当一个进程在没运行完的情况下被取下CPU时,肯定会保存一个信息,那就是当前进程运行到哪儿了?和C语言的代码相似,当前代码运行到哪儿了系统是怎么知道的?
1.为什么我们函数内定义的栈临时变量,会返回个给外部???
因为有eax
这个寄存器(帮助函数返回一个值),充当代码的临时空间;
2.为什么我们的进程知道我们当前运行到了哪里???如何做到函数间的跳转???
因为CPU内有eip
(程序计数器)。会保存当前指令的下一条指令的地址。
所以其实在进程运行时,是会使用到这些寄存器的!进程产生的各种数据会在寄存器中进行临时保存!
- 第二个问题
一个进程被取下来时CPU并不会删除它的临时数据;
而是当下一个进程被放入时,用下一个进程的数据将上一个进程 的数据覆盖了!
各个进程在CPU寄存器中形成的临时数据(进程的硬件上下文
),都是不一样!!互不影响!!!
将CPU内的寄存器保存到进程的PCB当中,本质:CPU寄存器的内容保存到了内容中!
总结: 当一个进程被调度时:如果之前被调度过了,那么它首先要做的事情是,将自己PCB中的硬件上下文恢复上来;如果之前没有被调度,那么直接让eip指向进程的初始代码。
Linux2.6内核进程调度队列
一个CPU拥有一个runqueue
如果有多个CPU就要考虑进程个数的负载均衡问题。
优先级
queue下标说明:
- 普通优先级:100~139。
- 实时优先级:0~99。
我们进程的都是普通的优先级,前面说到nice值的取值范围是-2019,共40个级别,依次对应queue当中普通优先级的下标100139。
注意: 实时优先级对应实时进程,实时进程是指先将一个进程执行完毕再执行下一个进程,现在基本不存在这种机器了,所以对于queue当中下标为0~99的元素我们不关心。
活跃进程
时间片还没有结束的所有进程都按照优先级放在活动队列当中,其中nr_active代表总共有多少个运行状态的进程,而queue[140]数组当中的一个元素就是一个进程队列,相同优先级的进程按照FIFO规则进程排队调度。
调度过程如下:
1、从0下标开始遍历queue[140]。
2、找到第一个非空队列,该队列必定为优先级最高的队列。
3、拿到选中队列的第一个进程,开始运行,调度完成。
4、接着拿到选中队列的第二个进程进行调度,直到选中进程队列当中的所有进程都被调度。
5、继续向后遍历queue[140],寻找下一个非空队列。
bitmap[5]:queue数组当中一共有140个元素,即140个优先级,一共140个进程队列,为了提高查找非空队列的效率,就可以用5 × \times× 32个比特位
表示队列是否为空,这样一来便可以大大提高查找效率。
过期队列
Q:当一个优先级为90的进程正在运行,但是此时突然多了一个优
先级为80的进程,那么这个多加入的进程也是放入活跃队列中和其中的进程抢占资源吗?
A:不会,优先级很高的进程加入进来,原本优先级比较低的进会迟迟得不到CPU的资源,会进程饥饿!
所以新加入进来的进程会被放进过期队列中!
和活跃进程
一样也是按照优先级排列!
- 过期队列和活动队列的结构相同。
- 过期队列上放置的进程都是时间片耗尽的进程。
- 当活动队列上的进程被处理完毕之后,对过期队列的进程进行时间片重新计算。
那么当活跃队列中的进程被调度完了
此时CPU是去过期进程调度吗?
答案是不!系统直接使用swap()函数
将活跃进程和过期进程的内容交换
CPU还是在处理活跃队列的进程!
active指针和expired指针
- active指针永远指向活动队列。
- expired指针永远指向过期队列。
环境变量
基本概念
环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数
如:我们在编写C/C++代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪里,但是照样可以链接成功,生成可执行程序,原因就是有相关环境变量帮助编译器进行查找。
环境变量通常具有某些特殊用途,还有在系统当中通常具有全局特性。
常见环境变量
PATH : 指定命令的搜索路径
HOME : 指定用户的主工作目录(即用户登陆到Linux系统中时,默认的目录)
SHELL : 当前Shell,它的值通常是/bin/bash。
查看环境变量的方法
我们可以通过echo命令来查看环境变量,方式如下:
echo $NAME //NAME为待查看的环境变量名称
测试PATH
为什么执行系统命令的时候不用带./就可以执行,而我们自己生成的二进制可执行程序必须要在前面带上./才可以执行?
当我们运行一个程序时,我们首先要知道他的位置,既然系统命令可以不使用./
就可以运行,说明系统已经找到了它的位置
那么如何让我们的程序不带./也能运行呢?
- 方法一
将可执行程序拷贝到环境变量PATH的某一路径下。
- 方法二
将可执行程序所在的目录导入到环境变量PATH当中。
测试HOME
任何一个用户在运行系统登录时都有自己的主工作目录(家目录),环境变量HOME当中即保存的该用户的主工作目录。
普通用户示例:
超级用户示例:
和环境变量相关的命令
- echo:显示某个环境变量的值。
- export:设置一个新的环境变量。
- env:显示所有的环境变量。
通过代码如何获取环境变量
方法一:main函数的第三个参数
#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;
}
方法二:通过第三方变量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;
}
通过系统调用获取环境变量
可以通过系统调用getenv函数来获取环境变量。getenv函数可以根据所给环境变量名,在环境变量表当中进行搜索,并返回一个指向相应值的字符串指针。
使用getenv函数获取环境变量PATH的值。
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
printf("%s\n", getenv("PATH"));
return 0;
}