进程、环境变量和程序地址空间

进程

进程实际上是操作系统对一个运行中的程序的描述----pcb,通过这个描述信息可以实现对程序的运行调度和管理,linux下这个pcb就是一个task_struct结构体

为什么需要对程序的运行进行调度和管理呢?这就需要了解cpu的运行机制。

cpu分时机制:操作系统调度每一个程序只在cpu上处理一段很短的时间(这个时间段称之为:时间片),然后就切换到下一个程序。通过这种机制,实现了多任务并发(轮询调度执行)/并行(同时)处理

程序描述信息–pcb

程序的描述信息(pcb)中都包含哪些信息?

  • 内存指针:指向要调度运行程序代码以及数据在内存中的位置
  • 程序计数器:cpu要执行任何指令,都需要将指令加载到寄存器;程序计数器用于保存在cpu上即将执行的下一步指令的地址
  • 上下文数据:保存cpu上正在处理的数据
  • 进程标识符:进程id----pid
  • 进程状态:不同状态干不同的事情
  • 进程优先级:决定获取cpu资源的优先级----为了让进程运行的更加良好用户体验更加良好

此外,pcb中还有IO信息、记账信息等等

创建和查看进程

进程创建:

pid_t fork(void);	//通过复制调用进程(父进程),创建一个新的进程(子进程)
  • 创建出来的子进程和原父进程内存指针一样:运行的代码一样
  • 创建出来的子进程和原父进程程序计数器一样:当前运行位置一样
  • 返回值:fork函数的返回值比较特殊。对于父进程来说,返回的是子进程的pid,是大于0的;对于子进程来说,返回的是0;通过这个返回值的不同,就可以实现父子进程代码分流。

利用fork创建子进程的作用:

  • 子进程与父进程干同样的事情,可以分摊压力提高效率
  • 父进程可以让子进程干其它事情,让子进程背锅

进程查看相关指令:

ps -ef				// 查看进程信息
ps -aux				// 查看更多的进程信息
ps -l				// 列出与本次登录有关的进程信息
ps -aux|grep xxx	// 查询xxx进程的详细信息
top   				// 查看内存中进程的动态信息
kill pid 			// 杀死指定pid的进程
kill -9 pid 		// 强制杀死指定pid的进程

linux下进程状态

  • 运行状态(R):正在运行/只要拿到时间片就能运行----这种进程调度到cpu上进行处理
  • 可中断休眠状态(S):当前处于休眠状态,但是这种休眠可以被打断----不被cpu调度;可还原到运行状态
  • 不可中断休眠状态(D):当前处于休眠状态,这种休眠不会被打断----不被cpu调度;可还原到运行状态
  • 停止状态(T):没有退出,但当前不再运行,什么都没做;可还原到运行状态
  • 僵死状态(Z):进程已经退出,但是资源没有被完全释放时所处的一种状态,一种等待后续被处理的状态,不可还原到运行状态

特殊的进程

  • 僵尸进程:进程退出了但是资源没有完全被释放----处于僵死状态的进程
    • 危害:资源泄露
      1.一个用户能够创建的进程是有限的(-ulimit -a查看),僵尸进程过多会导致创建新的子进程失败
      2.内存资源(内核中的pcb)没有被回收
    • 产生:子进程先于父进程退出,但是父进程没有进行进程等待,无法获取子进程退出状态,导致子进程资源无法完全释放,成为僵尸进程(子进程退出,操作系统就要封锁线程,子进程的退出原因保存在自己的pcb中;因此操作系统也不能直接回收子进程资源,而是通知父进程,但父进程没有关注到操作系统的通知,因此导致子进程退出了但是资源没有完全释放)
    • 避免:父进程等待子进程退出(进程等待)
  • 孤儿进程:父进程先于子进程退出,子进程就会成为孤儿进程,运行在后台;父进程成为1号(init或systemd)进程
  • 守护进程:也叫精灵进程,是一个特殊的孤儿进程。它脱离了终端(运行在后台),脱离了登录会话(不属于本次登陆期间所运行的进程),为了让进程完全不受影响的运行在后台(通常服务器程序都是守护进程,默默地运行在后台不受影响的完成循环往复的事情)

环境变量

存储/设置系统运行环境参数的变量,可以使系统运行环境的配置更加灵活(直接设置直接生效,不用再去修改配置文件,重新加载配置文件)

环境变量的命令操作

env			// 查看所有的环境变量
echo		// 查看所有的变量,包括环境变量
set			// 打印某一个环境变量的值
export		// 设置环境变量
unset		// 删除环境变量,不仅会删除环境变量也会删除普通变量

环境变量的代码操作

终端中的进程都能访问到环境变量,因此可以通过设置环境变量向进程传递数据

  • 程序的运行参数:在运行程序的时候赋予,在程序名称后边以空格进行间隔 ./main -a -c -d

查看环境变量:

int main(int crgc, char* argv[],char* env[])	// 通过main函数第三个参数获取
extern char **environ;		// 声明一个全局变量environ,可以让这个指针指向环境变量,再通过这个全局变量进行访问
char* getenv(const char* name)		// 通过环境变量名称,获取环境变量的值

设置环境变量:

int putenv(char* string)		// 通过代码设置一个环境变量
int setenv(const char* name,const char* value,int overwrite)	// 通过代码设置一个环境变量(会询问是否覆盖)

程序地址空间

程序地址空间更应该叫做进程的虚拟地址空间

虚拟地址空间

虚拟之地址空间是操作系统通过mm_struct结构体为进程所描述的一个虚假的、线性(连续)的地址空间,空有编号但不具备存储功能
在这里插入图片描述

  • 虚拟地址空间,可以让进程使用连续的虚拟地址,通过页表映射,实现在物理内存上的离散式存储,提高内存利用率;并且通过页表也可以实现内存访问控制,进一步提高进程独立性

  • 页表:映射虚拟地址与物理地址的关系,提供内存访问控制(访问权限标志位)

  • 物理内存包括:代码段、初始化全局数据段、未初始化全局数据段、堆、共享区、栈、参数和环境变量、内核空间

  • 实际上我们在进程中访问到的地址都是虚拟地址,并不是物理内存的单位编号,程序地址空间实际上是一个虚拟地址空间

虚拟地址空间的作用

  • 若直接访问物理内存,会造成大量内存碎片,对内存利用率太低;进程访问虚拟地址通过页表映射物理地址,可以在物理内存上实现离散式存储,提高了内存利用率
  • 若直接访问物理内存,缺乏内存访问控制,通过页表可以实现地址访问控制
  • 每个进程都有自己的虚拟地址空间映射到物理内存,保证了进程的独立性(不影响其它进程)

页表与虚拟地址空间的映射

页表如何映射虚拟地址和物理地址、如何通过虚拟地址找到物理内存?

  • 操作系统中的内存管理方式:分段式/分页式/段页式

分页式:将虚拟地址进行分页管理,通过页表映射虚拟地址页和物理内存块之间的关系,用于实现数据在物理内存上的离散式存储,提高内存利用率,也可实现访问控制

  • 虚拟地址的组成:页号+页内偏移量
    • 页号:分页式内存管理时,将整体虚拟地址分成了一个个小的内存页面(4096字节)
    • 页内偏移:一个变量的数据存储相对于页面起始位置的偏移量
  • 页表中的信息:物理块地址号+访问权限位+缺页中断位
  • 优点:对内存的利用率比较好

分段式:将虚拟地址进行分段管理,根据使用的性质将地址空间进行分段:代码段、数据段、堆、栈、参数、环境变量等等

  • 虚拟地址的组成:段号+段内偏移量
  • 段表中的信息:物理内存段起始地址
    • 在操作系统中有一个段表,表中包含:虚拟段号、物理内存段起始地址
    • 通过虚拟地址中的段号,在段表中找到相应的段表项,得到物理段起始地址,加上段内偏移量最终得到物理地址
  • 优点:对编译器/程序员的内存地址管理比较友好

段页式:将虚拟地址进行分段,在段内进行分页式管理

  • 虚拟地址组成:段号+段内页号+页内偏移
  • 段表中包含:段内页表起始地址
  • 段内页表中包含:物理块号
    • 通过段号在段表中找到内存段对应页表地址,根据地址找到页表,通过段内页号找到页表项,得到物理起始地址(物理块号)加上页内偏移
  • 优点:兼具分页式与分段式的优点

缺页中断

一个进程在通过虚拟地址访问物理内存中的数据时,发现自己的数据不在物理内存中,就会触发缺页中断

  • 数据为什么没在物理内存中??
    当内存不够用时,操作系统按照一定的算法将内存中的一些数据拷贝到交换分区1中进行存储,以腾出内存处理新的数据;此时交换出去的数据就不在内存中了,如果再来访问这些数据就会触发缺页中断,需要重新到交换分区中将数据交换回来。通常内存在16G以内时,交换分区的大小是内存的两倍。16G以上时通常和内存大小一样

LRU算法:一种内存置换算法(最近最久未使用)----内存不够用时将内存中最近最久未使用的数据拷贝到交换分区上,腾出内存空间


  1. 交换分区:在装系统进行磁盘分区时就确定(一直存在) ↩︎

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值