LInux-4-进程地址空间

前言

Vue框架:Vue驾校-从项目学Vue-1
算法系列博客友链:神机百炼

进程优先级

相关概念:

  • 优先级含义:

    CPU资源分配的先后顺序

  • 优先级作用:

    可以将指定进程运行到指定的CPU上(上下文切换次数少了),以改善多任务环境的linux的系统性能

  • 进程竞争性:

    系统进程数目众多,CPU计算资源有限

  • 进程独立性:

    一个进程在运行时,独享各种资源(网络带宽/CPU算力),其他进程不干扰

    考虑进程独立性,父子进程有时共享程序和数据,有时子进程需另开辟程序和数据,下面的进程地址空间将会展开说

  • 进程切换:

    当进程数目太多时,CPU切换进程的成本没有增加

    但是在应用层看来,会有卡顿的感觉

  • 进程切换的时机:

    1. 多数情况:PCB的时间片到期
    2. 少数情况:更高优先级的进程到来

查看优先级:

查询指令:

  • 查看PCB信息指令:

    ps -l					//粗略几个进程的信息,如bash + ps
    ps -la					//详细所有进程的信息
    
  • 查看PCB的优先级:
    PCB优先级

PRI&NI:

  • PRI:当前优先级,默认为80

    值越小则越先执行,范围为[60 , 99]

  • NI:Nice值,对优先级的修正数值,默认为0

    有正有负:从-20 ~ 19,共40级,输入-100自动-20,输入100自动19

    调整优先级其实是在调整NI值,且每次都是在80的基础上调节

调整优先级:

法一:top调整

  • linux的任务管理器:

    top							//查看所有进程
    top 输入r 输入pid 输入nice值	//调整指定进程的优先级 
    
  • top:查看进程管理器
    Linux进程管理器

  • top + r + pid + nice:修改进程优先级
    top + r + pid + nice

  • 尝试改动nice为-20后,再查看PCB信息:
    -20nice的pcb

法二:renice

  • renice 命令:

    renice -n 进程pid 新的nice值
    

环境变量

  • 引导问题:
    为什么我们写的程序要运行需要加./
    而Linux自带的命令程序要运行不需要加./?
./mytest.c			
//运行我们自己写的程序要带./才能找到
ls					
//运行系统指令不需要带./就能找到
llll 
//报错:command not found,说明命令行也是经过查找才找到的
  • 命令本身也是程序,存储在环境变量中

    所有可执行程序在运行前都在环境变量中查询源程序

    环境变量中查询不到,再根据给定的路径寻找源程序

相关概念:

  • 环境变量的含义:

    操作系统启动后,某些内容没有启动,需要后续启动

    后续启动前要先找到这些程序,就需要设定一些变量记录这些程序的路径

  • 组成:

    变量名 + 变量内容(与操作系统环境有关)

  • 全局性:

    环境变量就是系统级别的全局变量

  • 举例:

    编译c / c++代码时,链接时我们不知道所链接的动态库和静态库在哪个文件夹下,但是仍然可以找到动静态库,并且编译成功

常见的环境变量:

PATH:

  • 含义:常用的文件夹
  • 查看PATH:
echo $PATH						//查看PATH内容,其实是:隔开的很多路径
/usr/local/jdk8/bin:
/usr/local/jsk8/jre/bin:
/usr/local/bin:
/usr/bin:
/usr/local/sbin:
/usr/sbin:
/home/whb/.local/bin:
/home/whb/bin
  • ls命令程序的存储位置:在PATH内
    user/bin/ls存储在PATH下

HOME:

  • 含义:当前用户所处的工作目录
    HOME

SHELL:

  • 我们并不与Linux内核直接交互,而是通过shell:

    输入的命令通过shell命令解释器之后交给kel

  • 命令解释器也是一个程序,有很多版本,SHELL变量记录我们采用的版本

  • 查看SHELL:
    SHELL

环境变量相关命令:

查看所有环境变量:
  • env:
env
查看所有变量:
  • Linux下变量包括环境变量 + 本地变量
set				//查看环境变量 + 本地变量
查看单一环境变量:
  • echo + 环境变量名:
echo $PATH
添加环境变量:
  • 法一:复制粘贴
sudo cp -f 文件 PATH中某一路径	//删除刚才向PATH添加的myproc
  • 法二:export
export PATH=$PATH:新路径			//$PATH为保持原有路径
删除PATH中文件:
  • rm删除
sudo rm /usr/bin/文件名		//删除刚才向PATH添加的文件
  • 关机重启:

    云服务器的xshell每次重新连接,PATH内容自动复原

    最好不要随意向PATH等全局变量中添加自己的程序,容易污染命令池

增删本地变量:
  • 本地变量的作用域:

    只在本进程内有效,command line内输入后,作用域也就是bash进程内

    MYVAL = 100				//添加本地变量
    
    env | grep MYVAL		//在环境变量中查询为空
    
    set | grep MYVAL		//在所有变量中可以查到100
    
    export	MYVAL = 100		//将本地变量导入环境变量
    
    export MYVAL			//本地变量也是可以直接使用的,直接一个名字就可以导入环境变量
    
    unset	MYVAL			//从本地变量中删除MYVAL
    

显示器终端文件:

  • dev/pts:代表当前显示器开的所有窗口
  • 向此云服务器其他用户窗口发送信息:
//先查看其他用户窗口号:
who

//再登录root权限
su -

//再给其他用户发送消息
echo "消息" > /dev/pts/终端号

main()参数的环境变量:

  • C/CPP代码中的main()函数也可以接收参数:
    agrv 和 envp都是指针数组,最后一个元素都是NULL
    在这里插入图片描述

  • OS调用加载器 ,加载器调用mainCRTStartup()函数,mainCRTStartup()函数调用main()函数

    操作系统一方面通过argv & envp为main()函数提供信息
    另一方面通过僵尸进程接收main()函数运行完后return 的 0

argc & argv:

  • 含义:

    1. int argc:控制台输入的命令行参数个数
    2. char* argv[]:控制台输入的命令行参数
  • 举例查看argc & argv:

    1. 代码:
      代码
    2. 输入输出:
      输入输出
  • 内存调用:
    argv的内存调用

  • argv的应用:

  1. 代码:
    agrv
  2. 输出:
    argv控制输出
  • 举例:

    ls -a -l 			//此处的ls是命令,a & l就是命令行参数
    

envp:

  • 含义:程序运行时依赖的环境变量

  • 来源:

    1. argc & argv的输入来源于OS自带的内容 / 控制台命令行输入
    2. envp的输入来源于OS自带的所有环境变量
  • 内存调用: envp的内存调用

  • 查看envp内容:

    1. 代码:envp[]最后也是一个NULL
      envp[]
    2. 输出:其实就是PATH等等环境变量的内容
      enip内容

系统调用接口获取环境变量:

  • 函数:

    #include <stdlib.h>
    char* getenv(const char *name);					//通过名称获取环境变量
    char* secure_getenv(const char *namr);			//通过名称获取环境变量
    
  • 实例:
    getenv()

  • 输出:
    环境变量:路径

进程地址空间

  • 研究背景:
    kernel 2.6.32
    32位平台

进程地址空间布局:

  • 每个进程创建后,真实内存都给予他一个虚拟内存空间,便于进程创建变量/保存数据/进行计算

  • 这块固定大小的虚拟内存空间叫做进程地址空间,其组成布局如下:
    进程地址空间布局

  • linux中查看进程地址空间布局:

    1. 代码:
      各种类型地址空间
    2. 输出:从正文代码地址到栈变量地址到环境变量地址,地址应该是从低到高的
      低到高

虚拟地址:

  • 为了便于进程内部支配变量和数据,进程中所有地址都是虚拟地址,不是内存条上的真实地址
  • &变量:取出的是虚拟地址
int a = 10;
printf("%p", &a);			//&a是变量a在该进程中的地址,不是在内存条中的
  • 页表:记录虚拟地址到真实内存条地址的映射关系

父子进程地址空间:

  • 不同进程之间为了保证运行的独立性,一般来说各自的虚拟进程地址空间布局使用情况不同

    但是父子进程之间,子进程会直接使用父进程的代码和数据

    为了保证父子进程之间仍保持独立性,当子进程对父进程的代码或者数据做出更改后

    该数据或者程序会被单独拷贝出来一份供子进程使用,同时子进程的虚拟地址在页表中对应的实际地址发生改变

  • 图解父子进程的虚拟地址:
    父子进程虚拟地址空间关系

  • 为什么子进程不直接拷贝父进程的所有程序和数据?

    当子进程只读不写时,还要为子进程单独创立一套数据就属于浪费空间

  • 举例说明父子进程存在数据不同时,同一虚拟地址对应页表中真实地址不同:

    1. 代码:
      父子进程内存差异
    2. 输出:
      父子进程内存差异实例
    3. 解释:
      1. 父子进程一开始共享父进程的程序和数据,包括g_val变量

        也就是父子进程此时页表的虚拟地址和真实地址对应关系同

      2. 子进程修改父进程程序中g_val数据后

        内存中为子进程新建一个g_val变量,值为200

        同时修改子进程页表,将原本g_val虚拟地址对应的真实地址改为新建的变量地址

      3. 最终父子进程中对于g_val的虚拟地址相同

        但是页表中映射的真实地址不同

      4. printf(“%p\n”, &g_val);取出来的是进程的虚拟地址

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

starnight531

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

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

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

打赏作者

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

抵扣说明:

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

余额充值