Linux进程概念(2)

进程优先级

基本概念

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

查看系统进程

在linux或者unix系统中,用ps –l命令则会类似输出以下几个内容:
在这里插入图片描述
注意到其中的几个重要信息,有下:

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

PRI and NI

1.PRI表示进程的优先级,此值越小,优先级越高,Linux下PRI默认80。
2.NI是nice值,表示进程优先级的修正数值。
3.PRI值越小越快被执行,那么加入nice值后,将会使得PRI变为PRI(new)=PRI(old)+nice 所以调整优先级就是调整nice值
4.nice其取值范围是-20至19,一共40个级别。

更改nice值

top
进入top后按“r”–>输入进程PID–>输入nice值

在这里插入图片描述

其他概念

1.竞争性: 系统进程数目众多,而CPU资源只有少量,甚至1个,所以进程之间是具有竞争属性的。为了高效完成任务,更合理竞争相关资源,便具有了优先级。
2.独立性: 多进程运行,需要独享各种资源,多进程运行期间互不干扰
3.并行: 多个进程在多个CPU下分别,同时进行运行,这称之为并行
4.并发: 多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发

环境变量

基本概念

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

常见的环境变量

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

查看环境变量的方法

echo $NAME //NAME:你的环境变量名称
在这里插入图片描述

环境变量相关命令

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

环境变量的组织方式

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

在这里插入图片描述

通过代码获取环境变量

命令行第三个参数

#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[], char *env[])
{
 int i = 0;
 for(; env[i]; i++){
 printf("%s\n", env[i]);
 }
 return 0;
}

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

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

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

常用getenv和putenv函数来访问特定的环境变量。

程序地址空间

研究环境:
kernel 2.6.32
32位平台

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

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

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

结果:
在这里插入图片描述
我们发现,父子进程,输出地址是一致的,但是变量内容不一样!能得出如下结论:

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

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

分页&虚拟地址空间

在这里插入图片描述
上面的图就足矣说名问题,同一个变量,地址相同,其实是虚拟地址相同,内容不同其实是被映射到了不同的物理地址

Linux内核进程调度队列

在这里插入图片描述
上图是Linux2.6内核中进程队列的数据结构.
一个cpu拥有一个runqueue

活动队列

1.时间片还没有结束的所有进程都按照优先级放在该队列
2.nr_active: 总共有多少个运行状态的进程
3.queue[140]: 一个元素就是一个进程队列,相同优先级的进程按照FIFO规则进行排队调度,所以,数组下标就是优先级!
4.bitmap[5]:一共140个优先级,一共140个进程队列,为了提高查找非空队列的效率,就可以用5*32个 比特位表示队列是否为空,这样,便可以大大提高查找效率。

过期队列

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

active指针和expired指针

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

  • 32
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

gsfl

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值