🌈 个人主页:谁在夜里看海.
⛰️ 丢掉幻想,准备斗争
目录
一、查看进程字段
在Linux下,可以使用ps指令显示当前系统运行的进程信息,包含进程状态、资源使用情况等内容ps的-l选项可以显示长格式信息,包括F(标志)、S(状态)、UID、PID等详细字段:
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
1.字段说明
下面是对字段的解释说明:
字段 | 含义 |
F | 标志位(Flags)。与进程状态和调度相关的标志,常见值: - - |
S | 进程状态(State)。表示进程当前的状态,可能的值: - R :运行(Runnable)- S :睡眠(Sleeping)- D :不可中断睡眠(Uninterruptible Sleep)- Z :僵尸进程(Zombie)- T :停止(Stopped) |
UID | 用户 ID(User ID)。表示运行此进程的用户的 ID,即执行者的身份 - - - |
PID | 进程 ID(Process ID)系统中每个运行进程的唯一标识符 |
PPID | 父进程 ID(Parent Process ID)表示创建该进程的父进程的 PID |
C | CPU 使用率(CPU utilization)表示进程使用 CPU 的相对时间(以百分比表示) |
PRI | 优先级(Priority)进程当前的调度优先级,数值越低优先级越高 |
NI | Nice 值(Niceness)影响进程优先级的用户调整值,范围为 -20 (最高优先级)到 19 (最低优先级) |
ADDR | 内存地址(memory address)与进程的内存映射相关,通常显示为 - ,表示不适用 |
SZ | 内存大小(Size)表示进程的虚拟内存大小(以页为单位) |
WCHAN | 等待通道(Wait Channel)如果进程正在等待资源或事件,则显示等待的内核函数名,否则为 - |
TTY | 终端(Terminal)表示与进程关联的终端设备名 - 如果是后台进程,可能显示为 ? |
TIME | CPU 时间(Time)表示进程运行以来累计使用的 CPU 时间(格式为 hh:mm:ss ) |
CMD | 命令名(Command)。表示启动该进程的命令。 |
2.进程优先级
PRI表示进程的优先级,PRI值越低则优先级越高,那么Nice值是什么呢?它是用来影响进程优先级的用户调整值,范围是-20~19:
加入Nice值后,将会使得PRI变为:PRI(new)=PRI(old)+nice
PRI越小进程越快被执行,因此如果加入正数Nice值,会使进程优先级降低;加入负数Nice值,会使进程优先级提高。
注意:Nice并不是进程优先级,它们不是一个概念,可以理解成Nice值是进程优先级的修正数据。
更改nice值
可以使用 renice
命令更改已存在进程的nice值:
renice <新nice值> -p <进程id>
二、环境变量
1.概念
环境变量一般是指在操作系统中用来指定操作系统运行环境的一些参数,例如:我们在编写代码的时候,从来不知道我们的动静态库在哪,但是仍然可以链接成功,生成可执行程序,原因就是有环境变量帮助编译器进行查找。环境变量在系统中具有全局特性。
配置进程和应用程序:
环境变量为系统提供了一些配置信息,如系统路径、语言设置、用户名等。程序通过读取这些变量来决定它们的行为方式。例如:操作系统通过 PATH 环境变量确定哪些目录包含可执行文件,进而决定执行哪个命令。
常见的环境变量:
名称 | 作用 |
PATH | 定义操作系统查找可执行文件的路径。当你在终端输入命令时,操作系统会在 PATH 中定义的路径下查找对应的可执行文件 |
HOME | 当前用户的主目录路径。例如,在 Linux 上是 /home/username |
USER | 当前登录的用户名 |
SHELL | 当前用户使用的 shell 类型,常见的有 bash 、zsh 等 |
PWD | 当前工作目录路径 |
TEMP | 存放临时文件的目录 |
测试:
分别在普通用户和超级用户下查看HOME:
2.指令与PATH
当我们在终端输入一个指令时(如ls),系统会执行相应的操作,并显示在终端,那么这个过程的本质是什么呢?我们在终端输入的指令实际上就是与操作系统交互的一种方式:
①:指令本质上其实是一个可执行文件,操作系统通过环境变量PATH查找对应的文件,PATH是一个包含一系列目录路径的环境变量,系统会按顺序在这些目录下寻找文件;
②:系统找到文件之后,会将文件加载到内存,文件内部以二进制形式存储,包含了操作系统能理解的指令(如机器码),通过解码实现相应的操作。
vim /bin/ls #查看bin目录下的ls命令(二进制文件)
我们编写的程序在编译之后最终也会变成一个二进制的可执行文件,然而该文件的目录路径默认并没有保存在PATH中,所以在终端输入test没有反应,原因就是系统找不到该文件(指令):
需要输入./test,显示说明test文件在当前目录下,系统才能找到文件,执行命令:
所以我们自己定义的test文件也可以看成是一个命令, 因为test文件的目录路径没有在PATH中保存,所以直接执行找不到,那么我们手动将路径加载到PATH中呢:
export PATH=$PATH:$(pwd) #将当前目录加载到PATH中
此时输入test应该是可以执行的,但实际上并没有执行,这是为什么呢?
通过echo查看PATH,发现test的目录路径确实已经加载进去了,那就是test文件本身的原因:
./test没有问题,test是可以被正常执行的,但是为什么输入test并没有执行呢?
test
是一个常见的 Shell 内置命令,主要用于执行条件测试(如 if
语句中的条件判断)。因此,当输入 test
时,Shell 会首先尝试执行内置的 test
命令,而不是文件系统中的可执行文件。
那我们修改一下文件名称,修改成ttt,这样就不会和内置命令冲突了 :
3.环境变量相关命令
在Linux中,有以下几种和环境变量相关的命令:
1. echo: 显示某个环境变量值
2. export: 设置一个新的环境变量
3. env: 显示所有环境变量
4. unset: 清除环境变量
5. set: 显示本地定义的shell变量和环境变量
env:
unset:
unset PATH #删除PATH
命令无法执行(由于删除了PATH,系统找不到该命令所在的路径了)
export:
export PATH=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/ywh/.local/bin:/home/ywh/bin
将PATH恢复之后,命令可以正常执行 。
三、程序地址空间
程序在内存中的存储是按照特定的结构进行存储的,一般遵循如下顺序:
我们用代码来验证一下:
通过上述示例我们感受到,程序在内存中的存储是严格遵循顺序的,操作系统这么设计的的目的是为了更高效地管理内存,实现内存的保护和分离
但是实际上的内存地址存储并不是有序的,要知道为什么,就得从内存存储的底层原理讲起:
1.物理内存
物理内存是由实际的硬件(如内存芯片)组成的,其存储空间是物理上分散的。内存芯片的组织结构(如 DRAM)本身就是分散的,这意味着内存中的每个存储单元并不按照程序或操作系统的需求排列在一起。内存是由多个内存模块和芯片组成的,它们的物理位置和布局通常是随机的,无法像我们上述所讲的那样在逻辑上进行整齐排列。
所以,程序地址空间并不是真正的物理内存,那么他究竟是什么呢?
程序地址空间是操作系统为每个进程提供的一种抽象视图,是虚拟内存:
2.虚拟内存
程序访问的地址并不是真实的物理地址,而是虚拟地址,由于物理地址的分块存储,没办法实现地址的有序性,而虚拟地址则不然,它可以连续存储,不需要考虑实际情况,但是虚拟地址终究只是一个抽象的概念,不能真正地存储数据,所以需要将虚拟地址与物理地址一一对应,就像一个键值对一样,将虚拟地址映射到物理地址:
虚拟地址与物理地址的映射是通过操作系统的虚拟内存管理机制和内存管理单元共同实现的。虚拟地址与物理地址的转换在页表中实现,
当CPU需要访问内存时,先将虚拟地址传输给内存管理单元,管理单元根据页表的映射关系得到对应的物理地址,根据物理地址找到物理内存进行相应的操作。
虚拟内存管理机制除了可以让内存存储变得有序,便于管理,还可以节省物理内存空间,提高存储效率,一个直观的表现就是,32位的处理器可以存储约4GB的内存空间,但是实际上其RAM存储器是小于4GB的,这是为什么呢?不同的虚拟地址可以映射相同的物理地址,写时拷贝就是一个典型的例子:
3.写时拷贝
当多个实体(如进程、线程或对象)需要共享一段数据时,初始阶段并不额外开辟空间,而是让它们共同指向一块物理空间。只有当某个实体需要修改数据时,才真正执行数据的拷贝操作。这样可以有效减少不必要的资源占用。
例如:当父进程创建一个子进程时,子进程需要继承父进程的一系列数据,在初始阶段,虽然他们的虚拟地址不同,但在页表中,它们映射的是同一块物理地址,只有在子进程需要修改数据时,才会相应地拷贝数据,开辟空间,修改映射关系。
以上就是【进程字段、环境变量与进程地址空间】的全部内容,欢迎指正~
码文不易,还请多多关注支持,这是我持续创作的最大动力!