进程与环境变量

预备知识

冯诺依曼体系结构

在这里插入图片描述

可以看出:
1.站在硬件角度和数据层面上,CPU只和内存“交流”,外设只和内存"交流"
2.数据要处理必须预装载到内存,局部性原理,这个过程由OS完成

这就回答了为什么程序运行之前要加载内存?
程序本质上是文件,位于硬盘(外设)上,想到CPU运行,必须经过内存

操作系统介绍

操作系统:软硬件资源的管理者
在这里插入图片描述

操作系统不会和软硬件打交道,通过驱动拿到资源(数据)
操作系统要对拿到的数据管理必须先描述再组织

描述:用结构体来对其描述
组织:选用适宜的数据结构存储

所以操作系统对软硬件的管理转化为对数据,数据结构的管理

进程

概念:正在执行的程序

进程与程序:
可执行程序位于磁盘,将程序读入内存中并分配内核数据结构(组织)后,就成为了进程

PCB(struct):进程控制块,用来描述进程,操作系统通过管理PCB来管理进程
在这里插入图片描述
在这里插入图片描述
所以对进程的管理就转化成对链表的增删查改

Linux操作系统下的PCB是: task_struct
在这里插入图片描述

标示符: 描述本进程的唯一标示符,用来区别其他进程。
状态: 任务状态,退出代码,退出信号等。
优先级: 相对于其他进程的优先级。资源有限。
程序计数器: 程序中即将被执行的下一条指令的地址。保存程序运行到哪里。
内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针。
上下文数据: 进程执行时处理器的寄存器中的数据。保存与恢复的过程。
I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。

进程相关的系统调用

getpid()

在这里插入图片描述
示例:在这里插入图片描述
在这里插入图片描述

只需要取消sleep和打印就可以让CPU一直运行此时处于运行状态
在这里插入图片描述

在这里插入图片描述

fork

功能:创建子进程
在这里插入图片描述

1.fork之前代码被父进程执行,之后就有两个执行流
2.fork有两个返回值,父进程的fork返回子进程id,子进程返回值是0
3.fork之后,父子进程代码共享,数据各自开辟空间,私有一份(采用写时拷贝

示例:
在这里插入图片描述

在这里插入图片描述

进程的状态

进程的状态储存在task_struct中

①R状态

R状态不代表正在运行!

在这里插入图片描述

②S状态

浅度睡眠:对应挂起和阻塞状态,等待某种条件就绪
随时可以被唤醒和杀掉

③D状态

深度睡眠:无论如何,进程不会被杀掉,只有自己主动唤醒,才可以恢复

④T状态

暂停状态:
在这里插入图片描述
用SIGSTOP暂停进程,SIGCONT唤醒在这里插入图片描述
在暂停信号后,如果我们向进程发送2号信号杀死进程,此时进程仍然存在,在唤醒后才被杀死
在这里插入图片描述

在S状态下是可以响应信号并处理的
在T状态下是不会处理信号的,只有在唤醒过后才会处理

⑤Z状态

僵尸状态:进程退出,在系统层面,曾经申请的资源并不是被立即释放,而是要暂存一段时间,供OS(父进程)进行读取,这种状态就叫僵尸状态

当进程退出并且父进程(使用wait()系统调用)没有读取到子进程退出的返回代码时就会产生僵尸进程

特点:
僵尸进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码

为什么要有僵尸状态?
因为我们需要知道一个进程完成任务,完成的怎么样

如何知道进程完成的怎么样?
通过进程的退出信息(退出码),被暂时保存在task_struct中,如果没人有读取,task_struct就不会被释放掉,这时处于Z状态。

模拟实现僵尸进程
在这里插入图片描述
在4s后子进程退出后,父进程并没有获取其退出信息,进程处于僵尸状态在这里插入图片描述

僵尸进程危害:
1.上面我们知道如果子进程退出后,父进程一直没有读取其退出信息,进程会一直处于Z状态,OS会一直维护其数据(PCB),占用内存
2.如果创建了许多创建了许多子进程,空间得不到回收就会造成资源浪费,内存泄漏

⑥X状态

进程被读取完信息立刻释放相关资源,变成X状态,这个状态只是一个返回状态,你不会在任务列表里看到这个状态

孤儿进程

父进程退出,子进程还在运行,该子进程就叫孤儿进程

此时如果子进程退出后,就是僵尸进程(无人回收),造成内存泄漏
所以在父进程退出后,子进程立即被系统领养(1号进程),来防止内存泄漏

在这里插入图片描述
在这里插入图片描述

可以看到在父进程退出时,子进程ppid变成了1,并且子进程在后台运行,杀死进程后资源被OS回收

进程优先级

cpu资源分配的先后顺序,就是指进程的优先权,cpu资源有限,可以改善系统性能

在这里插入图片描述

UID : 代表执行者的身份
PID : 代表这个进程的代号
PPID :代表这个进程是由哪个进程发展衍生而来的,亦即父进程的代号
PRI :代表这个进程可被执行的优先级,其值越小越早被执行
NI :代表这个进程的nice值,表示进程可被执行的优先级的修正数值

调整进程的优先级本质是调整nice值:PRI(new)=PRI(old)+nice
nice其取值范围是-20至19,一共40个级别

用top命令更改已存在进程的nice

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

向上最多能调到19,向下最多-20
每次调整PRI(old)都等于80

在这里插入图片描述

renice -优先级 进程ID

用renice命令在命令行调整进程ID
在这里插入图片描述

进程地址空间

进程地址空间是内存中的一种内核数据结构:mm_struct

该数据结构划分了物理内存,将物理内存虚拟抽象成了一个结构体,并在该结构体上划分了几个区域,通过页表映射到物理内存
在这里插入图片描述

磁盘中的程序:在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
1.可以看到该地址一定不是物理地址,是虚拟地址,在语言层面上见到的都是虚拟地址

2.所以物理地址一定存放的是独一无二的数据,而虚拟地址可以存放重复的数据

3.父子进程输出的变量不是同一个变量

۞

所以现在我们知道创建进程需要创建结构体task_struct,mm_struct以及页表

进程地址空间的必要性

1.虚拟地址空间+页表:保证了不会存在系统级别(访问物理内存)的越界问题,保护了内存
当存在越界时,OS会检查页表是否有映射,如果没有判定为越界,杀死进程;此时进程并没有访问到右侧真实的物理内存,不会让进程访问不属于你的空间,就不会产生越界问题

2.规定了标准
每个进程的地址空间都是相同的,在找进程某一区的时候,都会默认到规定的区域中寻找

3.每个进程都认为自己独占内存,能更好地合理使用空间以及实现进程的独立性
在这里插入图片描述

环境变量

环境变量一般是指在操作系统中用来指定操作系统运行环境的一些参数,这个变量与操作系统的环境有关

在系统当中通常具有全局特性

在这里插入图片描述

1.常见环境变量

PATH:指定命令的搜索路径

此时环境变量储存的是路径,告诉操作系统在哪里去找
在这里插入图片描述
在这里插入图片描述
这种拷贝做法并不推荐容易对环境变量造成污染

方法二:将当前目录添加到环境变量PATH
在这里插入图片描述
PATH在每次启动后会重新生成,先前的修改就不见了

HOME : 指定用户的主工作目录(即用户登陆到Linux系统中时,默认的目录)

不同的用户工作目录是不同的
在这里插入图片描述

SHELL : 当前Shell,它的值通常是/bin/bash,查看Shell

在这里插入图片描述

  1. echo: 显示某个环境变量值
  2. export: 设置一个新的环境变量
  3. env: 显示所有环境变量
  4. unset: 清除环境变量
  5. set: 显示本地定义的shell变量(本地变量,只在本bash有效)和环境变量

2.命令行参数

在这里插入图片描述
可以通过传入的命令行参数产生不同的效果
在这里插入图片描述
在这里插入图片描述

3.环境变量参数

结构类似于命令行参数
在这里插入图片描述
**加粗样式**
获取系统提供的环境变量
在这里插入图片描述
看出环境变量是一个系统级别的全局变量

bash 之下所有进程都可以通过传入的环境变量参数获取此时的环境变量
在这里插入图片描述
用全局变量environ获取环境变量在这里插入图片描述在这里插入图片描述
用getenv函数获取指定名字的环境变量在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/hbbfvv1h/article/details/121741788
今日推荐