第二十章 内存等空间管理类的实现

来源:互联网 发布:java微信公众平台框架 编辑:程序博客网 时间:2024/06/09 17:15

                   第二十章   内存等空间管理类的实现

     空间、时间对我来说,或许永远是一个迷。即使我曾经深入到原子的最深处,即使人类科学家是自欺欺人,即使我了解到的最深层次的部分真理是正确的;那又能怎样?那都是过去式,在那光明与黑暗一体之地、我的灵魂受伤了;我不得不回到电脑这块充满垃圾的地方修心养性。

    或许我的论述方法不好,要完全理解本章是有点难度;你要对简单的空间概念需要一定的理解,即使只是论述1D的线性平面空间中的2个基本方法:分配与释放,但也很复杂。要知道LINUX单是内存管理源代码就3万6千行,文件系统的54万多行中磁盘空间管理占多少?网络的约38行中的网络连接管理占多少?将近500万行的驱动和架构、内核中用于空间管理的占多少?我不清楚,猜想LINUX中用于空间管理的为100万行吧;这还没有包含数据库的管理。为此,本章的论述可能会重复再重复,啰嗦再啰嗦;没办法、这将是一场艰辛的战斗!即使前面已经有了基础、规划,即使是连战七天七夜、也不在乎,我会尽最大努力的。APO的用于空间管理的只是160行源代码,这比原先计划是600行的要少了很多,意料之外啊。其实,越复杂的事情都是很简单的实现!我真的不清楚那些复杂脑袋的产物为何如此庞大?学院派的大神们,该脸红了;不要像老鼠上天平:自叹自称,够重啊!

     如果我们用一个二进制位来表示一个资源单位;资源单位可能是一段连续行、或一段连续数据块、或文件中的一条记录、或一个socket文件号、或一个进程号、或一个进程中的一个线程号、或一段连续单元、或一个内存v节点、或进程中的一个打开的文件描述符、或数据库线性表中的一个字段、或进程中的一个类号、或进程中的一个对象号、或一个消息号、或一个过程号等等。这样,对应于小模式,需要64K个位来表示;也即BU64K A;  64K位的位图变量A就对应一个小模式,小模式使用连续的256行作为64K位的位图变量。而中模式是使用一个64K位的位图变量数据块,该块有256个64K位的位图变量;可以管理16M个单位。而大模式则需要64K个64K位的位图变量来描述。一个64K位的位图变量只是占存储空间256E,并不多;但大模式需要占存储空间256个数据块,就比较多了。为减少空间的浪费;对于大模式,我们通常是动态生成的。最初只是分配一个位图变量数据块(中模式),如果还不能满足时,再申请分配一个位图变量数据块。。。最终会生成有n个(n <= 256)位图变量数据块。只要我们编写了大、中、小模式的分配、释放方法放于系统方法表内;那么,所有的程序类都将受益;无须重复的代码。增加、删除数据库表中的一条记录,或目录下的一个文件,或磁盘空间中的一段连续数据块,或数据库下的一个表文件,或内存空间中的一个v节点,或本地内存中的一段连续行、或一个TCP连接等等;都是调用大、中模式下的分配、释放方法。增加、删除数据库表中的一个字段,或一个进程中的一个对象号或类号或线程号或过程号或消息号或打开的文件号,或磁盘空间中的一段连续单元,或一个进程,或本地内存中的一段连续数据块等等;都是调用小模式下的分配、释放方法。APO中的位图是位为1,表示空闲;位为0表示占用。增加、删除只是对位图变量的操作,而不是对对象的具体内容进行。比如,删除一个文件;只是对代表文件所占磁盘空间的位图变量中的一些位做释放;如果,这些空间没有被其它文件占用;那么空间还是原来文件的内容。

    连续几天都不在状态,似乎神赋予的能力都没了,受到了封印;思感退化到小学生的天真、混沌时代。我不断的努力挣脱,日夜奋战;试图将许多零碎的、闪光的思想片段,拼接成一个美丽的图案。修改n遍了,还是没法满意,只好暂时先这样;以后,再不断修改完善;没关系的,我穷得只剩下时间了。

一、多功能硬件模块介绍

     这是集成在32位用户CPU核内的多功能辅助性的64K位硬件模块,功能非常强大!硬件模块YJMK有3个32位的参数与控制寄存器B2、B3、B4,和256E的高速内存YJMK,执行指令是SS1。 SS1指令启动后,需约6-10ns完成;期间用户CPU空转,直到SS1完成;CPU才能执行下一条指令。

BU256E  YJMK; // 64K位的硬件模块YJMK变量,分为256行,每行256位。
B2H: 高8位指令属性,低8位指令码。最高位为SS1启动位;完成时,B2H.15 = 0。
B2L: 低16位是你要COPY进去的位图行数 (也就是你的位图大小)。

B2H.7-0 低8位指令码:

0x00  allot(分配指令),

0x01  release(释放指令)= Set(位置1),

0x02  clr(位清0),

0x03  BIX(位查询指令),

0x04  CMP(比较指令),

0x05  compress(压缩指令),

0x06  insert(插入指令),

0x07  replace(替换指令),

0x08—0xff   保留为将来的扩充指令。

 

B2H.14-8  七位指令属性,为一些指令的功能属性。比如:

CMP(比较指令)的属性:最多只是比较256行中的值;位图内容不变。

B2H.11-8   4位CMP属性: B2H.11,  1、字比较,0、字符比较,其它3位B2H.10-8:

000: 最小值、   001:最大值

010: 等于       011: 不等于

100:小于、      101:大于

110:小于等于、  111:大于等于

如、比较B3的字与1-256行中字第一个相等的位置:B2H.11-8、1010。

如、比较B3H的字符与1-256行中字符第一个相等的位置:B2H.11-8、0010。

如、比较1-256行中字符小于B3H的字符第一个的位置:B2H.11-8、0100。

如果要求出所有的位置、那只能是比较128行,另128E放位置结果。

如、比较B3H的字符与1-127行中字符相等的位置:B2H.14-8、1000010。结果都在128E-255E里面,B4L为符合条件的位置序号数。

B3:  32位是你需要与n行中的32位值比较的数值。n <= 256

B3H: 16位是你需要与n行中的16位值比较的数值。

B4L: 返回结果:是第一个符合条件的字或字符开始地址;B4H不变,可作记录号高半字。如果已经比较完、并失败; PSR.YJ = 0;B2H.15 = 0。

PSR.YJ是状态寄存器中的硬件模块成功标志。

B2H.15为SS1启动位;完成时,B2H.15 = 0。B2H.14为256E的高速内存YJMK分块标志位,1、分为2个128E的内存,0、不分块。一些指令是需要分块的,如BIX(位查询指令)、和快速CMP(比较指令)等。硬件模块的256E,可以分成2部分:输入128E,输出128E;如果输入128E中符合条件的结果全部给出在输出,那么标志PSR.IN置位,请求再输入128E;如果输出128E中的结果满,那么标志PSR.OUT置位,请求读出结果。

对于BIX(位查询指令):我们可以将32K的位图放到输入128E,这样,执行BIX1就可以找出位图中从低位到高位的所有为1的序号值、顺序放在输出128E中。如果为1的序号值不止128E/16 = 2K个,那么标志PSR.OUT置位,请求读出结果。读了2K个后,我们可以再SS1启动、再来。。。。类似的,BIX0就是位0查询指令了。

对于快速CMP(比较指令):在数据库查询非常高效;如果一个字段是映射到字符或字数值,需要做数值条件查询。那么,我们可以一次拷贝128E = 1KW = 2KZ的数据段到硬件模块输入128E来进行比较,结果序号都在输出128E中。如果平均一个128E数据段可查询到n条(n < 1k)符合条件的记录;那么,在内存中的数据库表查找速度对字方式约是:1K/0.1us = 10G条记录/秒,对字符方式约是:20G条记录/秒;即约为200亿条记录/秒。

CIR指令:compress(压缩),insert(插入), replace(替换)。

压缩:可对1-256E中的指定字符或字进行清除,并压缩存放。

插入:可对1-256E中的指定字符或字位置插入一个字符或字。

替换:可对1-256E中的指定字符或字进行替换,或指定位置的字符或字进行替换。

与位操作相关指令:

B3H: 高16位是你的申请或释放的连续1位数。

B3L: 低16位是申请的连续1位数的返回结果开始位地址,或释放的连续1位数的开始位地址。

B4:  返回结果:是位图的最大连续1位数及开始位所属的行号。
   
allot(分配指令):搜索位图满足B3H个连续1位数的开始位地址到B3L;成功PSR.YJ = 1、还将B3H个连续1位数的1全部取反(变为0,表示占用)。等同搜索成功后,执行为部分清0的clr指令。已经搜索完位图、失败,位图内容不变,
PSR.YJ = 0;B2H.15 = 0。

release(释放指令):将你请求释放的连续位数的开始位地址起的B3H个连续位0全部置为1,释放定成功;等同部分位置1的Set指令。 返回结果 B4是位图的最大连续1位数及开始位所属的行号。

二、位图空间

      简单说空间就是指装东西的容器,在电脑界、只是装二进制位的容器,简称位容器。标准的位容器有:字节B是8位、16位是字符Z、32位是字W、256位是行E。程序里的一切都是位容器,对象、变量、指令码、等等都是描述位容器、或如何操作位容器。连续64K个位的位容器,我们称为位图变量。256个不一定连续的位图变量组成的容器,我们称为中模式位图空间;类似的,256个中模式空间组成的容器,我们称为大模式位图空间。

     世界上大大小小的容器多如牛毛,大到无法述说的天地、小到光子;我们是需要指明一个基本空间作为参考物、比如地球,才能分辨或比较事物的层次、大小。不说是一颗微尘,就算一个原子,里面所含的光子数也远超过地球上的生物数量。一花一世界,人类对事物的认知可以说还在表面。即使是电脑界的位容器,也是眼花缭乱、不可胜数。我们必须抽象出简单的描述位容器的规律,这是一件非常耗神的事情。

 

     一个平面线性4G单位的空间A,可以分割成64K个有64K个单位的子空间;这时,如果将不一定是连续的256个子空间组成中模式空间,那么、我们也可以将空间A看作是由一部分子空间和一部分中模式空间的混合组成。如果我们将一个平面线性4G单位空间映射到一个4G位图空间,一个二进制位对应一个单位;那么,我们就可以使用位图来描述线性4G单位空间的大、中、小模式。对于大模式的4G个位的空间,我们可以使用256个64K位的位图为单位(16M位)来分割;这样,大模式空间就分解为256个中模式空间;而每个中模式空间又分解为256个小模式空间(64K个位的位图变量空间)。这样一来,对大模式的管理最终会变成为小模式的管理、速度就能加快。

 

     不管大、中、小模式空间,我们都需要一个基本空间;所有的空间都必须是以基本空间为根本。在APO中,本地内存基本空间是一个单元、划分成64K个子空间(数据块);所有的:进程号空间、内存v节点空间、等等,都是建立在本地内存基本空间上面。其它,如进程的文件号空间、数据库文件内的记录号空间、等等,也都是建立在磁盘基本空间上面;磁盘基本空间是一个卷、划分成64K个子空间(单元)。大、中、小模式空间只是从管理的角度来对空间进行的抽象划分模式;当各种各样、大大小小的空间交织在一起时,会显得混乱与复杂。所有的空间,包括磁盘空间最终都要在本地内存空间中进行管理。不管怎样,空间都是要映射到位图空间来管理;这时,我们就只是简单考虑空间的尺度单位了。

     虽然一个位图变量是对应一个子空间,但中模式空间中的256个位图变量,可以对应到64K个子空间中的任意不一定连续的256个子空间;因为中模式空间的位图变量可以是动态生成的。

太多的空间管理了,我们必须对基本空间作出一些管理规定:

1)、基本空间划分成64K个子空间,一个子空间有64K个连续单位。

2)、基本空间管理:连续子空间的分配、释放(小模式管理),基本空间内的连续单位的分配、释放(大模式管理)。

     基本空间的位号是32位:高16位是位图变量序号,低16位是子空间下的位序号。基本空间的位图变量与子空间是一一对应的,位图变量序号就是子空间序号;这点是和非基本空间不一样的!

APO中通常是有2类的基本空间:(基本空间的位图变量数据块都是在一开始就按实际分配内存。)

1)、本地内存基本空间:单位行E,子空间是一个数据块64KE= 2MB,
基本空间管理:连续数据块的分配、释放,数据块内的连续行的分配、释放。

2)、磁盘基本空间:单位一个数据块64KE,子空间是一个单元64K个数据块 = 128GB,基本空间管理:连续单元的分配、释放,单元内的连续数据块的分配、释放。

三、 1位的模式空间管理

    如数据库文件的记录号,每次只是分配、或释放一个位。不管大、中、小模式空间,只要是每次只能是分配、或释放一个位的;都是使用到1位的模式空间管理。主要是应用于xx号的分配、或释放。
 
1、 1位的大模式空间管理:

LMODE1{        // 1位的大模式空间管理参数 72KE + 305E + 1W

  BU1W [256] BMPDBP;// 中模式空间的管理位图数据块指针数组。

  BU1Z [256] FBMPVN;// 中模式空间空闲的位图变量数的数组。

  BU1E       LFNZB;//256个中模式空间有空闲位1的位行。

  BU289E [256] BMPVP1{ // 1位的中模式空间管理参数的数组

   BU1W [256] SSPN;// 位图变量对应的基本空间位号数组,未分配0、禁止1。

   BU1E [256]FNZB;// 位图变量256行的每一行所对应的非0位的数组

   BU1E   IFNZB; // 256个位图变量有空闲位1的位行。

  }

  BU1Z LACTN;    // 中模式空间的实际数。

  BU1Z UNITLEN;  // 位图变量一个位的长度。

}

 

   BMPDBP中模式空间的管理位图数据块指针,必须一开始就安装好。FBMPVN中模式空间空闲的位图变量数的数组,SSPN位图变量对应的基本空间位号数组、未分配0、禁止1,LACTN中模式空间的实际数,UNITLEN位图变量一个位的长度;这些参数,应用于大模式空间的动态生成。

 

1位大模式分配、释放方法lmanage1()。    

入口:

分配时:R0-R2 = ( 0.allot.0.1, 1.0,LMODE1 ),

释放时:R0-R2 = ( 0.release.0.1, 1.位图变量的位序号, LMODE1 ),

R31H 为位图变量序号(高8位中模式空间序号、低8位相应的位图变量序号)。

出口:

R31H、为位图变量序号,R31L为位图变量的1位开始位序号,

R0H为0、成功,失败则R0H = -1。

占用:28W, R30-R31。

耗时:分配、96ns/97ns,释放、48ns,出错、9ns/33ns/67ns。

lmanage1(){ // 大模式1位的分配、释放方法。

  B2 = R0;  R0 = R1 AND 0X00ff; // 初始化硬件模块。

  B3 = R0;// 只是对YJMK的第0行进行SS1。

  R3 = R2.LFNZB; // R3指向LMODE1.LFNZB。

  if  R1L != 0  goto  free1; // 如果是释放,跳。

  BT0  (R3).E, mal3;// LMODE1.LFNZB为0、跳,无空闲位失败返回。

  YJMK.E = R3.E; // 拷贝LFNZB,分配1位。

  SS1;  // B3L为LFNZB的第一个为1的位序号(中模式空间的序号)

  R30H = B3L; // 保存中模式空间的序号到R30H。

mal1:

  R4 = R2.R30H.W;// R4为相应的中模式空间的管理位图数据块指针。

  R2 = +49;  // R2指向中模式空间参数区LMODE1.BMPVP1

  R2 = + R30H*289;// R2指向相应的中模式参数区BMPVP1。

  call imana1; // 调用中模式空间1位分配、释放方法。

  if RH = -1 goto failret;

  R30H = >>8; R3.R30H = 0;

  BT0 (R2.IFNZB).E, mal2;// 相应中模式空间无空闲位,相应位清0。

  R3.R30H = 1; // 否则置1。

mal2:

  R0H = 0;  RET  // 成功、返回。

mal3:

  R0H = -1; RET // 出错、返回。

free1:

  R30H = R31H; R30H = >>8; //R30H中模式空间的序号。

  R3.R30H = 1; // 释放相应中模式空间相应位。

  JMP  mal1;

}

 

2、 1位的中模式管理

IMODE1{           // 289E + 5Z。

  BU1W  BMPDBP;   // 中模式空间的管理位图数据块指针(SMBMP)。

  BU1Z  FBMPVN;   // 中模式空间空闲的位图变量数。

  BU1Z ACTN;     // 中模式空间中,位图变量的实际数。

  BU1Z BITLEN;   // 位图变量一个位的长度。

  BMPVP1{         // 中模式的256个位图变量参数 289E

   BU1W [256] SSPN;// 位图变量对应的基本空间位号数组,未分配0、禁止1。

   BU1E [256]FNZB;// 位图变量256行的每一行所对应的非0位的数组

   BU256IFNZB;    // 256个位图变量有空闲位1的数组。

   }

}

 

中模式位图空间的1位分配、释放管理方法:imanage1()       

入口:

分配:R0 = 0.allot.0.1,

释放:R0 = 0.release.0.1,

R1H: 为分配或释放的连续位数,1

R1L: 分配时、为0,释放时是位图变量的位序号,

R2 = BMPVP1, R4 = BMPDBP,

释放时:R31H低8位为位图变量序号

出口:

R31H、为位图变量序号,R31L为连续位数的开始位序号,

R0H为0、成功,失败则R0H = -1。

占用:23W, R30-R31。

耗时:分配、68ns/69ns,释放、30ns,出错:9ns、43ns。

imanage1(){ // 中模式的1位分配、释放管理方法。

  B2 = R0;  R0 = R1 AND 0X00ff; // 初始化硬件模块。

  B3 = R0;// 只是对YJMK的第0行进行SS1。

imana1:

  R3 = R2.IFNZB; // R3指向IMODE1.IFNZB。

  if R1L != 0  goto  ifree1; // 如果是释放,跳。

  BT0  (R3).E, mal3;// 失败返回、IFNZB为0、无空闲位。

  YJMK.E = R3.E; // 拷贝IFNZB

  SS1;  // B3L 为 IFNZB的第一个为1的位序号(位图变量序号)

  R30L = B3L;  // 保存位图变量序号R30L。

  R31H = R30L + R30H<<8; // 保存位图变量序号R31H。

  call  ifl1;

  BT0  PSR.YJ, mal3; // 失败、返回。

  R3.R30L = 0;

  BT0 (R2.FNZB.R30L).E, mal2;// 如果该行的最大连续位是0,跳返回。

  R3.R30L = 1; // 分配1位后,还有空闲、相应位置1。

  JMP mal2;

ifree1:

  R30L = R31H AND 0X00FF;  R3.R30L =1;

ifl1:

  R31L = R30L;

  R3 = R2.FNZB.R30L; //R3指向相应FNZB。

  R2 = R4 + R31L<<8; // R2指向位图变量序号的相应位图变量。

  JMP  mana1;// 跳位图变量的1位分配、或释放。

}

3、 1位的小模式管理

SMODE1{           // 257E + 1W。

  BU256E SMBMP; // 小模式空间的管理位图变量。

  BU256   FNZB; // 256行的每一行所对应的非0位,未使用的行为0。

  BU1Z    ACTRN; // 位图变量的实际行数。

  BU1Z    BITLEN;// 位图变量一个位的对应的长度E。

}

      位图变量的实际行数,决定了位图变量的实际大小,未使用的行为0。比如,本地内存空间实际只有32GB,而位图变量是按照128GB设计的;实际的位图变量只有32GB/512MB = 64行,后面的64-255行都是未使用的、行为0(初始化时设置);数据块分配、释放只会在前面的64行进行。1位与连续多位的分配、释放速度是大不一样的,所以、会有2种不同的编程方式。

64K位的位图变量的1位分配、释放管理方法:manage1()       

入口:

R0命令码: 1位、0.allot/release.0.1。

R1H: 为分配或释放的连续位数,1

R1L: 分配时、为0,释放时是位图变量的位序号,

R2: 64K位的位图变量指针SMBMP,

R3:指向FNZB。

出口:

释放:返回修改后的位图,

分配成功:R31L为1位的开始位序号,

分配失败:不修改位图、PSR.YJ = 0。

占用:25W,

耗时:释放21ns,分配40ns、41ns,分配出错:18ns。

manage1(){// 64K位的位图变量的1位分配、释放管理方法。

  B2 = R0;  R0 = R1 AND 0X00ff; // 初始化硬件模块。

  B3 = R0;// 只是对第0行进行SS1。

mana1:

  if  R1L = 0  goto  allot; // 如果是分配,跳。

  R1L = R1L>>8;R3.R1L = 1;// FNZB的相应位释放为1。

  R2 = +R1L;   // 只拷贝相对应的一行

all1:

  YJMK.E = R2.E; // 赋值R2指针指向的一行。

  SS1;           // 分配、或释放序号对应的1位。

  R2.E = YJMK.E; // 回传

  RET

allot:  // 先拷贝FNZB,找到空闲的位行;失败,报错。

  YJMK.E = R3.E; // 拷贝FNZB。

  SS1;      // B3L 为FNZB的第一个为1的位序号(位图行号)

  BT0  PSR.YJ, failret;// 失败返回、FNZB为0、无空闲位。

  R0H = B3L; // R0H为位图行号。

  R2 = +R0H; // 在有空闲位的行中分配1位。

  CALL  all1;// 分配1位。

  R3.R0H = 0;

  if B4H = 0 goto  all2; // 如果该行的最大连续位是0,跳。

  R3.R0H = 1; // 分配1位后,还有空闲、FNZB相应位置1。

all2:

  R31L = B3L; R31L = + R0H<<8; // 分配的位序号。

failret:

  RET

}

 

四、连续n位的模式空间管理

 

    如基本空间等,都需要使用到连续n位的分配、或释放。

1、 大模式空间的连续位管理

LMODE{              // 大模式空间管理参数 12KE + 64E + 1W

  BU1W [256] BMPDBP;// 中模式空间管理位图数据块指针数组。

  BU1Z [256] FBMPVN;// 中模式空间空闲的位图变量数的数组。

  BU1Z [256] MMAXCB1;// 中模式空间最大连续位1数值之最大值数组

  BU48E [256] BMPVP{ // 中模式空间管理参数的数组

   BU1W [256] SSPN;// 位图变量对应的基本空间位号数组,未分配0、禁止1。

   BU1Z [256]MAXCB1;// 位图变量最大连续位1数值的数组。

  }

  BU1Z LACTN;    // 中模式空间的实际数。

  BU1Z UNITLEN;  // 位图变量一个位的长度。

}

 

    中模式空间的256个位图变量中,可能有些位图变量还没使用;未使用的位图变量,其对应的最大连续为1的16位最大值为0;但位图变量的所有位都初始化为1。16位中模式空间空闲的位图变量数,最多为256。没有使用到的中模式空间,其管理位图数据块指针为0;其对应的位图变量最大连续为1的数值之最大值数为0;其对应的空闲的位图变量数为:0x0100、256个。

大模式连续位管理方法:lmanage()    

入口:

分配:R0-R2 = ( 7.CMP.0.16, 申请的连续1位数.0, LMODE ),

释放:R0-R2 = ( 0.release.1.0, 释放的连续1位数.位图变量的位序号, LMODE ),
释放时:R31H 为位图变量序号。

出口:

R31H、为位图变量序号,R31L为连续位数的开始位序号,

R0H为0、成功,失败则R0H = -1。

占用:21W, R29-R31。

耗时:释放345ns,分配398ns,分配出错:230ns、76ns、35ns

lmanage(){ //大模式连续位的分配、释放方法。

   B2 = R0;  B3 = R1; // 初始化硬件模块。

   R4 = R2;  R2 = + 48;// R2指向LMODE.MMAXCB1

   if  R1L != 0  goto  free; // 如果是释放,跳。

   kxcmp();// R30L符合条件的字符开始序号(中模式空间的序号)。

   BT0  PSR.YJ, mal3;// 失败跳、返回。

mall1:

   R29L = R30L;

   R3 = R2; // 保存R3指向LMODE.MMAXCB1

   R4 = R4.R30L.W;// R4为相应的中模式空间的管理位图数据块指针。

   R2 = +16;   // R2中模式空间参数区LMODE.BMPVP

   R2 = + R30L*48;// R2中模式空间参数区LMODE.BMPVP.序号

   call imanag; // 中模式连续位管理方法。

   if RH = -1 goto failret;

   R3.R29L.Z = R30H; // 保存最大连续位1数值之最大值。

   RET

free:

   R30L = R31H; R30L = >>8; // R30L中模式空间的序号。

   JMP  mall1;

}


2、中模式连续位管理

     有16M个单位、则是中模式空间,比如内存v节点管理(也是网络TCP连接管理)就是一个中模式管理。大模式管理也是分解成小于256个的中模式空间管理来进行的。
我们不要求中模式空间的256个子空间之间是连续的,但子空间的64K个单位的位图变量必须是连续的。所以,需要256个位图变量的序号;每个子空间对应一个64K位的位图变量,那么,位图变量存在一个最大连续位1数值参数。为了节省空间,中模式空间的256个子空间,并非是全部使用的,有一个动态增长的过程;需要一个空闲的位图变量数的参数。我们也需要一个管理中模式空间的256个64K位的位图变量的位图数据块指针。

    中模式空间通常是从大模式空间中产生的。比如本地内存空间划分为64K个数据块(子空间);中模式空间内存v节点的单位是4E,一个位图变量是表示64K*4E = 4个连续数据块;所以,我们需要4个连续数据块的一个开始数据块序号(16位数据块号、16位起始行号(0)),来对应一个位图变量。又比如:一个记录型文件,假设文件空间是一个中模式空间、单位是8KE,那么文件空间内的一个位图变量子空间是连续8K个数据块;同样,我们需要一个开始数据块序号(16位单元号、16位数据块号)。不管是什么空间,最终都是在其所属的基本空间安家、其位图变量映射的子空间必须与基本空间的子空间号和子空间下的单位号挂钩。

 

IMODE{            // 48E + 5Z。

  BU1W  BMPDBP;   // 中模式空间的管理位图数据块指针(SMBMP)。

  BU1Z  FBMPVN;  // 中模式空间空闲的位图变量数。

  BU1Z ACTN;     // 中模式空间中,位图变量的实际数。

  BU1Z UNITLEN;  // 位图变量一个单位的长度。

  BMPVP{          // 中模式的256个位图变量参数 272E

   BU1W [256] SSPN;// 位图变量对应的基本空间位号数组,未分配0、禁止1。

   BU1Z [256]MAXCB1;// 位图变量最大连续位1数值的数组。

  }

}


中模式位图空间的连续位分配、释放管理方法:vmanage()       

入口:

分配:R0 = 命令码:7.CMP.0.16,

释放:R0 = 0.release.1.0, 

R1H: 为分配或释放的连续位数,

R1L: 分配时、为0,释放时是位图变量的位序号,

R2 = BMPVP, R4 = BMPDBP,

释放时:R31H为位图变量序号

出口:

R31H、为位图变量序号,R31L为连续位数的开始位序号,

R30H为256个位图变量最大值数组中的最大值,

R0H为0、成功,失败则R0H = -1。

占用:24W, R30-R31。

耗时:释放326ns,分配357ns,分配出错:190ns、35ns

imanage(){ // 中模式的连续位分配、释放管理方法。

   B2 = R0;  B3 = R1; // 初始化硬件模块。

imanag:

   R30H = R30L; R2 = +32; // R2指向BMPVP.MAXCB1。

   if R1L != 0  goto  ifree; // 如果是释放,跳。

   kxcmp();// 返回R30L为第一个大于等于R1H的字符序号(位图变量序号)

   BT0 PSR.YJ, mal3; // 失败跳。

   R31H = R30L + R30H<<8; // 保存位图变量序号到R31H。

   R0 = 0.allot.1.0;

val1:

   R3 = R2; // 保存R3 = BMPVP.MAXCB1。

   R30H = R30L;

   R2 = R4 + R30H<<8;// R2指向位图变量序号的相应位图变量。

   manage(); // 分配、拷贝相应位图变量的256行。

   BT0  PSR.YJ, mal3; // 失败返回。

   R3.R30L.Z = R0H; // 保存最大连续位1数值到相应位置。

   R2 = R3;

   R0 = 1.CMP.0.16;  // 求256个位图变量最大值数组中的最大值。

   kxcmp(); // 返回R30L第一个符合条件的字符开始地址(最大值的序号)。

   R30H = R2.R30L.Z; // R30H为最大值之最大值。

   JMP  mal2; // 成功。

ifree:

   R30L = R31H AND 0X00FF; // R30L为位图变量序号。

   R0 = 0.release.1.0

  JMP  val1;

}


比较、寻找空闲数的序号方法:kxcmp()        

入口:命令码R0 = .CMP.0.16 、16位比较;R2 = 空闲数的数组首指针。

出口:返回符合条件的序号R30L。

占用:9W、R30L

耗时:26ns

kxcmp(){

    B2 = R0;  B3H = R1H; // 初始化硬件模块

    COPY.E( YJMK, R2, R0L );// 编译后4条指令,耗时:12 ns

    SS1;    // 比较R0L行,找到非空序号。

    R30L = B4L;

    RET
}

3、小模式连续位管理

    一个平面线性4G单位的空间A,可以分割成64K个子空间;每个子空间有64K个单位。如果将空间看作是有64K个单位、则是小模式管理;单位可以是子空间、也可以是大模式空间的单位(小模式空间是子空间时)。映射到位图空间,小模式空间就对应一个64K个位的位图变量;或说是256个256位、即256E的位图变量,如果每一个行的256位中有非零的位,则参数FNZB的相应位为1、否则为0;参数FNZB主要是用于快速位分配。

SMODE{            // 256E + 1W。

  BU256E SMBMP; // 小模式空间的管理位图变量。

  BU1Z    MAXCB1;// 位图变量的最大连续为1的位数。

  BU1Z    ACTRN; // 位图变量的实际行数。

}

    位图变量的实际行数,决定了位图变量的实际大小,未使用的行为0。比如,本地内存空间实际只有32GB,而位图变量是按照128GB设计的;实际的位图变量只有32GB/512MB = 64行,后面的64-255行都是未使用的、行为0(初始化时设置);数据块分配、释放只会在前面的64行进行。1位与连续多位的分配、释放速度是大不一样的,所以、会有2种不同的编程方式。

64K位的位图变量的连续位分配、释放管理方法:manage()       

入口:

R0命令码:连续位、0.allot/release.1.0,

R1H: 为分配或释放的连续位数,

R1L: 分配时、为0,释放时是位图变量的位序号,

R2: 64K位的位图变量指针SMBMP。

出口:

释放:返回修改后的位图,

分配成功:

R0 = 位图变量的最大连续1位数及开始位所属的行号,返回修改后的位图;

R31L = 分配的位图变量开始位序号。

分配失败:不修改位图、PSR.YJ = 0。

占用:17W,R31L。

耗时:释放279ns,分配282ns,分配出错:149ns。

manage(){ // 64K位的位图变量的连续位分配、释放管理方法。

  B2 = R0;  B3 = R1; // 初始化硬件模块。

  COPY.E( YJMK, R2, 256 );// 编译后4条指令,耗时:4+ 128 ns

  SS1;             // 释放、或分配序号对应的连续N位。

  if R1L != 0 goto release; // 如果是释放,跳。2W

  BT0  PSR.YJ, failret; // 失败返回;不回传。

  R0 = B4; R31L = B3L;    // 返回结果

release:

  COPY.E( R2, YJMK, 256 );// 成功则回传。

  RET

五、位图变量动态生成

    释放总是成功的,但当我们申请分配失败时,需要查找空闲的位图变量;并为之在基本空间中分配相对应的子空间,之后,再次分配。这时,对于基本空间是使用连续子空间分配、还是使用连续单位分配;就要看具体情况了。UNITLEN位图变量一个单位的长度,是指在基本空间中的连续子空间值、或是连续单位值。


    为了节省空间,中模式空间的256个子空间,并非是全部使用的,有一个动态增长的过程;需要一个空闲的位图变量数的参数。有时候,即使是位图变量的256行,也是一个动态增长的过程;需要一个空闲的位图变量行数的参数。比如,进程的打开文件表项、或说是文件号,并非是每一个进程都需要打开64K个文件的;我们不可能一开始就分配一个数据块用于进程的打开文件表项;这将是一个按需增长的过程。这些灵活因素,导致我们需要一个位图变量动态生成方法。

位图变量动态生成方法:bmpdgm()       

入口:

R0命令码:7.CMP.0.16,

R1L: 48指向BMPVP.SSPN.序号, 289为BMPVP1.SSPN,

R2: 指向FBMPVN中模式空间空闲的位图变量数的数组。

R3:指向SSPN位图变量对应的基本空间位号数组,未分配0、禁止1。

出口:

安装子空间序号到相应位置,接着,再调用分配。

占用:13W,R29-R31。

耗时:149ns。

lbmpdgm(){// 大模式位图变量动态生成方法。

lbmp:

  R0 = 5.CMP.0.16;//求第一个位图变量空闲数大于0的中模式空间序号  

  kxcmp( ,0 );// R30L为位图变量空闲数大于0的第一个中模式空间序号。

  BT0  PSR.YJ, mal3; // 失败出错返回。

  R3.R30L.Z-; // 空闲位图变量数减1。

ibmp:

   R2 = R3 + R30L*R1L;// R2指向BMPVP.SSPN.序号,或BMPVP1.SSPN.序号。

   R0 = A.CMP.0.16; // 求第一个为0的子空间序号。

   kxcmp(,0);// R30L为第一个0的空闲位图变量对应子空间序号。

   R29H = R30L;

   RET

// 接着,我们需要为位图变量分配一个对应的空闲子空间,如果是基本空间的连续

// 单位分配,用lmanage(7.CMP.0.16, UNITLEN值.0, LMODE )。如果是基本空

// 间的连续子空间分配,使用manage( 0.allot.1.0,UNITLEN值.0, SMODE )。

// 接着,跳lbmp2,安装子空间序号到相应位置;接着,再一次调用分配。

lbmp2:

   R2.R29H.W = R31;// 安装子空间序号到相应位置。

   RET

}

 

   太艰难了,耗费了160行代码,还不清楚有多少错误;我们终于开始进入APO操作系统的空间管理主题。

六、内存管理

    本地内存作为一个基本空间,只是一个单元64K个数据块,对应有一个全局的64K位图变量;需要一个小模式块分配管理。最初的256块在系统初始化时,已经分配给系统使用无须管理;即使有空余的块也是应急时用。

    本地内存空间本来就有限,如果代码中声明一个字变量,也要分配一个页(4KB);那就很不合理,很扯蛋了;现代操作系统内存分配的粒度还是比较粗的。APO中,对于本地内存用连续行分配方式较之其它更为合理,可以说无碎片问题,粒度可小到1E(32B、8W、16Z)。

本地内存管理:空间4GE、单位行E( 32B, 16Z, 8W ),子空间就是一个数据块64KE。
1、申请分配、或释放本地内存空间4GE的连续n个数据块。
2、申请分配、或释放本地内存空间4GE的某个数据块中的连续n行。

1、连续内存块管理

MEM_SMODE{ // 最大128GB的本地内存空间64K个数据块,256E + 1W。

  BU256E  SMBMP; // 小模式空间的管理位图变量。

  BU1Z    MAXCB1;// 位图变量的最大连续为1的位数。

  BU1Z    ACTRN; // 位图变量的实际行数。

}


连续内存数据块的分配与释放方法:

manage( 0.allot/release.1.0, 连续数据块数.0/数据块号, MEM_SMODE );

分配成功: R31L = 分配的位图变量开始位序号(数据块号)。

分配失败:不修改位图、PSR.YJ = 0。

2、内存块的连续行管理(大模式)

MEM_LMODE{  // 本地内存最大4G行的管理参数 12KE + 64E + 1W

  BU1W [256] BMPDBP;// 中模式空间管理位图数据块指针数组。

  BU1Z [256] FBMPVN;// 中模式空间空闲的位图变量数的数组。不使用

  BU1Z [256] MMAXCB1;// 中模式空间最大连续位1数值之最大值数组

  BU48E [256] BMPVP{ // 中模式空间管理参数的数组

   BU1W [256] SSPN;  // 位图变量对应的基本空间位号数组,不使用

   BU1Z [256]MAXCB1;// 位图变量最大连续位1数值的数组。

  }

  BU1Z LACTN;    // 中模式空间(512MB一块)的实际数。

  BU1Z UNITLEN;  // 位图变量一个位的长度。不使用

}

 

    参数FBMPVN和 SSPN并不需要,本地内存作为一个基本空间;位图变量的序号就是数据块序号,位图变量的位序号就是数据块内的开始行号。
   
内存连续行的分配方法:

lmanage( 7.CMP.0.16, 申请的连续1位数.0, MEM_LMODE ); 

返回:R31H、为数据块序号,R31L为数据块内的连续行数的开始行序号,

R0H为0、成功,失败则R0H = -1。

内存连续行的释放方法:释放时,R31H 为数据块序号。

lmanage( 0.release.1.0, 释放的连续1位数.数据块的行序号, MEM_LMODE ); 


七、本地内存v节点(或网络v节点、TCP连接)管理

VNODE_IMODE1{     // 289E + 5Z。

  BU1W  BMPDBP;   // 中模式空间的管理位图数据块指针(SMBMP)。

  BU1Z  FBMPVN;   // 中模式空间空闲的位图变量数。

  BU1Z ACTN;     // 中模式空间中,位图变量的实际数。

  BU1Z BITLEN;   // 位图变量一个位的长度。4

  BMPVP1{         // 中模式的256个位图变量参数 289E

   BU1W [256] SSPN;// 位图变量对应的基本空间位号数组,未分配0、禁止1。

   BU1E [256]FNZB;// 位图变量256行的每一行所对应的非0位的数组

   BU256IFNZB;    // 256个位图变量有空闲位1的数组。

  }

}

占用:23W, R29-R31。

本地内存v节点的1位分配方法:imanage1(),分配一个v节点号。       

  imanage1( 0.allot.0.1,1.0, VNODE_IMODE1.BMPVP1,, VNODE_IMODE1.BMPDBP );

  if RH = 0 goto  mal2; // 成功返回R31。

  bmpdgm(7.CMP.0.16, 289,VNODE_IMODE1.FBMPVN, VNODE_IMODE1.SSPN );

  manage( 0.allot.1.0, 4.0, MEM_SMODE );//分配一个内存连续4数据块。

  if R0H = -1 goto  print‘内存v节点满’;//出错返回

  R2 = R3 + R30L*R1L;//R2指向BMPVP1.序号。

  call lbmp2; // 安装子空间序号到相应位置。

  R2.IFNZB.R29H = 1; R2.FNZB.R29H.E =1;

  imanage1( 0.allot.0.1, 1.0, .BMPVP1,, .BMPDBP );//再次分配。

  RET

出口:R31H、为位图变量序号,R31L为连续位数的开始位序号,

R0H为0、成功,失败则R0H = -1。

 

本地内存v节点的1位释放方法:imanage1(),释放一个v节点号。

imanage1( 0.release.0.1,1.位图变量的位序号,.BMPVP1,, .BMPDBP );

释放时:R31H低8位为位图变量序号


     中模式空间16M个单位、单位4E( 128B, 64Z, 32W ),子空间就是一个64K单位 = 4个内存数据块(UNITLEN = 4)。申请分配、或释放中模式空间16M个单位的某个子空间64K单位中的一个单位。APO系统在一开始只是分配一个位图变量,对应本地内存连续4个数据块;当不够用时(申请分配失败),调用位图变量动态生成方法bmpdgm()来扩充。


八、卷磁盘数据块模式管理

卷磁盘数据块模式管理:空间4G个单位、单位为一个数据块64KE( 2MB, 1MZ, 512KW ),子空间就是一个单元(64K个数据块)。
1、申请分配、或释放卷磁盘空间的连续n个单元。
2、申请分配、或释放卷磁盘空间的某个单元中的连续n个数据块。

    卷磁盘作为一个基本空间,只是一个卷64K个单元,对应有一个全局的64K位图变量;需要一个小模式单元分配管理。一个单元128GB,只有大于128GB的文件分配才为使用连续单元分配方法;大部分的文件是使用大模式的连续数据块分配方法。那些不到一个数据块(2MB)的小文件,则集中到一些固定记录文件里;用于小文件集合的记录文件类型有:小文件内容小于等于,1E、8E、32E、128E、512E、2KE、8KE、32KE。共8种类型的小文件记录集文件,如果文件内容小于等于32KE、则文件内容按照大小被放入这8种类型的小文件记录集文件里;如果文件内容大于32KE,则使用大模式的连续数据块分配方法、或连续单元分配方法。

1、卷磁盘连续单元管理

DISKV_SMODE{ // 最大8PB的卷磁盘空间64K个单元,256E + 1W。

  BU256E SMBMP; // 小模式空间的管理位图变量。

  BU1Z    MAXCB1;// 位图变量的最大连续为1的位数。

  BU1Z    ACTRN; // 位图变量的实际行数。

}


卷磁盘连续单元的分配与释放方法:

manage( 0.allot/release.1.0, 连续单元数.0/单元号, DISKV_SMODE );

分配成功: R31L = 分配的位图变量开始位序号(单元号)。

分配失败:不修改位图、PSR.YJ = 0。

2、卷磁盘连续数据块管理(大模式)

DISKV_LMODE{  // 卷磁盘最大4G数据块的管理参数 12KE + 64E + 1W

  BU1W [256] BMPDBP;// 中模式空间管理位图数据块指针数组。

  BU1Z [256] FBMPVN;// 中模式空间空闲的位图变量数的数组。不使用

  BU1Z [256] MMAXCB1;// 中模式空间最大连续位1数值之最大值数组

  BU48E [256] BMPVP{ // 中模式空间管理参数的数组

   BU1W [256] SSPN;  // 位图变量对应的基本空间位号数组,不使用

   BU1Z [256]MAXCB1;// 位图变量最大连续位1数值的数组。

  }

  BU1Z LACTN;    // 中模式空间(512MB一块)的实际数。

  BU1Z UNITLEN;  // 位图变量一个位的长度。不使用

}

 

    参数FBMPVN和 SSPN并不需要,卷磁盘作为一个基本空间;位图变量的序号就是单元序号,位图变量的位序号就是数据块开始号。
   
卷磁盘连续数据块的分配方法:

lmanage( 7.CMP.0.16, 申请的连续1位数.0, DISKV_LMODE ); 

返回:R31H、为单元序号,R31L为连续数据块数的开始号,

R0H为0、成功,失败则R0H = -1。

卷磁盘连续数据块的释放方法:释放时,R31H 为单元序号。

lmanage( 0.release.1.0, 释放连续1位数.数据块开始号, DISKV_LMODE ); 


九、记录型文件空间管理(数据库管理)

    数据库管理,表文件的n个字段记录号管理,小文件记录集文件的小文件记录号管理等等,都是属于记录型文件的空间管理;为通常的大模式、或中模式的记录号管理。中模式管理,效率更高,只需一个位图变量数据块,可管理1600多万条记录;对于普通的应用已经足够。

 

十、进程v节点、进程号管理


   进程v节点、进程号管理:小小模式空间8K个单位、单位8E( 256B, 128Z, 64W )申请分配、或释放小小模式空间8K个单位中的一个单位。

十一、进程的打开文件表项、文件号管理

   进程的打开文件表项、文件号管理:小模式空间64K个单位、单位1E( 32B, 16Z, 8W )
申请分配、或释放小模式空间64K个单位中的一个单位。


    艰苦啊!十天十夜了,还没完没了,晕倒!下一章,保留为APO的文件I/O库;第二十二章  网络MAC。需要3天时间,清空当前的一切思想;准备启动网络思绪线程。

APO操作系统分为六大部件:

1、APO文件目录系统,

2、内核、进程、线程、调度,

3、空间管理,

4、GPU、显示管理,

5、网络,

6、其它设备驱动。

    每一个部件的代码量约为160行,这样、整个APO操作系统的代码量不到1000行。最为艰苦的“空间管理”,已经基本完工,剩下的不太难,日子应该会好过些。


西边的太阳快要落山了,

   微山湖上静悄悄,

     弹起我心爱的土琵琶,

        唱起那动人的歌谣,


。。。。。。。。。。

待续


0 0
原创粉丝点击