文章目录
- 前言
- 一、用户进程虚拟内存地址空间
- 二、tadm时间管理员之CPU调度
- 三、用户进程CPU虚拟设备v节点结构
- 四、processes virtual device进程虚拟设备v节点结构
- 总结
前言
当玩到“虚拟内存”时,“簇”的概念有冲突,前面2章又需修改,这没办法。休息了一个星期(8月23--29日)、再来,修修补补需要一段时间。
这章介绍AOS中最为复杂的“虚拟设备”进程v节点。先将主框架、流程,大致画出来、再慢慢仔细修改。
分而治之、将SMP多处理器抽象分层:
⚫ AOS内核容器层:管理大部分的设备(包含CPU的分配),五行CPU或内核线程,1号init进程,大部分的系统调用,等等。将系统资源划分为“木、火、土、金、水”五类,以减少竞争和并发;每个进程都运行在自己的虚拟“时空”中、各不相干,进程间通过IPC消息包中断来通信,AOS的0号进程为内核进程(有五类基本线程、管理较多的外设)。中断机制也部分归并到IPC消息包结构中,不再需要中断优先级概念,也没必要为每个进程线程建立独立的内核栈。
⚫ 单CPU内核层:管理一个用户进程队列。每个CPU拥有私有的一级Cache(高速缓存L1-I、L1-D)、二级Cache高速缓存L2,CPU对L1和L2的读写操作是最快的;每个CPU在L1或L2中建立一个内核栈(4kb),是最为合理和快速的。所以,一个用户进程队列共用其所属CPU的4kb内核栈;当CPU节点在用户进程空间接收到IPC消息包而中断时,CPU保存用户进程的线程之上下文到相应的用户进程之线程栈(用户进程最少有一个主线程,每个用户线程栈通常是8Mb虚拟内存空间),切换栈指针为CPU内核栈从而进入CPU内核空间处理IPC消息包;CPU在内核空间处理IPC消息包时,同样可以自动接收更多的IPC消息包、但不会是可重入中断处理,CPU的L2有4kb的IPC消息包循环接收缓冲区。中断上半步快速处理所有消息,在处理完所有中断消息后、用户CPU处理中断下半部(32个为用户CPU所属的内核线程、软中断、工作队列、tasklet),最后调度(抢占式调度)最高的动态优先级之进程的线程,从而回到相应用户进程的线程空间运行、等等。当用户进程的线程阻塞(通常是中断发送IPC消息包)、让步另外的进程线程时,或者滴答时间(通常是10ms)到的广播中断,用户CPU都要重新运行调度程序。CPU进入内核空间处理所有IPC消息包完成后,才会清中断,在准备进入用户进程空间时、还需再看一下是否有新的IPC消息包中断。描述单CPU的、是“单CPU虚拟设备”v节点,主要功能有:用户进程线程的调度、线程动态优先级计算,中断消息包上半部处理,单CPU的32个内核线程(软中断、工作队列、tasklet、调度)、处理中断下半部。
⚫ 单用户进程层:AOS中最为复杂的“虚拟设备”进程v节点结构struct pcb_inode,直接关联的v节点有:虚拟进程设备v节点pcb_inode、虚拟内存设备v节点mm_inode、用户环境文件v节点、进程所属可执行程序procedure的v节点、日志文件系统JFFS的v节点。间接关联的打开文件之v节点可以有64k个。
⚫ 单用户进程的线程层:进程v节点结构的v节点信息结构32字节字段、描述线程小组(线程池),最大可以有64k个线程。
物理内存地址48位,内存缓冲区(1页8扇区、4kb,物理页)号、32位4G个,往往是给出内存缓冲区号或说物理内存页号、就可算出其真实物理地址;物理内存一半用于内核分配,如内存缓冲区、v节点、等等,另一半用于用户进程虚拟内存的物理内存页映射分配;进程虚拟内存空间线性地址48位,每一个进程都视为有256TB的虚拟内存空间,高128TB为内核物理内存映射的共享虚拟空间、通常是只读。内存读取速度:私有高速缓存L1最快、类比于从“冰箱”读写(购与送货),其次是二级Cache高速缓存L2、类比于从“小超市”读写,之后是三级Cache高速共享缓存L3、类比于从“大超市”读写;最后是通过总线桥的64位DDR主物理内存、类比于从“网购”读写,如果还要经过虚拟内存空间到物理内存的映射环节(映射、缺页、分配、锁判断、等等手续)、那就更慢了。设备的读写是最慢的,即使是应用DMA(挪用外设64位或32位总线矩阵周期)和中断通知、也只是将设备数据读写到DDR主存。
用户进程虚拟内存空间:
页全局目录PGD(page global directory)(9位、占据一页、512GB/项,共512项),高256项(高128TB)为内核映射的共享虚拟空间;
页上级目录PUD(page upper directory)(9位、共占据512页2MB内存,共512*512 = 256k项、1GB/项),高128K项为内核映射的共享虚拟空间;
中间页目录PMD(page middle directory)(9位、共占据512*512页1GB内存,共512*512*512 = 128M项、2MB/项),高64M项共享虚拟空间;
页表条目PTE(page table entry)(9位、共需占据512*512*512页512GB内存,共512*512*512*512 = 64G项、4KB/项),高32G项共享虚拟空间;
页内地址12位,4KB。
用户进程页全局目录PGD页中,用户进程占据的是0---255项,第255项虚拟内存地址区域512GB、是最大64K个的用户线程栈。每个用户线程栈为8MB,实际运行中、每个用户线程栈动态分配、只是得到一个物理内存页映射(为线程运行时其栈指针所指虚拟区域页之映射);根据线程号tid就可以得知其用户线程栈虚拟地址范围,理论上、用户进程有128TB的虚拟内存空间、可以编写巨型程序,但现今的大部分电脑物理内存有16GB、就算高档的。一个程序、装入到物理内存页的是极少部分,往往是动态缺页时,才分配物理内存页。通常,AOS内核操作的是48位物理地址、用户进程操作的是48位虚拟内存线性地址。AOS的设计是尽可能将用户进程必须的页、直接放入物理内存页中,以提升速度和效能。为了速度,一个CPU一个内核栈、而不是一个进程一个内核栈;一个进程内的所有线程都有自己的用户线程栈,一个进程最少有一个主线程。一切以简洁、清晰、少代码、为主。如果一个低优先级线程已经获得资源锁,在线程调度前需考虑高优先级线程是否需要对共享资源做操作;不轻易做调度,等待低优先级线程释放共享资源锁后、才做线程调度,又或者做优先级提升操作方案。进程线程的描述在进程虚拟设备v节点,线程的详细描述在v节点信息结构;当进程只是一个主线程时、pid = tid,用户进程的线程组之2个页缓冲区无需使用。假如有最大64K个不同动态优先级字节值(数值越大优先级越高)的线程调度,可按16位线程号分为256个小组,每小组256个线程;当一个线程就绪或挂起等等情形时,必须对该线程所对应的小组线程描述符之就绪动态优先级执行1条指令VMAX256,从而输出该组的动态优先级最大字节值到用户进程第二缓冲区之线程组描述符;之后对256个线程组描述符再一次VMAX256得到MMAX,如果当前线程的动态优先级字节值小于MMAX,则置“需调度”标志,这样编写线程调度程序就非常简洁了。
进程号和其mm对应的v节点号在同一个64k范围内,只需16位的相对v节点号,前面32k个v节点号分给进程、后面的32k个为相应mm的v节点号。
提示:以下是本篇文章正文内容,下面案例可供参考
一、用户进程虚拟内存地址空间
⚫内存管理:内核内存与用户内存(虚拟内存)比例1:1。逻辑地址经段机制转化成线性地址,线性地址又经过页机制转化为物理地址。
⚫AOS用户进程空间:256TB,高128TB为内核映射的共享虚拟内存空间;通常,低128TB才是用户进程管理的虚拟内存空间。
⚫虚拟内存空间线性地址:PGD(9位) + PUD(9位) + PMD(9位) + PTE(9位) + 页内12位偏移地址offset。PGD.PUD.PMD.PTE.offset。
⚫用户进程空间虚拟内存线性地址:64位,最高位为0、高15位32K的进程号,PID.PGD.PUD.PMD.PTE.offset。
⚫AOS物理内存地址48位:LDZONE(4位、暂时为0)+ PBUF(32位页缓冲区、物理页号)+ 页内12位偏移地址offset。LDZONE.PBUF.offset。
⚫LZONE大型分区通常不用,32位PBUF(页号)就是物理内存页框、也称为页缓冲区,当前AOS最大物理内存4G页 = 16TB(以后会扩展到256TB)。
⚫linux:当用户进程需要内存时,从内核获得的仅仅是虚拟的内存区域,而不是实际的物理地址,进程并没有获得物理内存,获得的仅仅是对一个新的线性地址区间的使用权。实际的物理内存只有当进程真的去访问新获取的虚拟地址时,才会由“请求页机制”产生“缺页”异常,从而进入分配实际页面的例程。该异常是虚拟内存机制赖以存在的基本保证——它会告诉内核去真正为进程分配物理页,并建立对应的页表,这之后虚拟地址才实实在在地映射到了系统的物理内存上。(当然,如果页被换出到磁盘,也会产生缺页异常,不过这时不用再建立页表了)。这种请求页机制把页面的分配推迟到不能再推迟为止,并不急于把所有的事情都一次做完。之所以这么做是利用了内存访问的“局部性原理”,请求页带来的好处是节约了空闲内存,提高了系统的吞吐率。在内存区域结构上的nopage操作。当访问的进程虚拟内存并未真正分配页面时,该操作便被调用来分配实际的物理页,并为该页建立页表项。
⚫虽然应用程序操作的对象是映射到物理内存之上的虚拟内存,但是处理器CPU直接操作的却是物理内存。所以当应用程序访问一个虚拟地址时,首先必须将虚拟地址转化成物理地址,然后处理器CPU才能解析地址访问请求。地址的转换工作需要通过查询页表才能完成,概括地讲,地址转换需要将虚拟地址分段,使每段虚地址都作为一个索引指向页表,而页表项则指向下一级别的页表或者指向最终的物理页面。因为在虚拟地址映射到页之前必须先分配物理页——也就是说必须先从内核中获取空闲页,并建立页表。但是实际上系统使用内存时还是倾向于分配连续的内存块,因为分配连续内存时,页表不需要更改,因此能降低TLB的刷新率(频繁刷新会在很大程度上降低访问速度)。
⚫AOS内存管理功能跟linux大同小异,AOS更为简洁和更多的行为是直接操作物理内存而似乎忽略映射、从而更为高速和高效。
⚫用户程序分段:
代码段:代码段是用来存放可执行文件的操作指令,也就是说是它是可执行程序在内存中的镜像。代码段需要防止在运行时被非法修改,所以是只读。
AOS的用户程序代码段通常会小