Linux篇9进程2

1.进程优先级

概念:cpu资源分配的先后顺序,就是指进程的优先权(priority)

在linux系统中,用ps –l命令则会类似输出以下几个内容:

image-20220624025352036

其中PRI就是指该进程优先级,NI代表该进程的nice值

新PRi = 旧PIR + nice

nice的取值范围是-20 到 19共40个级别。PRI值越小,代表优先级越高。在Linux下,可以通过调整nice值来调整优先级。

我们可以通过top指令更改进程的nice值,方法如下:

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

其他概念:

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

2.环境变量

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

常见的环境变量:PATH,HOME,SHELL

PATH:指定命令的搜索路径

image-20220625001230098

ls 这条命令其实也是一个可执行程序,myproc也是一个可执行程序,我们如果要运行myproc,必须要加"./" , 这是因为我们在执行一个程序必须要先找到他,可是为什么ls不需要加“./”就能找到他呢呢,这就是环境变量PATH起的作用。他帮助操作系统找到了ls的位置。

image-20220625001938755

通过echo $PATH 可以查看PATH有哪些路径,当我们ls回车的时候,操作系统会在上面每一个:分隔的路径下寻找ls可执行程序。

如果我们想运行myproc像ls一样不加“./”就能运行,那我们可以把myproc,拷贝到PATH上面的路径下即可。或者,我们可以把myproc所在目录添加到PATH。具体操作如下

image-20220625003016277

HOME:保存当前用户所处的工作目录

image-20220625003631038

SHELL:命令行解释器,echo $SHELL 可以查看我们当前系统使用的是哪一款命令行解释器

image-20220625004119735

与环境变量相关的命令:

  1. echo: 显示某个环境变量值

  2. export: 设置一个新的环境变量

  3. env: 显示所有环境变量

    image-20220625004340146

    以上都是系统设置的环境变量

  4. unset: 清除环境变量

  5. set: 显示本地定义的shell变量和环境变量

    我们可以自己定义本地变量,但是env是不显示本地变量的,需要set才能显示出来

    本地变量只在本进程(bash)有效

    image-20220625005124187

    我们可以通过export导入一个环境变量,这样env就可以显示了

    image-20220625005401519

    那么如果我们想取消刚刚导入的那个环境变量MYVAL怎么办呢,unset MYVAL即可

3.main()函数的三个参数

image-20220625011431389

我们先说前两个参数,argv[]是一个指针数组,这个数组的char*指针的个数为argc。

image-20220625011647780

当我们这样运行这段代码,我们可以发现argc = 1;再看下面

image-20220625011826334

这是什么意思呢?

这里的 -a , -b, -c叫做命令行参数,如同ls命令后面可以加 -a, -l;

image-20220625012544433

char* envp[]存放的是环境变量信息;结构如下

image-20220625013100846

那我们如何打印环境变量呢?

image-20220625014307952

当我们运行这段代码就可以得到环境变量;

下面这段也可以

image-20220625022111124

也可以通过getenv()获取

image-20220625022736566

环境变量是一个系统级别的环境变量,bash之下所有进程都可以获取

4.进程地址空间

当我们在学习c语言的时候,一定对下面的这张图非常熟悉。

image-20220625193959901

接下来我们先写一段代码对上图进行一下验证

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <string.h> 

int g_unval;//未初始化全局数据
int g_val = 100;//已初始化全局数据
int main(int argc, char* argv[], char* envp[])
{
  printf("code addr: %p\n", main);//函数名就是代码起始地址
  char* str = "hello world";//"hello world"在字符常量区
  printf("read only addr: %p\n", str);

  printf("init addr: %p\n", &g_val);
  printf("uninit addr: %p\n", &g_unval);
  
  //堆区
  int* p1 = malloc(10);
  int* p2 = malloc(12);
  printf("heap addr: %p\n", p1);
  printf("heap addr: %p\n", p2);

  //栈区
  printf("stack addr: %p\n", &p2);
  printf("stack addr: %p\n", &p1);
  
  //这里我们再测试一下命令行参数的地址                                                                                                                 
  for(int i = 0; i < argc; i++)
  {
    printf("args addr: %p\n", argv[i]);//ls -a -l 
  }

  int i = 0;
  while(envp[i])
  {
    printf("envp addr: %p\n", envp[i]);
    i++;
  }
  return 0;
}      

结果如下,与上图吻合

image-20220625202657148

下面我们再来看这样一段代码

#include <stdio.h>                                                                                                                     
#include <stdlib.h>
#include <malloc.h>
4#include <string.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>

int g_val = 100;
int main()
{
  pid_t id = fork();
if(id == 0)
  {
    //子进程
    g_val = 200;
    printf("child: pid: %d, ppid: %d, g_val: %d, g_val addr: %p\n", getpid(), getppid(), g_val, &g_val);
  }
  else
  {
    //父进程
    sleep(2);
    printf("father: pid: %d, ppid: %d, g_val: %d, g_val: %p\n", getpid(), getppid(), g_val, &g_val);                                                                        
  }
  return 0
}

运行结果如下

image-20220625204403354

我们再子进程里面修改了g_val的值

我们可以看到的是,对于全局变量g_val的地址,父子进程是一样的,可是g_val的值却是不同的。这说明这个地址绝对不是真是的物理地址,而是虚拟地址。我们再语言层面上看到的地址都是虚拟地址。父子进程的g_val值不同,也是我们所希望看到的,因为这保证了进程间的独立性,互不影响

至于为什么发生这样的结果,看了下面这张图,你就明白了

image-20220625210545193

进程地址空间在内核中是一个数据结构类型,含有描述进程的地址空间变量,Linux下进程地址空间用一个结构体来描述——mm_struct。在32位操作系统下面,我们可以将mm_struct看成一把有刻度的尺子,从0x00000000到0xFFFFFFFF。这一串叫做虚拟地址。无论真正的内存有多大,mm_struct都把他分成从0x00000000到0xFFFFFFFF这么多份。比如说你要把一个长度等分成10份,那么如果总长为10米,每一份就是1米,如果总长为100米,那么每份的长度就是10米

image-20220629144957944

  • 什么叫做创建进程?

    task_struct,mm_struct,页表。(之后会继续完善)

  • 为什么要有地址空间?

    从此以后不会有任何系统级别的越界问题存在了。

    1.进程虚拟地址空间+页表,本质功能之一:保护内存!

    2.每个进程都认为看到的是相同的空间范围(构成+顺序)

    3.每个进程都认为自己在独占内存,更好地完成进程独立性以及合理的使用空间,将进程调度和内存管理进行解耦。

Cj-1656488144536)]

  • 什么叫做创建进程?

    task_struct,mm_struct,页表。(之后会继续完善)

  • 为什么要有地址空间?

    从此以后不会有任何系统级别的越界问题存在了。

    1.进程虚拟地址空间+页表,本质功能之一:保护内存!

    2.每个进程都认为看到的是相同的空间范围(构成+顺序)

    3.每个进程都认为自己在独占内存,更好地完成进程独立性以及合理的使用空间,将进程调度和内存管理进行解耦。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

逃跑的机械工

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

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

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

打赏作者

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

抵扣说明:

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

余额充值