Linux系统编程:(2)进程与进程内存布局

一、进程定义

进程是一个可执行程序的实例;从内核角度看,进程由用户内存空间和一系列内核数据结构组成,其中用户内存空间包含了程序代码代码所使用的变量,而内核数据结构则用于维护进程状态信息,记录在内核数据结构中的信息包括如下:

  • 与进程相关的标志号(IDs)
  • 虚拟内存表
  • 打开文件的描述符表
  • 信号传递及处理的有关信息
  • 进程资源使用及限制
  • 当前工作目录
  • 大量其他信息

运行进程相关的信息均在/proc/PID/xxx中可以查到

二、进程号

系统中每个进程都有一个唯一标识自己的进程号(PID,pid_t类型),可使用getpid()获取调用进程的进程号,每个进程都有一个自己的父进程,可以使用getppid()获取当前调用进程的父进程PID。所有进程一直往上找自己的父进程,都可以找到所有进程的鼻祖init进程(PID=1)。当父进程终止,其子进程就会变成孤儿进程,init进程就会收养该进程。

进程号分配原则
Linux内核显示进程号需要小于32767,新进程创建时,内核会按照顺序将下一个可用的进程号分配给新的进程使用,每当进程号达到32767的限制时,内核将重置进程号计数器,以便从小整数开始分配,一般重置为300,因为底数值的进程号长期被系统进程和守护进程长期占用,在此范围内搜索尚未使用的进程号只会浪费时间。最大进程号可以通过/proc/sys/kernel/pid_max文件来控制。

三、进程内存分段

在这里插入图片描述
c语言编程环境提供了3种全局符号:etext、edata和end,可以允许在程序内使用这些符号以获取相应程序的text段、data段和bss段结尾处下一个字节的地址,必须显示:extern char etext, edata, end;

在这里插入图片描述
在这里插入图片描述
其中,函数局部变量、参数及返回值均属于stack中。

四、进程虚拟内存管理

Linux像大多数现代内核一样,采用虚拟内存管理技术,该技术利用了大多数程序的一个典型特征,即访问局部性,以求高效利用CPU和RAM(物理内存)资源,大多数程序都展现了两种类型的局部性:

  • 空间局部性:指程序倾向于访问最近访问过的内存地址附近的内存
  • 时间局部性:指程序倾向于在不就的将来再次访问最近刚访问过的内存地址(循环)、

正是由于程序局部性,使得程序仅有部分内存地址空间存在于RAM中,依然能够正常执行。

虚拟内存技术将每个进程使用的内存切分成小型的、固定大小的“页(page)”单元,将RAM划分成一系列与虚拟内存页尺寸相同的“页帧”。任何时刻,每个进程仅有部分页需要驻留在物理内存页帧中,这些驻留的页构成了驻留集,进程未使用的页拷贝保存在交换区内----这是磁盘空间的保留区域,作为计算机RAM的补充,仅在需要的时候才会载入物理内存。若进程访问的页面目前尚不存在于物理内存,将会发生页面错误,内核会挂起进程的执行,同时从磁盘中将该页面载入内存。

为了满足上述的功能,内核需要为每个进程维持一张页表(page table),页表描述了每页在进程虚拟地址空间的位置(可为进程所有的虚虚拟内存页面的集合)。页表中的每个条目要么可以指出一个虚拟页面在RAM中的实际位置,要么表明其当前驻留在磁盘上。

在这里插入图片描述

虚拟内存的实现,需要硬件中分页内存管理单元(PMMU)的支持,将每个虚拟内存地址转换成相应的物理内存地址,当特定虚拟内存地址所对应的页没有驻留在RAM中,将以页面错误通知内核。

虚拟内存地址空间与物理地址空间隔离优点

  • 进程与进程、进程与内核相互隔离,一个进程不能读取或者访问另外一个进程或者内核的内存。这是因为每个进程的页表条目指向RAM(或交换区)中截然不同的物理页面集合。
  • 适当情况下,多个进程能够共享内存。这是由于内核可以使不同进程的页表条目指向相同的RAM页,例如同一程序的多进程共享代码副本;或者调用mmap或者shmget系统调用显示请求与其他进程共享内存区,这有利于进程间通信。
  • 因为需要驻留在内存中的仅是程序的一部分,所以程序加载都很快,且允许进程所占用的内存能够超出RAM容量。
  • 程序员和编译器、链接器之类的工具无需关注程序在RAM中的物理布局。

五、进程的环境变量

每个进程都有相关联的环境列表(Environment List),环境列表由多个环境字符串组成。环境字符串被定义成name=value格式。name叫做环境变量(Environment Variable)。当一个进程被创建时,该进程继承父进程的环境列表。这个特性可以作为父进程和子进程通信的一种方法。比如,当父进程要创建子进程时,可以先设置某个环境变量,子进程随后在自己的环境列表中读取该环境变量。不过这种通信是单向的(one-way)和一次性的(once-only),子进程在创建后,就完全拥有和父进程独立环境列表了。程序可以通过检查环境变量来改变程序的特性(像使用命令行参数一样)。

环境变量可以通过/proc/PID/environ文件检查指定进程的环境列表,每一个“NAME=value”对都以空字节终止。

在程序中访问环境:
(1)通过全局变量char **environ。environ和argv很相似
(2)也可以通过int main(int argc, char *argv[], char *envp[])中的envp来访问。
在这里插入图片描述
(3)使用API函数获取环境变量
在这里插入图片描述
参考:
深入理解linux内存管理之 页表管理- https://blog.csdn.net/u011209099/article/details/9248525

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值