• LInux-4-进程地址空间


    前言

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

    进程优先级

    相关概念:

    • 优先级含义:

      CPU资源分配的先后顺序

    • 优先级作用:

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

    • 进程竞争性:

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

    • 进程独立性:

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

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

    • 进程切换:

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

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

    • 进程切换的时机:

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

    查看优先级:

    查询指令:

    • 查看PCB信息指令:

      ps -l					//粗略几个进程的信息,如bash + ps
      ps -la					//详细所有进程的信息
      
      • 1
      • 2
    • 查看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值	//调整指定进程的优先级 
      
      • 1
      • 2
    • top:查看进程管理器
      Linux进程管理器

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

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

    法二:renice

    • renice 命令:

      renice -n 进程pid 新的nice值
      
      • 1

    环境变量

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

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

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

    相关概念:

    • 环境变量的含义:

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

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

    • 组成:

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

    • 全局性:

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

    • 举例:

      编译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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • ls命令程序的存储位置:在PATH内
      user/bin/ls存储在PATH下

    HOME:

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

    SHELL:

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

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

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

    • 查看SHELL:
      SHELL

    环境变量相关命令:

    查看所有环境变量:

    • env:
    env
    
    • 1

    查看所有变量:

    • Linux下变量包括环境变量 + 本地变量
    set				//查看环境变量 + 本地变量
    
    • 1

    查看单一环境变量:

    • echo + 环境变量名:
    echo $PATH
    
    • 1

    添加环境变量:

    • 法一:复制粘贴
    sudo cp -f 文件 PATH中某一路径	//删除刚才向PATH添加的myproc
    
    • 1
    • 法二:export
    export PATH=$PATH:新路径			//$PATH为保持原有路径
    
    • 1

    删除PATH中文件:

    • rm删除
    sudo rm /usr/bin/文件名		//删除刚才向PATH添加的文件
    
    • 1
    • 关机重启:

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

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

    增删本地变量:

    • 本地变量的作用域:

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

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

    显示器终端文件:

    • dev/pts:代表当前显示器开的所有窗口
    • 向此云服务器其他用户窗口发送信息:
    //先查看其他用户窗口号:
    who
    
    //再登录root权限
    su -
    
    //再给其他用户发送消息
    echo "消息" > /dev/pts/终端号
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    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就是命令行参数
      
      • 1

    envp:

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

    • 来源:

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

    • 查看envp内容:

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

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

    • 函数:

      #include 
      char* getenv(const char *name);					//通过名称获取环境变量
      char* secure_getenv(const char *namr);			//通过名称获取环境变量
      
      • 1
      • 2
      • 3
    • 实例:
      getenv()

    • 输出:
      环境变量:路径

    进程地址空间

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

    进程地址空间布局:

    • 每个进程创建后,真实内存都给予他一个虚拟内存空间,便于进程创建变量/保存数据/进行计算
    • 这块固定大小的虚拟内存空间叫做进程地址空间,其组成布局如下:
      进程地址空间布局
    • linux中查看进程地址空间布局:
      1. 代码:
        各种类型地址空间
      2. 输出:从正文代码地址到栈变量地址到环境变量地址,地址应该是从低到高的
        低到高

    虚拟地址:

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

    父子进程地址空间:

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

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

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

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

    • 图解父子进程的虚拟地址:
      父子进程的虚拟地址

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

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

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

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

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

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

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

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

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

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

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

  • 相关阅读:
    web自动化测试详细流程和步骤
    bin-editor-next实现josn序列化
    微前端qiankun接入Vue和React项目
    bootstrap treeview基本用法+横向显示
    提升写作效率:ChatGPT助力学术论文撰写
    你能猜出这是什么代码
    多线程案例(单例、阻塞队列、生消模型、定时器)
    使用TCP方式拉取Canal数据
    阿里P8熬了一个月肝出这份32W字Java面试手册,在Github标星31K+
    什么是跨站请求伪造(CSRF)攻击?如何防止它?
  • 原文地址:https://blog.csdn.net/buptsd/article/details/126061218