栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Linux篇9进程2

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Linux篇9进程2

1.进程优先级

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

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

其中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:指定命令的搜索路径

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

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

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

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

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

与环境变量相关的命令:

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

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

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

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

  4. unset: 清除环境变量

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

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

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

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

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

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

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

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

这是什么意思呢?

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

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

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

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

下面这段也可以

也可以通过getenv()获取

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

4.进程地址空间

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

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

#include 
#include 
#include 
#include 
#include  

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

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

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

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

结果如下,与上图吻合

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

#include                                                                                                                      
#include 
#include 
4#include 
#include 
#include 
#include 

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: %pn", getpid(), getppid(), g_val, &g_val);
  }
  else
  {
    //父进程
    sleep(2);
    printf("father: pid: %d, ppid: %d, g_val: %d, g_val: %pn", getpid(), getppid(), g_val, &g_val);                                                                        
  }
  return 0
}

运行结果如下

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

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

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

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

  • 什么叫做创建进程?

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

  • 为什么要有地址空间?

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

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

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

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

Cj-1656488144536)]

  • 什么叫做创建进程?

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

  • 为什么要有地址空间?

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

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

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

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

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/998729.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号