实战篇3:一切皆对象,文件目录体系(节点树)

AOS与阿里名称冲突,现改为OACS;面向对象汇编语言OASM(Object assembly language),又带一点点C风格,改名为OACS、即是带一点C风格的面向对象汇编语言系统(Object assembly language C system)。一切皆对象,相比unix/linux的一切皆文件,会显得范围更广一些;许多内核对象,如内存对象、CPU对象、IPC对象、线程对象、等等,是没有文件i节点的。c语言功能也强大,但个人认为、想用好并不容易;这段时间,看了不少嵌入式操作系统及相关的源代码;给我印象是英文单词满天飞,对我这类E文小白不友好,许多缩写E文没有给出E文源单词、有翻译软件也很难查阅;动不动就数量过万的函数,没那么多时间去仔细阅读。stm32f7xx_hal_rcc.c + stm32f7xx_hal_rcc_ex.h + stm32f7xx_hal_rcc.h的三个文件就将近6千行,这只是“复位和时钟控制RCC”、一个小小单片机30多个功能部件的其中一个功能部件;必须大幅度简化!我相信、使用过汇编语言编写单片机程序的老手,都不会同意使用HAL库的;估计就十多行汇编代码的东东,却啰里啰嗦写成几千行、你可以忍受?反正我是宁愿推倒重来。多年前,我也是用汇编写过单片机程序的;相当复杂的项目,编译后也就4KB吧;你现在看看:W601、w800、等等,在平头哥CDK或MDK5上编译,没几个功能,动不动就1MB、2MB代码量,上万函数。你或许会说、人家是包含了多线程复杂操作系统,而汇编用的大多是前后台操作系统;但如果你真正开发过单片机,就自然会明白操作系统内核是没有多少东西的,即使是多进程多线程、复杂内存管理(从只有1k内存或更小、到EB级以上的巨大动态内存管理)和文件管理,就算增加虚拟内存管理。那为何linux、windows、等等,花费几十年、不断改进,却整出几千万行、上亿行的代码量?如果考虑的关联因素太多,自然是代码量会大增,还有就是没有用好C语言、10多行代码硬是编写成几千行代码;呵呵,有人会说我这个小白、还没用过c语言编程,就在此乱说了;其实,这跟用何语言编程无关、与是否面向对象编程无关,linux本质上也是面向对象编程的;即使是面向对象编程,代码量也跟你的编程思想和方法有关。编程思想才是最重要的,想减少代码量、面向对象编程是必须的;另外就需要懂得取舍了,如果觉得让小白更为容易理解和阅读代码、而将10多行的代码硬是增加一大堆函数变成几千行代码量,就如HAL库,你认为选择应该是什么?
c语言指针概念太拗口,我得软件仿真、进去main函数内反复学习和测试,即使这样、也给绕得昏头转向3天。是故,OAC语言必定是取消“指针”概念的,如何更简洁的表达才是OAC语言的重心!
C语言表示方法的改进,OAC语言必定得另写编译器。例如C语言的:

/* Reset PLLCFGR register 复位PLLCFGR寄存器 */
  CLEAR_REG(RCC->PLLCFGR);
  SET_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM_4 | RCC_PLLCFGR_PLLN_6 | RCC_PLLCFGR_PLLN_7 |RCC_PLLCFGR_PLLQ_2 | ((uint32_t)0x20000000U));

1、(uint32_t)0x20000000U表示0x20000000是无符号(U)的32位数值,(uint32_t)强制为无符号32位。uint32是 某些编译器定义的别名,以方便使用,uint32_t是C/C++ 标准中定义的类型。OAC语言:(u32)0x20000000即可。
2、OAC语言没有指针,类属性对象cao就类同C语言的结构;RCC是结构指针,其操作成员变量PLLCFGR时,只能这种形式写:RCC->PLLCFGR。在OAC语言中就会改造成对象(结构)、即是表示为RCC.PLLCFGR;而函数CLEAR_REG(RCC->PLLCFGR),在OAC语言中、只是一条简洁汇编指令:RCC.PLLCFGR = 0; 是故,OAC语言有对象的声明和定义,但没有结构与指针了。OAC语言的类属性对象cao本质上就是C语言的结构。
3、查到:#define RCC    ((RCC_TypeDef *) RCC_BASE)  就是说RCC是指向RCC_TypeDef结构的指针,也就是将RCC_BASE基地址强制为指向RCC_TypeDef结构,而
#define RCC_BASE       (AHB1PERIPH_BASE + 0x3800U),或说地址
RCC_BASE =  (AHB1PERIPH_BASE + 0x3800U)。又
#define AHB1PERIPH_BASE    (PERIPH_BASE + 0x00020000U) 或说外设总线AHB1地址AHB1PERIPH_BASE = (PERIPH_BASE + 0x00020000U),又
#define PERIPH_BASE       0x40000000U
/*!< Base address of : AHB/ABP Peripherals   AHB/ABP外设总线的基地址为0x40000000U */。
这样,RCC就是结构RCC_TypeDef的相对PERIPH_BASE的偏移地址,为
0x40000000 + 0x00020000 + 0x3800 = 0x40023800 。如果将AHB/ABP外设总线看作一个类属性对象cao,RCC不外是其中的一个成员对象吧;如果将AHB/ABP外设总线看作根类属性对象,AHB1总线看作根类属性对象下的子节点类属性对象,RCC则是AHB1总线子节点类属性对象下的一个成员对象吧。
4、查结构和RCC的PLLCFGR的相关位定义

typedef struct
{
  __IO uint32_t CR;            /*!< RCC clock control register 时钟控制寄存器,相对地址偏移Address offset: 0x00 */
  __IO uint32_t PLLCFGR;  /*!< RCC PLL configuration register 锁相环PLL配置寄存器,Address offset: 0x04 */
  __IO uint32_t CFGR;        /*!< RCC clock configuration register时钟配置寄存器,Address offset: 0x08 */
  __IO uint32_t CIR;           /*!< RCC clock interrupt register,时钟中断寄存器,Address offset: 0x0C */
  __IO uint32_t AHB1RSTR;      /*!< RCC AHB1 peripheral reset register,                          Address offset: 0x10 */
  __IO uint32_t AHB2RSTR;      /*!< RCC AHB2 peripheral reset register,                          Address offset: 0x14 */
  __IO uint32_t AHB3RSTR;      /*!< RCC AHB3 peripheral reset register,                          Address offset: 0x18 */
  uint32_t      RESERVED0;       /*!< Reserved, 0x1C                                                                    */
  __IO uint32_t APB1RSTR;      /*!< RCC APB1 peripheral reset register,                          Address offset: 0x20 */
  __IO uint32_t APB2RSTR;      /*!< RCC APB2 peripheral reset register,                          Address offset: 0x24 */
  uint32_t      RESERVED1[2];   /*!< Reserved, 0x28-0x2C                                                               */
  __IO uint32_t AHB1ENR;       /*!< RCC AHB1 peripheral clock register,                          Address offset: 0x30 */
  __IO uint32_t AHB2ENR;       /*!< RCC AHB2 peripheral clock register,                          Address offset: 0x34 */
  __IO uint32_t AHB3ENR;       /*!< RCC AHB3 peripheral clock register,                          Address offset: 0x38 */
  uint32_t      RESERVED2;       /*!< Reserved, 0x3C                                                                    */
  __IO uint32_t APB1ENR;       /*!< RCC APB1 peripheral clock enable register,                   Address offset: 0x40 */
  __IO uint32_t APB2ENR;       /*!< RCC APB2 peripheral clock enable register,                   Address offset: 0x44 */
  uint32_t      RESERVED3[2];  /*!< Reserved, 0x48-0x4C                                                               */
  __IO uint32_t AHB1LPENR;     /*!< RCC AHB1 peripheral clock enable in low power mode register, Address offset: 0x50 */
  __IO uint32_t AHB2LPENR;     /*!< RCC AHB2 peripheral clock enable in low power mode register, Address offset: 0x54 */
  __IO uint32_t AHB3LPENR;     /*!< RCC AHB3 peripheral clock enable in low power mode register, Address offset: 0x58 */
  uint32_t      RESERVED4;         /*!< Reserved, 0x5C                                                                    */
  __IO uint32_t APB1LPENR;     /*!< RCC APB1 peripheral clock enable in low power mode register, Address offset: 0x60 */
  __IO uint32_t APB2LPENR;     /*!< RCC APB2 peripheral clock enable in low power mode register, Address offset: 0x64 */
  uint32_t      RESERVED5[2];  /*!< Reserved, 0x68-0x6C                                                               */
  __IO uint32_t BDCR;             /*!< RCC Backup domain control register,                          Address offset: 0x70 */
  __IO uint32_t CSR;                /*!< RCC clock control & status register,                         Address offset: 0x74 */
  uint32_t      RESERVED6[2];  /*!< Reserved, 0x78-0x7C                                                               */
  __IO uint32_t SSCGR;           /*!< RCC spread spectrum clock generation register,               Address offset: 0x80 */
  __IO uint32_t PLLI2SCFGR;    /*!< RCC PLLI2S configuration register,                           Address offset: 0x84 */
  __IO uint32_t PLLSAICFGR;    /*!< RCC PLLSAI configuration register,                           Address offset: 0x88 */
  __IO uint32_t DCKCFGR1;      /*!< RCC Dedicated Clocks configuration register1,                 Address offset: 0x8C */
  __IO uint32_t DCKCFGR2;      /*!< RCC Dedicated Clocks configuration register 2,               Address offset: 0x90 */
} RCC_TypeDef;
/********************  Bit definition for RCC_PLLCFGR register  ***************/
#define  RCC_PLLCFGR_PLLM_4                  0x00000010U
#define  RCC_PLLCFGR_PLLN_6                  0x00001000U
#define  RCC_PLLCFGR_PLLN_7                  0x00002000U
#define  RCC_PLLCFGR_PLLQ_2                  0x04000000U
#define  RCC_PLLCFGR_PLLR_1                  0x20000000U
#define SET_BIT(REG, BIT)     ((REG) |= (BIT))
#define CLEAR_BIT(REG, BIT)   ((REG) &= ~(BIT))
#define CLEAR_REG(REG)        ((REG) = (0x0))

可以看出SET_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM_4 | ...)实际上等效就是RCC->PLLCFGR = 0x24003010; 写那一长串,我感觉很难看(只是耍花腔而已),资料已经说明PLLCFGR寄存器的复位值就是0x24003010了。例子改为以下写法就简单明了,不外是对象RCC的成员寄存器赋值吧:
    RCC.PLLCFGR = 0;        // PLLCFGR寄存器清0。
    RCC.PLLCFGR = 0x24003010;    // PLLCFGR寄存器恢复复位值。
5、OAC语言的类属性对象可看为u32或u64的数组,也不需要说什么对齐了。几个位段变量(1--n位、n<32 or 64),最好是可以拼接成一个u32或u64的大小,这样就不需要无效的保留位段。位或位段的操作方法(不外是汇编指令的语句吧),例如对PLLCFGR寄存器吧:
    RCC.PLLCFGR.bit25 = 0 or 1;    // PLLCFGR寄存器的第25位置1或清0。
    RCC.PLLCFGR.PLLQ = 4;    
// PLLCFGR寄存器的第27位--24位是定义位段PLLQ = PLLQ[3:0],主PLL  分频系数,适用于 USB OTG FS、SDIO 和随机数发生器时钟 (Main PLL division factor for USB OTG FS, SDIO and random number generator clocks)。
对位段声明,制作一个位段变量名称,再操作就好了。也可以对某一位、声明一个位变量名称,操作赋值该变量为1或0就好了。怎么简单怎么来!对象的成员变量是多个位段组合时,比如:
u32  xxx.; 需要在变量名称后加“.”,然后在.h头文件另处的声明块u32  xxx. {...};内部对各个位段变量作声明。可以用公共的bitx的x位声明一个位变量,b[x1:x2]声明一个位段变量。OAC语言的编译器会对每个变量(或者常量、方法、对象、位段、数组、等等)的名称、属性、类型、长度、等保存到相应符号表中。OAC语言的类名称一定是唯一的,但属性对象名称或对象成员名称可以相同(不同类情形下)、会在“.”前加上类名称限定词;如果认为对象名称是唯一的(如内核对象),就可以不加,如上面的RCC对象。

一、类和对象

❏尽管我不喜欢E文,但ASCI符号才128个,还可以有压缩单词的简写,这点是满优越的;OAC语言的类名称最多8个ASCI符号,已经是够用,没必要“鸡鸭肠子”样子的长度吧、好难看的,对于成员变量名字可以是加“_”分隔,略为长点没关系,比如上面的RCC_PLLCFGR_PLLN_6。文件目录名字除了有8个ASCI字符的唯一短名称,还有可以在一个系统内同名的文件或目录的可变长度名称、最大可到256个UTF-16(Unicode字符16位编码)字符。一切皆对象、皆文件,那么看作为文件的类或对象的名称、自然是统一到“文件节点名字哈希映射表FNHT(file_name_hash_table)”中去。当我们编写代码时的对象成员变量(或者常量、方法、位段、数组、等等)名称也只能是包含在头文件(.h)或方法代码文件(.oac)或线程文件(.thr)的文件内容中(键(名称)/值(相对地址、类型、属性、长度、等)、对),而这名字最大只有28个ASCI字符;既然都编程序了,简单的E文自然是要懂得的(百度翻译软件辅助)。可以用缩写,又大小写区分,不同对象下可以同名;使用最大28个ASCI字符,来命名对象成员变量已是够用;多于28字符的会被自动截断,对于短名字,尾部会存在没有用到的ASCI字符字节、这里为0xFF(对于flash,增长名字时、容易),而没有使用/0作为字符串结束。

❏为何要面向对象编程?对我而言、最重要的是减少了E文单词量!不至于英文单词满天飞。一切皆对象、皆文件,那么不管什么类型的文件对象,其i节点成员通常就那十多个E文对象成员名称而已。每个类的方法组、对应同类的n个对象也只是一份,不同类的方法名称也大多数是相同的;如open();、close()、等等,加上xxx类.来区分而已。如果说有1亿个类,岂不是要1亿个函数、xxx类.open(); 是故,或许会统一为公共的open()方法,无非是init初始化、最终也就是memcopy()方法、不到10条汇编指令而已。是故,OAC语言会随时对方法数量作优化设计(由此对比,应该可以明白linux等的代码量巨大原因了)。当面向对象编程时,我们或许面对数以万计的各类对象;至于对象管理、并不一定要求极为高速,而是更多地需考虑代码的精简量和简明性;也就不得不引入双向和单向链表环概念,就会有“对象钩子、单向节点环、双向节点环”等说法。OACS通常规定一个节点环最大64K个子节点,当在链表节点环上漫游处理时,比如删除一个目录下的所有子节点(子目录)和叶子节点(文件);假设处理一个子节点的时间1us,若64K个子节点、则需要64ms,还可以接受;若是4G个子节点、则需要1个多小时,显然会不耐烦;是故,一个目录节点下的子节点数最多64k个。也有例外情形,比如内核的一个进程打开文件对象数量就可以设置到达4G个,但其处理情形和方式是不一样的。无论是用OAC语言写编译器、或编写OACS操作系统内核、或编写应用程序,都是简单的面向对象之“节点树”描述模式。抽象说就是“道生一、一生二(动分阴(空间的类对象静态数据)阳(时空的指令流、从而变动的数据流))、二生三(阴阳和合生三才)、三生万物”,遵从“简单到复杂”的自然规律过程;简单地说就是:先编写根类节点、再编写子节点、之后编写孙节点...,从“一到二、到三、到多”而已。即先定义顶层模块类功能,进而分析要构成顶层模块类的必要子模块类;然后进一步对各个模块类进行分解、设计,直到无法进一步分解的底层功能块类。既然一切皆对象、文件,其编写过程无非是相应“文件目录体系”的节点树半自动构建过程。道生一,动分阴阳,阴阳和合成三才,三才生四象、之后有:五行,六合,七音,八卦,九宫。也可以理解三才为“阴、阳、中”,三才是无处不在的。

❏类:类可以定义为描述对象行为/属性/状态的模板/蓝图。OAC语言将“类”划分为类属性和类方法2部分,将类比拟为“目录节点”;旗下的类属性对象cao(class attribute object)比拟为“.h”头文件,类方法对象cmo(class method object)比拟为“.oac”文件。这样划分,会使得编程更为简单明了;类目录节点下、通常还有一个扩展名为.thr的线程(thread)对象文件,根目录下就是包含main()方法的主线程文件了。.h文件反映了类属性对象cao的规划模板,还包含用这模板声明和定义的具体cao对象或cao对象数组;而cao对象的初始化元组是常量,在cmo中定义、也就是说其放置在.oac文件内容中。常量和类方法(函数)都是在.oac文件中编写,指令构成方法(函数)、指令段(伪指令、宏指令、内联函数);宏指令是汇编语言程序中的一种伪指令,是代表某功能的一段指令代码;在宏指令出现的地方,编译器总是自动的把他们替换成相应定义的指令代码块。宏指令与子程序(方法、函数)都可以用一个名字定义一段指令代码,以简化源程序的结构和设计。宏指令的参数传送简单,执行效率高;使用宏指令不会缩短目标程序,适用于子功能代码较短、传参较多的情况。子程序代码(如类的方法)在目标程序中只出现一次,调用子程序是执行同一程序段,因此,目标程序也得到相应的简化;模块化、方法类库、节省内存,可被多次调用、编程效率高;但有额外开销(压入将使用的寄存器组和返回地址,计算转向地址、传递参数,返回时还需弹出恢复等),增加了执行时间;适用于子功能代码较长,调用比较频繁的情况。

❏对象:现状的对象定义为具有状态和行为。但OAC语言定义为一切皆对象(Object)!而类(Class)的一个实例(Instance)包含一个具体的cao对象(属性数据)和一个具体的cmo对象(方法、指令码流数据),一阴(cao)一阳(cmo)、相对而言。

❏方法:从基本上说,一个方法表示一种行为,一个类可以包含多个方法。可在方法中写入逻辑、操作数据以及执行所有的动作。方法还有很多叫法,比如函数、子例程或子程序、等等,其本质就是一段指令;OAC语言一条机器指令码用半字u16表示、可以和对应的汇编指令语句相互转换(编译器功用),方法就是一个指令码数组,可以和汇编指令语句组或字符串数组相互转换。

❏标识符:OAC语言标识符(键)是用来标识变量、函数、类、模块,或任何其他用户自定义项目的名称。一个标识符以字母 A-Z 或 a-z 或下划线 _ 开始,后跟零个或多个字母、下划线和数字(0-9)。OAC语言是区分大小写的编程语言,标识符内不允许出现标点字符,比如 @、& 和 %。

❏节点树(生长发育):节点描述文档从根节点(0层、root node)开始,以树状一层层节点展开,每个标签行是一个节点或叶子(属性)终端节点,一个文档最大有4G个节点;根节点外的每个节点都有一个父节点(parent_node ),节点可以有最多64k(下层)子节点(child_node)、第一个子节点(first_child_node)、最后一个子节点(last_child_node);同级节点(兄弟节点sibling_node)是拥有相同父节点的节点(注意:同层不一定是同级),前一个兄弟节点(prev_sibling_node)、下一个兄弟节点(next_sibling_node);叶子节点(简称叶子、leaf _node)是没有子节点或说节点描述块内的标签行都是叶子标签行、的节点(即末端节点、又称为终端节点),层数(layers_number,也称深度)最大256层(0层(根)---255层),通常是不到16层(文件目录体系)。

❏空间:磁盘空间,虚拟内存空间(通常每个进程有独占的2GB虚拟内存空间(堆空间),共享128TB的内核虚拟内存空间(包含内核虚拟空间、进程的线程堆栈虚拟空间)),物理内存空间,编译器空间,flash空间,等等;一个线程(内核或用户)的栈空间最大为一页4KB(还包含64B的cao线程对象在内),考虑到一些单片机的有限资源、线程对象及其栈(属于内核对象)的总大小也可以设为128B、256B、512B、1KB、2KB;局部变量通常只是CPU内部的有限寄存器u32或u64,需要局部大数据空间、如大数组等,只能是动态new或在cao对象中定义。将来64位体系、可考虑到每个进程有128TB虚拟线性内存空间。
PGD页表共512项、每项管理512GB,最大64k个用户进程的虚拟内存空间参考布局:
0--255项、    用户进程虚拟地址空间128TB,每个进程有2GB独立线性虚拟内存空间,每1项512GB包含256个用户进程。用户进程包括:code段、data数据段、BSS段、堆brk(动态对象),用户进程的线程堆栈页在内核共享区域(每进程64K*4K = 256MB,共4G*4KB = 16TB)。
编译器符号表:根类节点、类节点、子类节点、...,节点描述树排列。有三种符号表:cao对象节点描述树表(data数据段、BSS段),cmo对象节点描述树表(类方法集、对象常量集,code段后部),thr线程对象节点描述树表(线程方法集、线程常量集,code段前部(程序))。
用户进程(应用程序)文件:兼容ELF 文件格式规范。
用户进程2GB布局:虚拟地址PVMA对象区域,进程私有;虚拟地址静态或动态方法库区域,进程线程区域,进程私有。

256--511项、共享内核虚拟内存地址空间128TB参考布局:(间隔页在项内)
256--287项:    内核虚拟内存空间16TB与物理内存的直接映射(4G页),固定区域;
288--415项:    内核虚拟内存区域64TB,内核v节点打开文件表,固定区域;
416--447项:    内核虚拟内存用户进程线程栈VMA对象4G*4KB = 16TB(线程cao对象64B包含在线程堆栈页内),固定区域;
448--479项:    内核虚拟地址file_vma对象区域16TB(进程打开文件描述符对象32B、最大512G个,平均每进程8M个),固定区域,进程共享;
480--495项:    共享内核虚拟内存地址空间8TB(磁盘缓冲页空间、最大2G个页),进程共享;
496--503项:    共享内核虚拟内存地址空间4TB(磁盘双缓冲页空间、最大0.5G个),进程共享;
504--511项:    内核映射、静态动态公共方法库区域共4TB,固定区域。

物理内存空间管理、磁盘空间管理、虚拟内存空间管理、等等是大同小异,都属于空间管理类,自然是希望统一到简单的2种方法:分配和释放。这样,可以大幅度减少代码量;还应考虑到有些单片机的内存小于1KB的情形,OACS应该具有非常大的自动变化“弹性”,或说支持小于1KB的空间管理、和最大直到16ES级(4G*4G*512B = 8K EB)的空间管理。虚拟内存空间,下一步计划扩展到64位。

❏i节点(inode):文件索引节点(index node)、也称i节点inode,通常:在内存中打开的vfs_inode文件cao对象称为v节点vnode、在磁盘空间中的称为文件i节点inode。内核有一张v节点打开文件表(位图+链表环、管理)。一个内核文件v节点 = 32B的v节点管理对象vmo
(V node management object)+ 224B的文件i节点(目录、链接文件、等无文件内容的,是96B),部分内核文件v节点是只有v节点管理对象vmo、而无磁盘空间i节点;v节点的大小、通常有:32B、64B、128B、256B、512B、1KB、2KB、4KB(页)、8KB(双页)。OACS的i节点数可到256T个(64K*4G、16位i节点号所属区域,32位区域的i节点号),磁盘文件种类繁多,通常划分为4类:
无文件内容的微型文件(如目录、链接文件、设备文件、等),i_fnna = 1;
文件内容小于等于116B的小型文件,i_fnna = 2;
文件内容小于等于112B + 4KB(带磁盘缓冲页)的中型文件,i_fnna = 3;
大型文件(4KB以上、不需要带磁盘缓冲页),i_fnna > 3;。
这4类是处于不同的i节点号所属区域。前三类文件、其内容或在i节点号所处区域或磁盘缓冲页空间,通过i节点号,就可以快速定位到文件的磁盘空间位置,一次I/O就可以拉入内存。与linux不同,内核v节点、其f_sflags(描述了file文件对象状态标志),f_pos(描述了文件的偏移位置),等等、是在进程打开文件描述符对象file中,而并非在v节点打开文件表中;用户进程cao对象有file_head双向节点环表头项,可将其打开的所有打开文件描述符对象钩挂在环上,最大可达到4G个、或说一个用户进程最大可打开4G个文件,取代了linux进程打开文件描述符表。进程open打开一个文件,返回当前可用的最小打开文件描述符对象号fd(u32)。
v节点管理对象vmo的v_fcount项会记录通过该文件表项(v节点打开文件表的表项)打开文件的次数,当v_count计数归0时这个文件表项才会被删除,因此,对于指向同一文件表项的两个不同文件描述符对象file(如、同一进程中dup的两个文件描述符fd指向同一个文件表项),即使其中一个文件描述符fd关闭了,只要仍然有文件描述符指向这个文件表项,那么就依然能通过这个文件表项访问文件,直到所有指向该文件表项的文件描述符都关闭了才不能再进行访问。
 
文件打开表fot的file的流容器对象,文件磁盘空间或设备空间到FVO流容器对象的窗口映射,大型文件。

u8w file. {    		// 进程打开文件描述符对象file,32B。功能类同linux的struct file、结构类同address_space对象。
	u64 f_pos;	    // 关联文件的偏移量、单位字节。
	u32 f_next; 	// file对象节点钩子,下一个对象号。钩挂到相应进程file_head头,最大可达到4G个。
	u32 f_prev; 	// file对象节点钩子,上一个对象号。
	u48 f_start;	// file对象的fvo流容器对象(窗口)虚拟内存地址开始页号,大型文件才需要(相当于文件窗口缓冲区)。	
	u48 f_onn;	    // 相应打开文件表的文件v节点对象号。
	u32 f_sflags.; 	// file对象状态标志。
};

性能超越linux和windows的OACS操作系统,支持最大64K个进程对象、每个进程支持最大64K个线程对象;我希望系统内核编译后不超过16KB代码量,也就是不超过3千行的实际OAC语言语句(宏指令语句、方法,包含有多条汇编指令);这对编程思想、OAC语言、OACS操作系统规划、OCC编译器,都有很高大上的要求。

二、文件目录体系(节点树),VFS(Virtual File System)虚拟文件目录系统实现

❏OACS操作系统,是一切皆对象;对象若在磁盘空间有表现、有i节点的,才视为磁盘文件;通常90%以上的对象都是文件对象,只是少数无“磁盘文件包装”的内核对象才不看作磁盘文件。微型文件只是有i节点、而通常是无文件内容,或说其在磁盘空间中不占用文件内容空间;如目录、链接文件、等等,设备文件的“寄存器空间描述”是硬件固定分配,在内核8W的v节点管理对象vmo中描述、没有在i节点表现,也看作微型磁盘文件。微型文件的i节点大小只有128B,为32B的vmo + 96B的i节点大小。有不少文件只有很少的文件内容,若文件内容小于等于116B的,称之为小型文件;其文件内容直接包含在256B的i节点内,微型文件和小型文件都可以直接用i节点寻址。还有许多文件内容小于112B + 4KB(带磁盘缓冲页)的中型文件,也是可以直接用i节点寻址的,只是需要2次磁盘I/O(i节点1次,磁盘缓冲页1次),实际上、根据路径名称哈希表FNHT查找i节点寻址时,还需要另外2次的磁盘I/O。大型文件通常也只是需要2次磁盘I/O,i节点中有文件内容磁盘空间开始地址,file对象中有文件偏移位置(f_pos)、窗口缓冲区。

❏OACS的cao对象通常都有2个钩子,一个钩子钩挂在对象节点树上、另一个钩子钩挂到应用双向节点环上(不一定使用);比如内核线程对象的一个钩子钩挂在主线程上、从而钩挂到内核进程文件目录体系上,另一个钩子或许钩挂在“就绪”管理对象上、也或许是钩挂在各种IPC管理对象上、也或许钩挂在“睡眠”管理对象上、等等。文件的i节点cao对象有2---3个钩子,一个钩子钩挂在文件目录树单向节点环上,一个钩子作为源i节点头环、钩挂对其进行链接的所有链接文件,另一个双向环钩子可以钩挂到其它应用上(如进程文件钩挂到相应的用户进程组)。当文件对象在系统内存中展开为v节点时,其vmo还有2个钩子,反映文件对象在内存中的映射(内存打开的文件目录体系),进程文件file_head头钩子则会钩挂其所有的打开文件描述符对象file,内核cao对象钩子、是对象号或直接物理地址。呵呵,一堆钩子、就像“挂猪肉”样子, 系统编程的代码量就会大幅度减少。

❏磁盘空间文件名字哈希映射表FNHT(file_name_hash_table):
任一条路径是唯一的、任一条路径 + 文件名也是唯一的,同一个父目录路径下不能有相同名字的文件,这是规则;不同父目录路径下允许同名文件、同名目录,以及文件和目录同名。OACS系统:不同父目录路径下的同名文件(或目录)只允许最大1k个,对一个“名字”而言。大系统理论上支持48位的i节点数(256T个i节点、约为282万亿个i节点(或文件)),如果将文件(或目录)名字哈希映射到32位的分配器对象项(2W),那每项还需最大16位的不同文件名字映射相同哈希值节点数(实际上,因存在同名文件(或目录)的最大1k个(10位)情形、是不到16位的)。映射表FNHT在大系统时,需要4G*8B = 32GB的FLASH空间(不需要机械磁盘IO),如果只分别映射到256个24位哈希空间、而每个24位哈希空间只是16M*2W = 128MB的FLASH空间;如linux等的中系统只是32位的i节点数、只有一个24位或16位哈希空间,不同文件名字映射相同哈希值节点数只需最大8位。总之、打开一个文件等等操作,只是想2次磁盘IO、就可定位到相应i节点,而最终将文件拖入内存通常也是需要2 + 2 = 4次磁盘IO(微型和小型文件则为3次磁盘IO)。

用“空间换时间”或者“用时间换空间”这是没办法的事情,当按文件名字查找其相应i节点时,不可能在一个巨大的文件名字线性空间16PB(假设平均一个文件名字32字符64B、256T*64B = 16PB)中、一个一个比对(最大需要256T次比对,及4G次的磁盘IO、每次装入内存2MB进行对比),那会慢如蜗牛。利用硬件哈希计算:文件名字-->硬件哈希4字MD5-->二次哈希到32位线性相对地址哈希映射表FNHT,这表放在无需磁盘IO的FLASH空间中、有4G项,每项为一个8B的“分配器对象”指示、其中32位为分配器对象磁盘空间开始地址、16位为映射到相同哈希值的不同文件名字节点数、16位为状态标志。如果说需考虑:相同哈希值的不同文件名字节点数最大有64k个,每个节点允许对应有最大1k个同名项(每个同名项为8W),则需磁盘空间:4G项*64K*32K = 8EB;这显然不合理,即使未来的个人电脑磁盘空间可达到EB级; 在特例情形下、可以适当增加IO次数,用时间换空间,但我们也是希望特例情形下一次查询、可以控制在2秒时间内。

分配器对象中的查找分为2次:
a、查找映射到相同哈希值的不同文件名字节点中(最大有64k个)的对应节点,按文件名字长度和类型的轻型比较,符合后再进一步比对文件名字。一个节点对应一个双扇区,最大需要64K*1KB = 64MB的磁盘空间;一次拖入内存64MB再进行比较、自然只是一次IO,但我现在用的电脑、文件数估计也就几十万个,就算系统有1万亿个文件,这些节点数估计也在1k个之内;使用单向链表、将分配器对象划分为2MB块的单向链表,极端情形下最大32次IO;这样,需要的初始磁盘空间大小从:4G*64MB = 256PB降为4G*2MB = 8PB;如果将分配器对象拆分为256个“256分配器对象”单向链表,还可降低为4G*256KB = 1PB, 但极端情形下循着链表需最大256次IO,那将是有上百万亿个文件的情形。256分配器对象充斥在OACS系统的每个角落,为简洁代码量起着很重要的作用。在此,一个256分配器对象管理256个双扇区(相同哈希值不同文件名字节点,256KB),动态增减节点数;一次IO读入一个256分配器对象到内存,再轻型比较、文件名字比较。系统文件数量小于1万亿个时,通常就是一次磁盘IO。
b、当定位到相应的相同哈希值不同文件名字节点,下一步是找出不同路径下的同名文件项8W:文件所属父目录节点路径名字哈希值(硬件4字MD5、唯一性),48位的i节点号(其中高16位i节点区域),16位的v节点号类型,32位的v节点号,32位的父v节点号。文件名字节点双扇区32*8W,如果文件名字为256字符(8字对齐),则只有14个文件项,或许需要文件项扩充双页;有时文件名字只是不到16字符(8W),则还可以装入29个同名文件项8W;通常多个同名文件的情形并不多的,256字符的长文件名也不多见。已知文件名字及所属父目录节点路径名字时,查找其对应i节点和v节点,通常就是2步、2次磁盘IO(如果文件项在节点双扇区、只需一次磁盘IO);实际上也不一定限制同名文件项只是1K个,但最大不超过64K个。

一个256双扇区分配器对象为256KB = 256*1KB = 256*256W = 64KW,有256个相同哈希值的不同文件名字节点,最大可扩充为256个256双扇区分配器对象;0号256双扇区分配器对象的地址由哈希映射表FNHT中相应的项所指示;或说256双扇区分配器对象的0号双扇区,才会包含有下一个扩充256双扇区分配器对象节点钩子,之后才是相应的节点名字、长度、等等,以及同名文件项8W。256分配器对象ao256(256 allocator object),双页dp(double pages), 有2种形式的256分配器对象ao256:
a、256双扇区分配器对象256KB,对应、映射到相同哈希值的最大256个不同文件名字节点(对应一个双扇区);如果不止256个节点时,0号节点的相同哈希值不同文件名字节点的ao_next成员指向下一个扩充256双扇区分配器对象、动态增加256个节点;用横向单向链表来动态扩充节点、ao_next为0结束。非0号节点,ao_next = 0、不使用;每一个节点的双扇区(256W)分为32项,ao256对象使用了2项,文件名字字符串、以项8字对齐,最小占用一项(小于16字符),最大占用16项(256字符、16*8W = 128W);余下的就是x个同名文件项了,最大x = 32 -2 - 1 = 29项,最小x = 14项;同名文件项:文件所属父目录节点路径名字哈希值4W(硬件4字MD5、唯一性),16位i节点区域、16位的v节点号类型,32位的i节点号,32位的v节点号,32位的父v节点号。
b、256双页分配器对象8KB:如果同名文件项有更多时,需要增加同名文件项扩充双页(256双页分配器对象8KB);OACS系统允许一个文件名字,最大有64K个同名文件项,为纵向单向链表动态增加,ao_dpnext 下一个扩充同名文件项双页地址,为0结束,最大钩挂256个扩充同名文件项双页。每个扩充同名文件项双页共有256同名文件项,最初的2个同名文件项空间16W用于256双页分配器对象8KB的n_ao256.;是故,实际只有256 - 2 = 254个同名文件项,不够用、则纵向单向链表动态扩充。

增加或释放256分配器对象ao256,通常是拷贝原有的相应ao256对象,但“块”最终是由相应的块空间(256KB或双页8KB)管理对象进行。无论如何,都是要拖进内存才能进行相关操作,ao256对象必定有相应的v节点管理对象vmo(磁盘空间无意义)。cao对象的本质就是一个u32数组,数组的成员自然也可以是cao对象;表示成cao对象,是因其某些u32成员可以拆分为:位、位段、的组合表示;也可以写成u8w、u256w等等的整体数组结构模式表示,自然就好。cao对象或说u8w、u256w等等的整体数组结构的成员变量是多个成员位段组合时,比如:u32  xxx.; 需要在变量名称后加“.”,然后在.h头文件另处的声明块u32  xxx. {...};内部对各个位段变量作声明;可以用公共的bitx的x位声明一个位变量,b[x1:x2]声明一个位段变量。所有这些表示模式区别,都是编译器的任务。

	u256w n_object.[256];    	// 虚拟文件名字256双扇区对象数组,256KB/64KW。

u256w n_object. {    			//  虚拟文件名字256双扇区对象数组成员描述 。
	cao n_ao256.;		// 256分配器对象ao256,u16w。
	u8w  n_name[ao_ncount]; 	// 文件(目录)名字的字符串数组。
	u8w  n_snf_item.[ao_ficount]; 	// 同名文件项(same name file item)数组。
};

u8w n_snf_item. {    			//  同名文件项描述 。
	u4w n_md5;		// 文件所属父目录节点路径名字哈希值4W(硬件4字MD5、唯一性)。
	u16  n_i_fnna;		// inode号所属区域(area)。
	u16  n_v_type; 		// 16位的v节点号类型。 
	u32  n_i_fnn;		// 索引inode号(file inode number)。
	u32  n_v_fnn;		// 相应在内存打开的v节点号。
	u32  n_v_pdnn; 		// 相应在内存打开的父v节点号。
};

cao n_ao256. {    		// 8W(含4W的vmo) + 8W位图 。
	u32 v_next; 	// 相应内存空间节点钩子(0号节点),下一个扩充256双扇区分配器对象节点地址,0结束,最大钩挂256节点。
	u32 v_dpnext; 	// 相应内存空间扩充同名文件项双页钩子,下一个双页地址,为0结束,最大钩挂256个扩充同名文件项双页。
	u16 v_type; 	// 对象v节点类型。 
	u16 v_state; 	// 对象v节点状态。 
	u32 v_flags; 	// 对象v节点标志。

	u32 ao_next; 	// 磁盘空间节点钩子(0号双扇区),下一个扩充256双扇区分配器对象节点号(地址),0结束,最大钩挂256节点。
	u32 ao_dpnext; 	// 磁盘空间扩充同名文件项双页钩子,下一个双页地址,为0结束,最大钩挂256个扩充同名文件项双页。

  	u8   ao_ocount;	// 本对象节点单向链表的实际子节点计数。非0号双扇区为0、不使用。
  	u8   ao_dpcount;	// 扩充同名文件项双页的计数。
  	u8   ao_ficount;	// 本对象的同名文件项计数(每项8字)。
  	u8   ao_ncount;	// 本对象的文件名字项(8字对齐)计数(节点为:14---29,扩充同名文件项双页:1---254)。

	u8   ao_namel;	// 本对象节点的对应文件(目录)名字的实际长度,最大128字(256个UTF-16字符),0xff为字符串结束。
  	u8   ao_type;	// 文件(目录)的类型。
	u16 ao_tficount;	// 总文件项计数(包含扩充文件项)。
	
	u8w n_bitmap;	// 256位图,对应256个双扇区或文件项。
};

1、目录文件cao对象i节点。

不同于linux,这里的目录(节点)看作是无文件内容的微型文件,被包含在相应的i节点内;目录节点最大有64K个目录项,目录项可以是子目录节点或叶子(文件)属性节点;目录inode号所属区域(area),固定为1,只需32位的目录索引i节点表示。目录节点单向环是48位,包含挂到目录下的48位子i节点,高16位是inode号所属区域(area),如果是子目录节点则为1。新建一个目录时,目录i节点head头钩子i_hnext = 自身i_fnn(初始目录节点单向环),每增加一个目录项、都是在目录i节点head头钩子插入;而删除一个目录项,则需从head头钩子循着单向链表环查找到相应目录项后、删除。目录可以被链接文件进行链接,并提供i_shead头钩子,钩挂对其进行链接的所有链接文件,方便管理,最大被链接数64K个。目录的双向环钩子可以钩挂到其它应用上,比如作为xxx组的成员。目录是无文件内容的微型文件(少了116B的i节点文件内容),其时间戳比普通文件的、少了一项文件内容时间戳3W,共少了116B + 12B = 128B。
//    u16 i_fnna;    // 目录inode号所属区域(area),固定为1。

cao directory_inode {    	// 目录i节点cao对象,只需32B + 96B = 128B = 32W。
	u8w vmo.;	// 内核使用,文件打开表v节点管理对象8字/8w(v node management object)。
	u32 i_fnn;		// 目录索引inode号(file inode number)。将本目录inode节点钩挂到所属父目录的i节点单向环上(头插入)。
	u32 i_pdnn; 	// 所属父目录i节点号(parent directory inode number)。
	u48 i_hnext; 	// 目录i节点head头钩子,目录节点单向环的下一个i节点号,本目录i节点单向环(挂到目录下的子i节点,头插入)。
  u16 i_mode.;	// 目录类型和访问权限控制。
	u32 i_next; 	// 目录i节点钩子,下一个i节点号。自定义目录i节点双向环钩子,可以钩挂到其它应用。
	u32 i_prev; 	// 目录i节点钩子,上一个i节点号
  u16 i_fcount;	// 本目录i节点单向环的实际子节点计数(目录项数)。
  u16 i_nlink;	// 目录被链接的计数。
	u32 i_flags.;	// 目录标志。
  u32 i_uid;		// 目录拥有者id。
  u32 i_gid;		// 目录用户组id。
    u8   i_name[8];	// 目录短名字ASCI字符。
	u8   i_type; 	// i节点对象所属类的类型。
	u8   i_layers; 	// i节点对象的层数。
  u48 i_nhash;	// 名字32位哈希映射表FNHT项某256双扇区分配器对象256KB的某双扇区(16位相同哈希值不同文件名字节点)。
  u32 i_shead;   	// 目录源i节点号的链接文件头(所有链接到本目录下的链接文件i节点头部,头插入)。
	u9w i_timestampsd.;	// 时间戳。
};

// 时间戳(Timestamps)字段结构、9*4字节。高64位表示正负秒数,它们以1970年1月1日(unix元年)表示为0,正数表示之后至今的秒数,最大表示
// 约2147.5亿年;负数表示之前的秒数,最小表示约负2147.5亿年。低32位的单位是纳秒(毫微秒(nanosecond),上一秒开始经过的ns数)。
u9w i_timestampsd.{
	s64 i_atimes;  	// 文件的最后访问(access)时间,秒数。
	u32 i_atimens;	// 纳秒数。
	s64 i_ctimes;  	// 文件inode属性的最后改变(change)时间,秒数。
	u32 i_ctimens;	// 纳秒数。
	s64 i_crtimes;  	// 文件的最初创建(create)时间,秒数。
	u32 i_crtimens;	// 纳秒数。
};

u16 i_mode.{
  u4 i_mode.[15:12]{  		// f_types,文件类型File types。
	F_UNKNOWN	0	// 不确定。
	F_REG		1	// 普通(常规)文件(regular file)R
	F_DIR		2	// 目录文件(微型文件)D(directory file)
	F_DBT		3	// 数据库表文件T(data base table file)
	F_LNK		4	// 链接Link(微型文件)L
	F_EXECP		5	// 可执行程序executable programme文件E
	F_CHR		6	// 字符设备(微型文件)C(character device file)
	F_BLK		7	// 块设备(微型文件)B(block device file)
	F_VDEV		8	// 虚拟设备virtual device(微型文件)V
	F_SOCK		9	// Socket文件S
	F_FIFO		10	// FIFO管道文件F
	F_SMALL		11	// 小型文件(小于等于116B)
	F_MSB		12	// 中型带缓冲区文件(medium-sized buffered file)(112B + 4KB)
	F_LARGE		13	// 大型文件(不带缓冲页、大于4KB)
	F_WHT		14	// 变换文件W
	F_DEV		15	// 物理设备文件
	};

  u12 i_mode.[11:0]{ 	
	bit0	S_IXGADM	// 组管理员执行权限
	bit1	S_IWGADM	// 组管理员写权限
	bit2	S_IRGADM	// 组管理员读权限
	bit3	S_IXGRP		// 同组用户执行权限
	bit4	S_IWGRP		// 同组用户写权限
	bit5	S_IRGRP		// 同组用户读权限
	bit6	S_IXOTH		// 其它用户执行权限
	bit7	S_IWOTH		// 其它用户写权限
	bit8	S_IROTH		// 其它用户读权限
	bit9	S_IXAPP 		// 指定appoint用户执行权限。
	bit10	S_IWAPP 		// 指定appoint用户写权限。
	bit11	S_IRAPP		// 指定appoint用户读权限。
// i_mode.bit9	S_ISVTX 		Sticky 位特殊权限,沾着位。
// i_mode.bit10	S_ISGID 		set-group-ID 位特殊权限。
// i_mode.bit11	S_ISUID 		set-user-ID 位特殊权限。
	};
};

u32 i_flags.{
	bit31  I_H;		// 1、i节点为“.h”头文件,0、否。
	bit30  I_OAC;	// 1、i节点为“.oac”文件,0、否。
	bit29  I_THR;	// 1、i节点为.thr的线程(thread)对象文件,0、否。
	bit28  I_DSBUF; // 1、i节点文件使用磁盘空间缓冲页(中型文件)Disk space buffer,0、否。
	bit27  I_DG;    // 1、i节点文件内容为动态增长Dynamic growth的(通常按大型文件处理),0、i节点文件内容相对固定。
	bit26  I_SYS;   // 1、i节点文件为系统文件,0、否。对于系统文件root也没权限,只能由机器程序执行。
	bit25  I_FSR;   // 1、i节点文件为文件系统根目录文件File system root file,0、否。
	bit24  I_IF;    // 1、i节点文件为不可变的文件Immutable file(不能修改、删除和更名),0、否。
	bit23  I_AOF;   // 1、i节点文件为仅追加(append-only)的文件(只能把数据追加在文件尾),0、否。
	bit22  I_MICRO; // 1、i节点文件为微型文件micro file(没有文件内容),0、否。
	bit21  I_OFST;  // 1、i节点文件为其它文件系统类型other file system types,0、否。
	bit20  I_MUTEX; // 1、i节点互斥锁定,0、否。
	bit19  I_IBUF;  // 1、i节点缓冲区锁定inode buffer(对应磁盘空间缓冲区在内存中的缓冲区),0、否。
	bit18  I_IDM;   // 1、i节点数据变动(已修改、脏标志,需磁盘I/O更新)inode data movement,0、否。
	bit17  I_IBDM;  // 1、i节点缓冲区页数据变动inode buffer data movement,0、否。
	bit16  I_DBTP;	// 1、i节点为数据表文件时的数据项需要细分rwx权限,0、否。
	bit15  I_DIR;	// 1、i节点为目录文件(微型文件)D(directory file),0、否。

...			// 待续。

};

2、链接文件.lnk、文件叶子i节点cao对象。
内核为每一个新创建的文件分配一个唯一的inode(索引节点),我们可以将inode简单理解成一个指针,它永远指向本文件的具体存储位置。文件属性保存在索引节点里,在访问文件时,索引节点被复制到内存中,从而实现文件的快速访问。系统是通过索引节点、而不是文件名来定位每一个文件。快捷方式(shortcut)是一种功能上类似符号链接的文件对象,但与符号链接有本质的不同。快捷方式是普通的文件(拥有扩展名 .lnk),而非符号,因此,快捷方式可以被复制、移动、更改(某些特殊的快捷方式无法更改所有信息)或删除。快捷方式可以指向文件、文件夹或其他任何系统中合法的位置(包括控制面板、桌面等)。快捷方式如果指向可执行程序,则可以同时指定启动的命令行参数以及启动位置(对于非可执行程序的快捷方式也能指定这些信息,但无意义)。同时,可以为快捷方式单独选择图标(如果没有选择图标,则使用目标的图标),以方便用户个性化。总之,建立快捷方式就是建立了一个新链接文件。当访问链接文件时,系统就会发现他是个链接文件,它读取链接文件找到真正要访问的文件。每建立一个新链接文件,其对应的源i节点之链接引用计数都会加1,创建源i节点文件时、其引用计数 i_nlink = 1,当所有对其的链接文件都删除后,也即i_nlink = 1时、才可删除源i节点文件。可以用根权限强行删除源i节点文件,但相应的链接文件就成为无源而被遗弃(系统自动删除相应链接文件)。

cao link_inode {    // 链接文件叶子i节点cao对象,需32B + 96B = 128B。
	u8w vmo.;	    // 内核使用,文件打开表v节点管理对象8字/8w(v node management object)。
	u32 i_fnn;		// 链接文件索引 inode号(file inode number)。将本链接文件i节点钩挂到所属父目录的i节点单向环上(头插入)。
	u32 i_pdnn; 	// 所属父目录i节点号(parent directory inode number)。
	u32 i_hnext; 	// 没有使用。
	u16 i_fnna;	    // 链接文件inode号所属区域,也是固定为1。
  u16 i_mode;	    // 链接文件类型和访问权限控制。
	u32 i_next; 	// 链接文件i节点钩子,下一个i节点号。自定义链接文件i节点双向环,或许是所有连接文件双向链表i节点钩子。
	u32 i_prev; 	// 链接文件i节点钩子,上一个i节点号
  u16 i_fcount;	// 没有使用。
  u16 i_nlink;	// 没有使用。
	u32 i_flags;	// 链接文件标志。
  u32 i_uid;		// 链接文件拥有者id。
  u32 i_gid;		// 链接文件用户组id。
    u8  i_name[8];	// 链接文件短名字ASCI字符。
	u8  i_type; 	// i节点对象所属类的类型。
	u8  i_layers; 	// i节点对象的层数。
  u48 i_nhash;	// 名字32位哈希映射表FNHT项某256双扇区分配器对象256KB的某双扇区(16位相同哈希值不同文件名字节点)。
    u32 i_sfnn;	    // 链接文件的源i节点号。
	u9w i_timestampsd.;	// 时间戳。
};

u8w  vmo. {    		// 文件打开表v节点管理对象8字/8w(v node management object),嵌入(被包含)到v节点中、为其成员。
// u32 v_fnn;   对象索引v节点号(file node number)。内核使用v节点内存地址管理,v_fnn = &v_pdnn变量的地址即是。
	u32 v_pdnn; 	// 对象父目录v节点(parent directory node number), 将对象v节点钩挂到所属父目录v节点单向环上(头插入)。
	u32 v_hnext; 	// 对象v节点head头钩子,本对象v节点单向环的下一个子v节点,钩挂对象的子节点(头插入),v节点树。
	u16 v_type; 	// 对象v节点所属类的类型。
  u16 v_fcount;	// 本对象v节点单向环的实际子节点计数。
  u32 v_count;	// 对象v节点引用计数。
	u32 v_next; 	// 对象v节点钩子,下一个v节点。自定义对象v节点双向环,可以钩挂到其它应用。
	u32 v_prev; 	// 对象v节点钩子,上一个v节点。
	u32 v_sflags; 	// 对象v节点状态标志。
	u32 v_fpbuf;    // 对象v节点物理内存缓冲区页起始地址,类同this指针 。
};

3、虚拟文件(普通文件,非、目录、链接文件、物理设备文件、等微型文件)cao对象:
一切皆对象,具有i节点的对象才称为磁盘文件;只有文件打开表v节点管理对象vmo、8字/8w(v node management object)的,称为内核文件;oacs系统有90%以上的对象为磁盘文件,余下的、基本上都是内核文件,是故、也有一切皆文件的说法。许多内核对象,如内存对象、CPU对象、IPC对象、线程对象、等等,是没有文件i节点的、但有vmo。链表头初始时是指向自己就构成单向环或双向环了,

cao vfs_inode {    	// 虚拟文件叶子i节点cao对象,224B、56W、28DW,总256B = 32DW = 64W。
	u8w vmo.;	    // 内核使用,文件打开表v节点管理对象8字/8w(v node management object)。
	u32 i_fnn;		// 文件索引i_node号(file node number)。将本文件i节点钩挂到所属父目录的i节点单向环上(头插入)。
	u32 i_pdnn; 	// 所属父目录i节点号(parent directory node number)。
	u32 i_hnext; 	// 文件i节点head头钩子,本文件i节点单向环的下一个子节点号,可作为文件内容数据表记录分配器对象钩挂。
	u16 i_fnna;	    // 文件inode号所属区域。
  u16 i_mode;	    // 文件类型和访问权限控制。
	u32 i_next; 	// 文件i节点钩子,下一个i节点号,自定义文件i节点双向环,可以钩挂到其它应用。
	u32 i_prev; 	// 文件i节点钩子,上一个i节点号
  u16 i_fcount;	// 文件i节点单向环的实际子节点计数。
  u16 i_nlink;	// 文件被链接的计数。
	u32 i_flags;	// 文件标志。
  u32 i_uid;		// 文件拥有者id。
  u32 i_gid;		// 文件用户组id。
    u8  i_name[8];	// 文件短名字ASCI字符。
	u8  i_type; 	// i节点对象所属类的类型。
	u8  i_layers; 	// i节点对象的层数。
  u48 i_nhash;	// 名字32位哈希映射表FNHT项某256双扇区分配器对象256KB的某双扇区(16位相同哈希值不同文件名字节点)。
  u32 i_shead;   	// 文件源i节点号的链接文件头(所有链接到本文件i节点号下的链接文件i节点头部,头插入)。
  u29w i_pdata.;   // 文件私有private数据区、116字节。小型文件内容:116B,中型文件内容:112B + 4KB。
	u12w i_timestamps.;	// 时间戳。
};

u29w i_pdata.{		// 中型文件或小型文件
   u32  i_dsbuf;	// 中型文件磁盘空间数据区的缓冲页号,或小型文件内容4B数据。
	u28w i_data;	// 文件内容数据28W(字),112B。 
};

u29w i_pdata.{		// 大型文件,100B + xxx。
	u64  i_dssadd;	// 大型文件磁盘地址空间的扇区开始地址(或许是文件内容数据表记录根分配器对象开始地址)。
	u64  i_fsize;	// 大型文件总大小,单位字节B。或者是数据表记录分配器对象数,实际的记录数、等等。
	u25w i_data;	// 大型文件的25W(100B)数据区作为分配器对象链表等。
};

// 时间戳(Timestamps)字段结构、4*12字节。高64位表示正负秒数,它们以1970年1月1日(unix元年)表示为0,正数表示之后至今的秒数,最大表示
// 约2147.5亿年;负数表示之前的秒数,最小表示约负2147.5亿年。低32位的单位是纳秒(毫微秒(nanosecond),上一秒开始经过的ns数)。
i_timestamps.{
	s64 i_atimes;  	// 文件的最后访问(access)时间,秒数。
	u32 i_atimens;	// 纳秒数。
	s64 i_ctimes;  	// 文件inode属性的最后改变(change)时间,秒数。
	u32 i_ctimens;	// 纳秒数。
	s64 i_crtimes;  // 文件的最初创建(create)时间,秒数。
	u32 i_crtimens;	// 纳秒数。
	s64 i_mtimes;  	// 文件内容的最后修改(modify)时间,秒数。
	u32 i_mtimens;	// 纳秒数。
};

4、 数据库表文件T(data base table file)对象dbtf:
具有i节点的cao对象才能称为磁盘文件。dbtf通常是大型动态文件,通过数据表记录分配器对象可以动态增减文件的记录、可以1D、2D、3D、、、等动态扩展,前面的磁盘空间文件名字哈希映射表FNHT就是一个2D的256分配器对象ao256使用例子;我们还可以使用64K分配器对象ao64k,3D扩张就会有256T个记录,设每个记录平均占空间64KB,就会有16EB的巨型dbtf文件。数据库DB(data base)是一个目录,可以包含各种杂牌DB子目录,OACS_DB可链接64k个dbtf文件,扩张是没问题,问题是用户磁盘空间是否“够力”而已。我们应用的大多数文件都是dbtf:i节点表文件,各种空间文件,记事本文件text,word文件,网页文件,电子表格文件,资源管理器,编译空间的.h、.oac、.thr文件,等等。大型数据表文件通常是用64K分配器对象ao64k居多,为了更大的动态“弹性”、则是使用256分配器对象ao256居多。世界上大多数软件公司在玩的、通常就是DB节点树,各种应用程序的设计也是围绕dbtf。我一个“初级发烧音响业余玩家”,可没那么多精力去玩花样、只想“简化再简化、最好是一天就可以出结果”;设想2种分配器对象搞定80%的工作量以及规划总体框架,本打算闭关半年攻关、而这就耗费3个月时间了;还得经常通宵,感觉有点力不从心,最近还是决心晚上11点后抽1小时学唱歌,否则唱歌水平又得回到“解放前”;想想七月份,就可以出来“吃喝玩乐”了、还是坚持吧。错误是难免的,以后慢慢修改。

5、编译空间cso(compiling spatial objects)对象:

❏我们不管“先有鸡还是先有蛋”的问题,OACS系统包含了编译空间规则及相应的occ编译器,就如同linux包含gcc编译器一样;不过,“第一次的OACS系统编译”一定是在第三方平台进行。OAC语言本来就是面向对象汇编语言为主,occ编译器自然会比gcc要简单得多,但也是得重新构造和设计,我是选择windows平台来进行。编译器维护一个符号表,符号表中的每项记录一个符号相关信息;例如符号名字,符号类型,数据类型(据此可计算出占用内存大小),偏移起始地址等信息。当使用某个标识符a时,编译器就在符号表中找名为a的符号;找到了就知道其类型,地址等信息,没找到就会报“未定义的符号a”。符号表自然就是一个数据库表文件dbtf,符号表中的一个记录就是“键值对”项(item),键值对通常写法为 name : value(键与值以冒号分割),变量名作为键KEY,然后语义信息作为值。键值对类似于:PHP 中的关联数组,Python 中的字典,C 语言中的哈希表,Java 中的哈希映射,Ruby 和 Perl 中的哈希表。OAC语言的键值对32B/8W(项):最大28个ASCI字符(E文大小写,对于不到28字符的短名字,尾部会存在没有用到的ASCI字符字节、这里为0xFF(对于flash,增长名字时、容易),而没使用/0作为字符串结束。):u8项的类型(数值(Number)类型、或位段类型、或字符串(String)、或函数(Function)、或子节点类型(cao对象、集合对象object)、或数组类型(Array)、或未使用值来声明的变量 undefined、或空(Null)、或可变动态类型var、或唯一值(Symbol)、等等)、u8项的属性、u16项的长度(位段长度、或数组长度),等效为1字u32的键属性说明值。变量(或常量、方法、位段(0--31位)、等,可把变量看做存储数据的容器、大小写敏感)项的符号名字(Symbol Name),编译器在进程所在虚拟内存空间的起始地址开始,每次从头比对查准项名称时,自然会得到项的相应虚拟内存地址,从而用地址替代变量(或常量)标识符。通常标识符只用于链接或调试信息,所有实际运行时要用的信息都已经被转换为某种寻址方式了,内存地址的内容或是用户给出的初始化值、或是初始化为0、等等,还得看是全局变量或局部变量等情形。CPU 访问内存时需要的是地址(Address)或说指针(Pointer),而不是变量名和函数名!变量名和函数名只是地址的一种助记符,当源文件被编译和链接成可执行程序后,它们都会被替换成地址。编译和链接过程的一项重要任务就是找到这些名称所对应的地址。变量名和函数名为我们提供了方便,让我们在编写代码过程中可以使用易于阅读和理解的英文字符串,不用直接面对二进制地址。虽然变量名、函数名、字符串名和数组名在本质上是一样的,它们都是地址的助记符,但在编写代码的过程中,我们认为变量名表示的是数据本身,而函数名、对象名、字符串名和数组名表示的是代码块或数据块的首地址。

❏无论是用OAC语言写编译器、或编写OACS操作系统内核、或编写应用程序、或编写物理(或协议)设备节点树,都是简单的面向对象之数据库DB“节点树”描述模式。抽象说就是“道生一、一生二(动分阴(空间的类对象静态数据)阳(时空的指令流、从而变动的数据流))、二生三(阴阳和合生三才)、三生万物”,遵从“简单到复杂”的自然规律过程;简单地说就是:先编写根类节点、再编写子节点、之后编写孙节点...,从“一到二、到三、到多”、或说从“点到面、到体、到多”而已。即先定义顶层模块类功能,进而分析要构成顶层模块类的必要子模块类;然后进一步对各个模块类进行分解、设计,直到无法进一步分解的底层功能块类,不外是数据库DB节点树编写过程。

❏编译器符号表:根类,类节点,子类节点、...,排列,节点树描述符表。编译空间cso对象对应的简单说就是类文件目录、或说DB目录,终是一个cso目录节点树。OAC语言将“类”划分为类属性和类方法2部分,将类比拟为“cso目录节点”;旗下的类属性对象cao(class attribute object)比拟为“.h”头文件(cao符号表,全局变量、静态变量、堆空间,可以在设计时赋值),类方法对象cmo(class method object)比拟为“.oac”文件(cmo符号表,局部变量,全局类属性常量(u64对齐的cao对象初始化数组常量),方法u16代码数组(一个个方法数组、u64对齐),代码空间)。这样划分,会使得编程更为简单明了;cso类目录节点下、通常还有一个扩展名为.thr的线程(thread)对象文件(线程符号表,方法数组、常量数组,类似.oac,动态变量、堆空间,栈空间),cso根目录下就是包含main()方法的主线程文件了。.h文件反映了类属性对象cao的规划模板,还包含用这模板声明和定义的具体cao对象或cao对象数组;而cao对象的初始化元组是常量,在cmo中定义、也就是说其放置在.oac文件内容中。常量和类方法(函数)都是在.oac文件中编写,指令构成方法(函数)、指令段(伪指令、宏指令、内联函数);宏指令是汇编语言程序中的一种伪指令,是代表某功能的一段指令代码;在宏指令出现的地方,编译器总是自动的把他们替换成相应定义的指令代码块。宏指令与子程序(方法、函数)都可以用一个名字定义一段指令代码,以简化源程序的结构和设计。宏指令的参数传送简单,执行效率高;使用宏指令不会缩短目标程序,适用于子功能代码较短、传参较多的情况。子程序代码(如类的方法)在目标程序中只出现一次,调用子程序是执行同一程序段,因此,目标程序也得到相应的简化;模块化、方法类库、节省内存,可被多次调用、编程效率高;但有额外开销(压入将使用的寄存器组和返回地址,计算转向地址、传递参数,返回时还需弹出恢复等),增加了执行时间;适用于子功能代码较长,调用比较频繁的情况。cmo对象的项多为数组(u64对齐):cao对象的初始化常量元数组,方法的指令数组(oac汇编指令一条为半字,汇编语句和宏指令则要编译成多条汇编指令,而指令码会对应到oac_asm公共汇编语言数据表文件)。方法的语句代码块或元数组,对应的只是cmo对象符号表中一个数组变量项:方法名字,1字u32的数组变量说明值(数组变量属性、长度、等);而方法的语句代码块(包含注释)或元数组则被编译自动生成到.lst汇编列表文件,.thr的线程(thread)对象文件也是类似的、为.asm汇编列表文件。

❏编译器新建一个项目文件时,就会自动构建项目的cso根目录,cso根目录(名称就是用户设定的项目名称xxx)包含三个基本数据库表文件dbtf:xxx.h、xxx.oac、xxx.thr。如何实现从“一到二、到三、到多”的编程?这得看你在根dbtf文件xxx.h中的设计了。类属性对象cao包含有叶子节点(变量)项和子节点项(子类cao对象),编译器会据子节点项自动生成新的cso目录节点及相应dbtf文件(.h是必须的,其它2个可以没用);子节点项(子类cao对象)有3种形式的子目录节点:单一子类cao对象或mod模块对象,子类cao对象数组(cao 对象数组名[len];),多个不同子类cao对象集合(obj 对象集合名[len];)。前2种编译器自动生成一个cso子目录及其下属相应的dbtf文件(模块项则是生成一个链接文件),最后一种、编译器自动生成一个cso子目录及其下属多个cso孙目录及相应的dbtf文件。cso目录名称、dbtf文件名称(或说键值对),自然是统一到“文件节点名字哈希映射表FNHT(file_name_hash_table)”中去。写代码时的对象成员变量(或者常量、方法、位段、数组、等等)名称也只能是包含在头文件(.h)或方法代码文件(.oac)或线程文件(.thr)的文件内容中(键(名称)/值对(相对地址、类型、属性、长度、等)),而对象成员变量最大只有28个ASCI字符;既然都编程序了,简单的E文自然是要懂得的(百度翻译软件辅助)。可以用缩写,又大小写区分,不同对象下可以同名;使用最大28个ASCI字符,来命名对象成员变量已是够用;多于28字符的会被自动截断。我们不希望一个dbtf文件设计一大推变量(常量)项、方法项、子节点项,那会让读者很难看;通常就十多项,加上位段说明项也就几十项而已;是故,dbtf文件(.h、.oac、.thr,变量的容器)使用中型文件较为合适,1页4KB可支持到128项;小型文件模式,最大只有3项;当然,dbtf文件你要设计几万项以上也是可以的,那得使用1D的256分配器对象ao256,最好的模式自然还是中型dbtf文件DB节点树。编译器会根据你的设计自动选择相应的大、中、小dbtf文件类型。

❏编译器目标文件:
源代码编译空间cso目录下通常有6个基本文件:.h、.oac、.thr、.lst、.asm、.obj。这里的.obj是编译前5个文件后生成的可重定位二进制代码文件,相当于java的class类文件;编译器通过链接、类及其子类的目标文件.obj以及动态库dll或静态库slib,生成可执行文件.exe或模块文件.mod。而.exe或.mod目标文件可以单独设定路径文件名字,源代码编译空间cso根目录也是可以单独设定路径。OACS系统根目录及其基本目录文件体系,通常是由内核资源管理器文件进程explo.exe构建和管理。无需预编译头文件.pch、程序数据库文件.pdb、.ilk 状态文件、map文件、等等。
.oac文件包含了编写的方法源代码,.thr文件包含了编写的线程源代码;编译器除了在源代码编译空间cso根目录下,生成可执行文件根名字.exe或模块文件根名字.mod外,还将所有的.h文件、.oac、.thr节点树之所有符号表项合成一个统一的“平面”型根名字.sym符号表文件;这样,编译后、交给用户的可以只是:.exe或.mod文件,以及.sym文件;当然,为免去“逆向工程”反汇编的泄密,也可以不提交.sym文件。其实,当内容很多时,无需考虑泄密问题;因为,就算是给了源代码,大多数人也会懒得去看,还不如告知其原理说明;是故,加解密、专利、等等,我一直认为是多此一举、不好玩。如果源代码编译空间cso目录节点树、没有.thr文件,编译后的模块文件、根名字.mod,只是链接cso目录节点树中的所有.obj(只有.oac文件中的方法(可看作半字(oac的16位指令集)或字(其它cpu结构的32位指令集)、数组的函数)的数组),我们称之为方法库lib(.a文件、一个接一个方法规则排序)。

❏构建第三方平台编译器:
a、c# 编写服务器,vscode做编辑器、cjson通信连接内含的编译器服务器模式,节点对象树。
b、资源管理器风格,包含系统内核、多APP应用项目,对象节点与文件目录节点合一;菜单选择时、自动钩挂生成相应子目录(类)和文件。
c、软件模拟器,含自设CPU。
或者用 Node.js 来做前后端分离,用JS(JavaScript),vue.js编程工具、等等,也是另一种方案。我是没用过,但相信许多人都可以用之来简洁实现。

❏cso目录下的数据表dbtf文件(.h、.oac、.thr,变量的容器)i节点:与普通(虚拟)文件i节点vfs_inode不一样的主要有i_pdata.成员。

u29w i_pdata.{
   u32 i_dsbuf;	// dbtf对象磁盘空间数据区的缓冲页号(8扇区),最大包含128项 i_item.。大型dbtf对象不使用。
	u64 i_dssadd;	// 大型dbtf对象磁盘地址空间的扇区开始地址,或256双页分配器对象aod256(256 allocator object)的开始地址。
	u32 i_sh_addr;	// 一个dbtf对象作为一个节区(section area)符号表,在进程所在虚拟内存空间的起始地址。
	u32 i_sh_offset; // 此成员的取值给出节区(dbtf对象)虚拟内存空间的第一个字节与文件头(Section Header Table)之间的偏移。
	u32 i_sh_size;   // 此成员给出节区的长度 (字节(项数*32B))。
	u8w i_item.[3];	// 3个变量(或常量、方法等等)项,24W,每项8W、32B。大型dbtf对象不使用、或者待定。
};

u8w i_item.{		// 成员表达。成员数通常就几个到十多个,很少超过100个的。
	u8 s_name[28];	// 变量(或常量、方法、位段(0--31位)、等等)项的符号名字(Symbol Name)。
	u8 s_type;		// 项的类型。
	u8 s_attr;		// 项的属性。
	u16 s_type;	    // 项的长度(位段长度、或数组长度)。
};

二、OACS操作系统内核节点树

如何编写OACS操作系统内核?如何实现简单的面向对象之数据库DB“节点树文档”描述模式?如何遵从“简单到复杂”的自然规律过程?道理大家都明白的,具体去实现时、你会发现得面对许多困难;世界上从没有“简单的事情”,只是当你的“基本功”到达时,才会有“简单”而已;俗话说:台上1分钟,台下十年功。当你想做一名“业余玩家”时,注定是要“独自”面对巨大的困难;你得抛开“红尘俗念”,就像一匹在宇宙中流浪的“孤狼”。2020年玩《中古音》时,我用“中古音”改编了一首歌,现在都还没学好。

星空迷情(《忘情冷雨夜》改編):

流浪這星空,li.ɐu1lɒŋ3dʑɛ6seŋ7kuŋ7(hʊŋ7)
去找失落片段,kʏ5(hɵy5)dзau6ɕɜd7lɒg1pen5duɒn3
冰冷中我心感覺凌亂。bIŋ7lɐŋ2dʐuŋ7ŋɒ2si.ɐm7gɒm6gɔg4lIŋ1luɒn3
仍然懷念逝去的歲月,rIŋ1rɛn1huɐ.i1nem3dʑɛi3(sɐi3)kʏ5(hɵy5)deg7sv.ai5ŋyd1
曾經多麼激蕩過,tsəŋ1geŋ7dɒ7mɒ2geg7dɒŋ2guɒ5
問誰能讓快樂再一遍。mvən3tɕv1(sɵy1)nəŋ1rœŋ3kuɔi5(fai5)lɒg1dzə:i5iɐd7ben5

忘掉那一天,mvɒŋ3deu3nɒ2(na2)iɐd7ten7
記不起是那年,gi.ə5bv.əd7ki.ə6dʑi2(si3)nɒ2(na2)nen1
只記得恍惚中此處徘徊。dʑi6gi.ə5dəg7hv.ɒŋ6huəd7dʐuŋ7tsi6tɕʏ5puə.i1huə.i1
濃情年月再不回頭,nʊŋ1tsɛŋ1nen1ŋyd1dzə:i5bv.əd7huə.i1təu1
純真的心早經蛻變,tɕuɜn1dʑɜn7deg7si.ɐm7dzɒu6geŋ7tuɒi5bɛn5
從前片段漸漸飄遠。tsʊŋ1tsen1pen5duɒn3dziəm2dziəm2pIu7-yn2

望著消逝的光景,mvɒŋ3drœg1sIu7dʑɛi3(sɐi3)deg7guɒŋ7giɐŋ6
只盼急追中可找得到你;dʑi6pan5gɜb7drv.ɐ7dʐuŋ7kɒ6dзau6dəg7dɒu5ni.ə2
馳騁太虛,tʂ1trɛŋ6tɒi5(tai5)hʏ7
尋覓逝去的遠古。si.ɐm1meg1dʑɛi3(sɐi3)kʏ5(hɵy5)deg7-yn2gu6
螺旋飄飛的軌跡,luɒ1syan1pIu7fəi7deg7gv.ɐ6dzɛg7
迎著星光在延伸,ŋiɐŋ1drœg1seŋ7guɒŋ7dzə:i2jɛn3ɕɜn7
傻癡癡吻向幽暗、...默然。ʃua6(sɔ2)tʂ7(tɕi7)tʂ7(tɕi7)mvən2hœŋ5i.əu7-ɒm5、...məg1rɛn1
(今改为:独孤孤旋進這幽暗、...默然。)
。。。
註明:國際音標後的數字為音調、對應音樂的7音階。與粵語讀音區別大時,()內為粵語音標。

❏OACS操作系统的根目录符号为“/”。在源代码编译空间cso根目录、别名是“sysroot”,cso根目录:根目录类名“sysroot”,用户需编写的数据表文件dbtf:sysroot.h、sysroot.oac、sysroot.thr。这些文件以及其子类对象的.obj和动态库dll或静态库slib,最终是被编译成sys.bin(镜像文件),放到磁盘空间上的,但最终会被加载到系统硬件flash空间(spi_flash、eMMC、Nand_flash、SDCard 等,由CPU内部厂家固化的ROM代码,从而sd卡、或串口、等等模式导入到flash空间、内存SRAM空间);OACS操作系统并不大,我得时刻牢记内核只有约3千行的代码量。新的CPU与硬件设备体系,我会将DMA都去除,但OACS操作系统得考虑兼容其它CPU结构体系;而由此而带来的“复杂性”,将由OAC编译器功能去中和。我们先要面对的问题是:系统上电后,会加载镜像文件sys.bin(image)到内存(厂家固化的ROM代码进行)、之后跳到sys.bin的sysroot.thr文件之0号线程对象kthread0第一行代码_start执行;而此时,系统内存管理空间还没建立、相关flash设备还没初始化,根目录/、也不存在,就不用说进程、线程等管理对象还没有建立;是故,必须默认是先有“鸡”再有“蛋生鸡体系”,默认存在0号系统内核进程,默认有sysroot.thr文件的0号内核线程对象_start;你需规划和编写的内核线程对象_start,就是要实现这一大堆初始化工作过程的“先行鸡”0号内核线程kthread0对象;当进程线程管理对象体系建立后,再自我“钩挂”到“蛋生鸡管理体系”。

❏这一过程有点复杂:
对于小资源的单片机,或许只是1KB的flash、256B的SRAM;常是通过仿真器直接烧写镜像代码(.bin文件内容)进去,然后仿真调试;用occ编译器编辑代码和编译,而无需复杂的uboot启动程序。对于SRAM大于32KB的单片机而言,通常OACS操作系统编译后也只是约128KB的elf模式文件(.exe +.sym),可在编译器平台下运行;但通常做法是删除许多编译空间运行的信息,制作为、约16KB的.bin模式的内核镜像文件image。是故,OACS操作系统内核较小、不需要SPL(Secondary Program Loader)二级加载,最好是直接烧写进SoC 厂家的BootROM中。
如今、通常的SoC上电过程:
0、上电后,BootROM 开始执行,初始化时钟,关闭看门狗,关 Cache,关中断等等,根据 Bootstrap Pin 来确定启动设备,初始化部分外设;
1、使用外设驱动,从存储器读取 SPL;(对于OACS、直接读取sys.bin(image)就好了)
---------------- 以上部分是 SoC 厂家的事情,下面是用户要做的事情 ----------------
2、SPL 被读到 SRAM 执行,此刻,控制权以及移交到我们的 SPL 了;
3、SPL 初始化外部 DDR;
4、SPL 使用驱动从外部存储器读取 u-boot 并放到 DDR;
5、跳转到 DDR 中的 u-boot 执行;
6、加载内核。
当然,我们也是可以直接用仿真器烧写镜像代码进SoC芯片;但对普通用户而言,多是用SD卡、U盘、虚拟串口、等工具来安装OACS系统。

❏OACS操作系统主CPU(管理DDR的)之_start(初始过程代码_start_init):编写数据表文件dbtf:sysroot.h、sysroot.oac、sysroot.thr,来实现。

1、划分内存区域(zone):物理内存地址48位(大多数单片机是32位的),页式机制:1页8扇区、4kb,共有32位4G个物理页(实际页数量取决于芯片硬件设计);每个CPU核对应一个一个cso子目录(或说子节点node),所有CPU核的cso子目录链接成一个根目录“/”下的cpu目录,在sysroot.h数据表文件中的cao对象内只是占据一项(obj cpu[len]; // len是cpu数);每个CPU核都统一分配有本地存储器SRAM区域(L1一级Cache、或许有L2二级Cache),所有CPU核都可以访问全部的系统物理存储器,但是访问本节点CPU内的存储器所需要的时间,比访问某些远程节点内的存储器所花的时间要少得多;内存区域(zone)是以页为单位、统一编址,除了主CPU之SRAM区域cpu0_mem,还有物理设备内存区域、其它CPU[len]的本地存储器SRAM(cache)区域cpun_mem、FLASH空间区域(有些cpu核集成有flash空间)、BootROM区域、DDR内存区域、等等;不同硬件,不一样的sysroot.h及下层cso目录.h文件的节点树一层层编写,无需各种配置文件。

_start_init首先要做的事情是:
在主CPU之SRAM区域cpu0_mem,建立256个vao256r根对象分配器对象(v节点  allocator root object,需占用256个*64B = 16KB = 4页);其中0号vao256r根对象分配器对象、看作为“森林根/”,管理1---255号的动态分配或释放,1---255号vao256r根对象分配器对象、看作为“树根”;每个CPU核都有一个vao256r[n]对象,它们分布在每个CPU核的本地cache空间,它们的根目录结构(/cpu/cpun_mem/...)是可以不一样的,由用户设计而定。一片深林,如何种植这最多256“棵树”?自然是每个CPU核对应一“棵树”,一个soc芯片也就最多集成1百多个CPU核吧、大多只是1--8核;深林根目录“/”下的一层子目录并非都是对应一棵棵“树”的,而是整个内存v节点磁盘文件目录体系节点树只是对应一“棵树”(生长在DDR空间的v节点文件打开表);实际上,我们是用空间区域(space zone)对应一“棵树”。内存v节点磁盘文件目录体系节点树生长在DDR空间,i节点文件目录体系节点树生长在磁盘空间、但其“生长变化”都得依靠在DDR空间的v节点文件打开表中的操控;每个CPU核都统一分配有本地存储器SRAM区域(L1一级Cache、或许有L2二级Cache)cpun_mem,有对应的vao256r[n]根对象分配器对象;另外还有物理设备空间区域,flash空间区域,BootROM区域,i节点号空间,v节点号空间,虚拟内存空间,磁盘空间,等等;所有的“树”都对应有vao256r根对象分配器对象,“树根”都在主CPU之SRAM区域cpu0_mem之0号vao256r[0]根对象分配器对象上。

我们需要建立空间管理体系对象,来管理各个内存区域(zone),DDR内存空间,FLASH空间(有些单片机集成有flash)、磁盘空间、虚拟内存空间、设备内存空间、文件v节点打开表空间、等等;它们都将被挂接到主CPU的vao256r[0](简写为vao256r)根对象分配器对象上,以便于内核管理。任何内存对象,你都得先分配其相应内存空间容器来“装配”吧,DDR有限、还得考虑先在虚拟内存空间分配;考虑速度和效率,则vmo的对象v节点地址还都得是物理页地址,还需一个映射层、反映虚拟内存到物理内存的映射。我们需要2个链表环:一个是文件目录体系v节点树环,一个是空间分配管理体系对象节点树环。先有空间,对象在空间运动时、才开始有时序、时间。

主CPU的vao256r.vmo对象、看作从深林根部伸出2个链表节点环:文件目录体系v节点树环和空间分配管理体系容器对象节点树环,实现从“一到二”的深林生长。这2个链表节点环,其实都只是包含最多256项的“树根”;一个是反映文件目录体系v节点树的生长,另一个则反映在各种空间的伸展情形(空间占用、内存容器)。所有vmo对象的项名称都是一样的,但其“键:值、对”之属性描述值、意义就不一定是一样的,得看其表述的是什么样类型v节点。就算对应磁盘文件的v节点也有2种基本形态:vmo + 96B的i节点 = 128B,vmo + 224B的i节点 = 256B;也就会有2种不同的DDR空间之分配器容器与之对应,钩挂都是通过其包含的vmo对象之链表方法进行的;即使是磁盘空间的文件目录i节点树,钩挂也是相应的v节点对象之链表方法进行的。使用统一的vmo对象,将删除linux的大量结构表示,大幅度减少代码量。从内核角度看,一切都是v节点对象(= vmo + xxx)。

文件目录体系v节点树环、根下的部分一层子目录:每项都对应有一个v节点文件打开表管理对象vmo、(只是暂时规划)。

/cpu,  CPU核本地存储器SRAM区域(L1一级Cache、或许有L2二级Cache)、等等,每个CPU核vao256r[n]对象钩挂链接在vao256r上,树根节点;
/bin,   存放二进制可执行文件(ls,cat,mkdir等),常用命令一般都在这里;
/sbin, 系统管理命令,只有root才能访问,这里存放的是系统管理员系统级别的管理命令和程序;
/lib,    标准程序设计库,又叫动态链接共享库,作用类似windows里的.dll文件;
          /lib/modules 目录包含系统核心可加载各种模块,尤其是那些在恢复损坏的系统时重新引导系统所需的模块(例如网络和文件系统驱动);
/etc,   存放系统管理和配置文件及脚本;
/dev,  用于存放物理设备文件节点树,物理设备内存空间区域;
/pdev,用于存放协议设备文件节点树,如字符设备、块设备、TCPIP协议设备、等等;
/home  存放所有用户文件的根目录,是用户主目录的基点,比如用户user的主目录就是/home/user,可以用~user表示;
/root     超级用户(系统管理员)的主目录(特权阶级);
/usr      这是最庞大的目录,要用到的应用程序和文件几乎都在这个目录;
	/usr/x11r6 	存放x window的目录;
	/usr/bin 		众多的应用程序; 
	/usr/sbin 		超级用户的一些管理程序;  
	/usr/doc 		OACS文档 ;
	/usr/include 	包含OACS内核的源代码编译后的符号表文件system.sym。  
	/usr/lib 		常用的动态链接库和软件包的配置文件;  
	/usr/man 		帮助文档;  
	/usr/src 		源代码目录,OACS内核的源代码就放在这里;  
	/usr/local/bin 	本地增加的命令;  
	/usr/local/lib 	本地增加的库;
/lost+found	这个目录平时是空的,系统非正常关机而留下“无家可归”的文件(windows下叫什么.chk)就在这里;
/mnt	系统管理员安装临时文件系统的安装点,系统提供这个目录是让用户临时挂载其他的文件系统;
/opt	额外安装的可选应用程序包所放置的位置。一般情况下,我们可以把tomcat等都安装到这里;
/tmp	用于存放各种临时文件,是公用的临时文件存储点;
/var	用于存放运行时需要改变数据的文件,也是某些大文件的溢出区,比方说各种服务的日志文件根(系统启动日志根);
/ddr	DDR内存空间区域,非磁盘文件,树根节点;
/flash	flash空间区域,非磁盘文件,树根节点;
/vms	virtual memory space虚拟内存空间区域,非磁盘文件,树根节点;
/dsa	disk space area磁盘空间区域,非磁盘文件,树根节点;
/bootrom		bootrom厂家启动代码空间区域,非磁盘文件,树根节点;
/inode	i节点磁盘空间区域,非磁盘文件,树根节点;
/vnode	v节点内存空间区域,非磁盘文件,树根节点;
/proc	存放动态变化的进程process文件,树根节点。

我们建立起一个“根支点”,就可以在此支点的基础上、通过“搭积木”模式逐步建立起OACS系统以及“一切可能”。vao256对象分配器对象,其本质是表述一个“最大256个对象的动态数组”,加v表述、是在内存中而已,加r表述这里是用于“节点树根”;vao256对象分配器对象完全是可以用于其它场合的,在这里是表述为、vao256r根对象分配器对象。0号对象通常用于管理1--255号对象的分配与释放,必须有。

u16w vao256r. {    		// 8W的根(/)vmo对象 + 8W位图 ,vao256r分配器根对象。
	u8w  vmo.; 	    // 0号则表述为内核文件系统(也是磁盘文件体系)的总根“/”之vmo对象 。	
	u8w  bitmap;	// 256位图,对应最多256个vmo对象项。
};

u8w  vmo. {    		// 文件打开表v节点管理对象8字/8w(v node management object),嵌入(被包含)到v节点中、为其成员。
	u32 v_pdnn; 	// 对象父目录v节点(parent directory node number),根目录节点为0。
	u32 v_hnext; 	// 对象v节点head头钩子,本对象v节点单向环下一个子v节点,钩挂对象的子节点(头插入),文件体系v节点树环。
	u16 v_type; 	// 对象v节点所属类的类型。为0
  u16 v_fcount;	// 本对象v节点单向环的实际子节点计数。高8位根目录下最大256项,低8位对象v节点树双向环计数。
  u32 v_count;	// 对象v节点引用计数。为0、不使用
	u32 v_next; 	// 对象v节点钩子,下一个v节点。自定义对象v节点双向环,空间分配管理体系对象节点树双向环、头节点。
	u32 v_prev; 	// 对象v节点钩子,上一个v节点。
	u32 v_sflags; 	// 对象v节点状态标志。
	u32 v_fpbuf;    // 对象v节点物理内存缓冲区页起始地址,类同this指针 。空间(如CPU之SRAM区域cpun_mem)初始页号。
};

2、_start_init其次要做的事情是:内存区域(zone)初始化,其实就是填写:vao256r根对象分配器对象。也就是说,根据BootROM提供的SoC芯片flash信息表(当然、信息表最后会在/etc/...以配置文件建立,问题是现在还不知道磁盘在哪个“角落”);如每个cpu核之SRAM区域cpun_mem信息,DDR内存空间信息(其实页、大小),等等,来初始化一个一个相应的vao256r[n]对象、并钩挂到vao256r.vmo.v_node(v_next、v_prev);同时,也会在内存文件体系建立相应的“/”下相应子目录(只是v节点的vmo对象、钩挂);最终都是类似一个循环填表过程而已,没几条指令。

到此,我们规划了“森林根”,就像玩游戏一样、也在森林中种下一些树根;接着,就是开始“这些树根的生长发育”之旅行。

3、在开始旅游之前,我们得介绍一些相关内容、这段说的是“页表”。

逻辑地址经段机制转化成线性地址,线性地址又经过页机制转化为物理地址。
AOS用户进程空间:256TB,
高128TB为内核映射的共享虚拟内存空间;通常,低128TB才是用户进程管理的虚拟内存空间。
虚拟内存空间线性地址48位:PGD.PUD.PMD.PTE.offset。
PGD(9位) + PUD(9位) + PMD(9位) + PTE(9位) + 页内12位偏移地址offset。
用户进程空间虚拟内存线性地址64位:高16位64K的进程号,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)。

当用户进程需要内存时,从内核获得的仅是虚拟的内存区域,而不是实际的物理地址,进程并没有获得物理内存,获得的仅仅是对一个新的线性地址区间的使用权。实际的物理内存只有当进程真的去访问新获取的虚拟地址时,才会由“请求页机制”产生“缺页”异常,从而进入分配实际页面的例程。该异常是虚拟内存机制赖以存在的基本保证——它会告诉内核去真正为进程分配物理页,并建立对应的页表,这之后虚拟地址才实实在在地映射到了系统的物理内存上。(当然,如果页被换出到磁盘,也会产生缺页异常,不过这时不用再建立页表了)。这种请求页机制把页面的分配推迟到不能再推迟为止,并不急于把所有的事情都一次做完。之所以这么做是利用了内存访问的“局部性原理”,请求页带来的好处是节约了空闲内存,提高了系统的吞吐率。在内存区域结构上的nopage操作。当访问的进程虚拟内存并未真正分配页面时,该操作便被调用来分配实际的物理页,并为该页建立页表项。

虽然应用程序操作的对象是映射到物理内存之上的虚拟内存,但是处理器CPU直接操作的却是物理内存。所以当应用程序访问一个虚拟地址时,首先必须将虚拟地址转化成物理地址,然后处理器CPU才能解析地址访问请求。地址的转换工作需要通过查询页表才能完成,概括地讲,地址转换需要将虚拟地址分段,使每段虚地址都作为一个索引指向页表,而页表项则指向下一级别的页表或者指向最终的物理页面。因为在虚拟地址映射到页之前必须先分配物理页——也就是说必须先从内核中获取空闲页,并建立页表。但是实际上系统使用内存时还是倾向于分配连续的内存块,因为分配连续内存时,页表不需要更改,因此能降低TLB的刷新率(频繁刷新会在很大程度上降低访问速度)。

代码段:代码段是用来存放可执行文件的操作指令,也就是说是它是可执行程序在内存中的镜像。代码段需要防止在运行时被非法修改,所以是只读。
数据段:数据段用来存放可执行文件中已初始化全局变量,换句话说就是存放程序静态分配的变量和全局变量。
BSS段:BSS段包含了程序中未初始化的全局变量,在内存中 bss段全部置零。
堆(heap):堆是用于存放进程运行中被动态分配的内存段。
栈:用户存放程序临时创建的局部变量,也就是说我们函数括弧“{}”中定义的变量(但不包括static声明的变量,static意味着在数据段中存放变量)。除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。由于栈的先进先出特点,所以栈特别方便用来保存/恢复调用现场。从这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。
数据段、BSS和堆通常是被连续存储的——内存位置上是连续的,而代码段和栈往往会被独立存放。堆和栈两个区域一个向下“长”(i386体系结构中栈向下、堆向上),一个向上“长”,相对而生。堆、bss、数据段(初始化过的)都在进程空间中由数据段内存区域表示。

物理页(PP, Physical Page)(也叫页框、页帧、page frame)4kb,物理内存中的页PP;
虚拟页( VP, Virtual Page ),虚拟空间中的页VP;
磁盘页( DP, Disk Page ),磁盘空间中的页DP。

从Virtual Address到Physical Address的映射,通过一个叫MMU( Memory Mangement Unit )单元来完成。每一个进程有它自己的页全局目录PGD(Page Global Directory、一个物理页,也称为PGD页表、PGD描述符)和自己的页表集。当发生进程切换时,把cr3控制寄存器的内容(页全局目录基址)保存在前一个执行进程的页全局目录PGD描述符(一个48位页全局目录物理基址的指针、或者32位物理页号)中,然后把下一个要执行进程的页全局目录PGD描述符的值装入cr3寄存器中。因此,当新进程重新开始在CPU上执行时,分页单元指向一组正确的页表。分页单元( paging unit )把线性地址转换成物理地址。其中的一个关键任务就是把所请求的访问类型与线性地址的访问权限相比较,如果这次内存访问是无效的,就产生一个缺页异常。

页表:把线性地址映射到物理地址的数据结构称为页表(page table)。页表存放在主存中,并在启用分页单元之前必须由内核对页表进行适当的初始化。正在使用的页目录的物理地址存放在控制寄存器CR3中。

有n个运行的进程(n小于等于64k),就必须分配n个装配PGD页表的物理页。PUD页表、PMD页表、PTE页表的数量是跟用户进程相关,或说编写用户程序相关;通常PUD页表会被分配物理内存,PMD页表、PTE页表、则会是部分被分配物理页而驻留内存。PGD页表、PUD页表、PMD页表、PTE页表、统称用户进程页表,这4种页表都有512个条目项,PGD页表项指向一个PUD页表、PUD页表项指向一个PMD页表、PMD页表项指向一个PTE页表、PTE页表项指向一个物理页,offset是页内偏移。一张表需要一个物理页框来装配,或说一张表大小是4kb、512个表项、表项大小为8b = 2w(2字),其中36位为物理页号、另12位+16位为属性标志。
表项 = 高16位属性状态标志 + 36位为物理页号(实际只使用到32位) + 12位页属性标志。

a、物理页、页表项结构

内核必须记录每个物理页的状态,是属于用户进程的页、还是内核的,空闲还是使用、等等;linux将物理页信息保存到struct page的页描述符中,占据32字节、约为一页的1%,浪费啊、4G物理页就要额外占去128GB物理内存。mem_map是一个struct page的数组,管理着系统中所有的物理内存页面。在系统启动的过程中,创建和分配mem_map的内存区域。OACS追求小代码量,任何不符合的“苗头”都会想法扑灭,是故、去除linux的struct page页描述符。
linux页描述符结构struct page中字段:
virtual  对于需要使用高端内存区域的页,即无法直接映射到内核的虚拟地址空间,因此需要用virtual保存该页的虚拟地址。这是老CPU错误,不必要!
_refcount    引用计数字段。没有关联实际对象、太细,去除!在vma对象虚拟内存段中实现。当对象释放时,是连续多个页回收。
_mapcount 被页表映射次数。没有关联实际对象、太细,去除!在vma对象虚拟内存段中实现。
index 在映射的虚拟空间(vma_area)内的偏移。没有关联实际对象、太细,去除!在vma对象虚拟内存段中实现。
private 私有数据指针,由应用场景确定具体含义。太细,去除!在vma对象虚拟内存段中实现。
lru 链表头。太细,去除!
mapping    指向与该页相关的address_space对象(类似file_vma对象)。太细,去除!在文件v节点才有指向file_vma对象的mapping。

OACS的页描述符结构struct page相比linux要简单很多,页在内存中为物理页时、大部分标志位才有意义;物理页简单分类为页表的页、非页表的页,而页表有4种:PGD页表、PUD页表、PMD页表、PTE页表。页为页表时,它的大部分标志对其所映射之所有页面起作用。

u48 page. {	        // OACS的页描述符结构。
  u36 p_pno;      // 物理页号。(实际物理页号只使用到32位)
  u12 p_flags.;   // 页属性标志。
};

u12 p_flags. {
	bit0  PRESENT;  // 1、物理页号(页面)有效,或说页在内存中。0、否,缺页异常。
	bit1  RW;		// 1、页面可以读写Read/Write,0、为只读。当CPU在特权级时,此位不起作用。
	bit2  USER;	    // 1、页面所有级别的程序都可访问,0、只允许Supervisor特权程序访问。
	bit3  PWT;	    // 1、用Write-Through的Cache类型,0、用Write-Back的Cache类型。CR0.CD=1(Cache被Disable),忽略。
	bit4  PCD;		// 1、页面是不能被Cache,0、允许Cache。当CR0.CD=1时,此标志被忽略。
	bit5  ACCESSED; // 访问位。1、页面已被访问(读或写),OACS用来监视页的使用频率。
	bit6  DIRTY;	// 脏位。1、页面内容已经改变,OACS用来稍后回写磁盘。
	bit7  PS;		// Page Size标志。1、(少用一级、PTE页表),0、4KB。
	bit8  GLOBAL; 	// 全局位。1、表项所指页是全局Page,在CR3被更新时,TLB内的全局Page不会被刷新。在CR4的页全局启用PGE(Page Global Enable, )标志置位时、这个标志才起作用。
// t_pflags.[11:9] AVL;	// CPU忽略,软件可以使用。
	bit9   FVO; 	// 1、该page属于页缓存或文件映射、FVO对象,0、该page为匿名映射、anon_vma对象。
	bit10 NOEXEC; 	// 1、该page不可执行,0、否。
	bit11 FILE; 	// 1、该page为非线性映射,0、否。
};

u64 table_entry {		// PGD页表、PUD页表、PMD页表、PTE页表、的页表项结构。
    u16 t_flags.;		// 页表项所指页的属性状态标志。
  u48 page t_page.;	// 页表项所指的页描述符结构。
};

u16 t_flags. {
	bit48  PG_unevictable; 	// 1、表项所指页不可回收,0、否。该page被锁住,不能交换。
	bit49  PG_mlocked; 		// 1、表项所指页在对应的VMA中被锁定locked,0、否。一般是通过系统调用mlock()锁定了一段内存。
	bit50  PG_locked; 		// 1、表项所指页被锁定,0、否。
	bit51  PG_error;    	// 1、表项所指页的I/O操作发生了错误,0、否。
	bit52  PG_uptodate; 	// 1、表项所指页的数据已经刷新,0、否。
	bit53  PG_slab;    		// 1、表项所指页属于slab分配器,0、否。
	bit54  PG_writeback;    // 1、表项所指页中的数据正在被回写到后备存储器,0、否。
	bit55  PG_private; 		// 1、表项所指页为私有,0、否。用于I/O的页可使用该字段将页细分为多核缓冲区。

	bit56  PG_arch_1; 		// 1、表项所指页与体系结构相关,0、否。XXX、OACS不用。
	bit57  PG_swapbacked; 	// 1、表项所指页的页面后备存储器swap,通常匿名页面才可写回swap分区,0、否。XXX、OACS不用
	bit58  PG_reclaim; 		// 1、表项所指页马上要被回收,0、否。当PFRA决定回收某个page后,需设该标志。XXX、OACS不用
	bit59  PG_lru; 		    // 1、表项所指页加入了LRU链表,0、否。内核使用LRU链表管理活跃和不活跃页面。XXX、OACS不用。
	bit60  PG_active; 		// 1、表项所指页活跃程度,0、否。在kswapd页面回收中使用。XXX、OACS不用。
	bit61  PG_referenced;   // 1、表项所指页刚刚被访问过,0、否。在kswapd页面回收中使用。XXX、OACS不用。
	bit62  PG_swapcache;    // 1、表项所指页处于swap cache中,0、否。XXX、OACS不用。
	bit63  PG_reserved;    	// 1、预留页、表项所指页不可交换到swap,0、否。XXX、OACS不用。
};

PG_owner_priv_1	表项所指页为所有者使用。
PG_mappedtodisk	表示page中的数据在后备存储器中有对应。

OACS或许会用LRU类型的算法置换页面,但总觉得置换页面显得“太细”,不如置换具有连续页面“对象”;是故,t_flags标志字段还在思考中,标志太多也意味着代码量增大。

b、fvo流容器对象Flow vessel object

一个页面、我感觉“太细”,尽管有“死板”的2MB大页面存在;是故,用户程序编写有必要增加一种可变的连续页结构、虚拟内存空间流容器对象。页描述符结构、页表项结构,描述的是虚拟内存空间页到物理内存页的映射关系和物理页的状态标志。256TB的用户进程虚拟内存空间,以页为单位有64G页,OACS的流容器对象fvo最大为4k个连续页。为了速度,有时候fvo在虚拟内存空间是连续页、映射到物理内存空间时、也是不可交换出去的连续页;OACS在用户进程虚拟内存空间与内核物理内存空间交换数据时,通常是fvo指针提交、而非拷贝!如果一个4MB的fvo使用拷贝要多花费近千万条指令周期,即使你有几百万个CPU并行、也是无法补偿其亏损。那些一个进程的多个线程可以并发运行在多个CPU上的各种锁、淫荡技巧、等等,在我看只是“花拳绣腿”、引起代码量巨增。fvo不一定在物理空间也是连续页,如果只是一个页时,也要分配2k个连续物理页,就很浪费了,应该是动态按需分配物理页(非线性映射)。

u48 fvo. {			// 虚拟内存空间流容器对象Flow vessel object结构。
	u36 fvo_start;	// fvo对象的虚拟线性地址开始页号,PGD.PUD.PMD.PTE.0。地址空间(address_space)	
	u12 fvo_len;	// fvo对象的连续页数、1---4k页,流容器最大16MB或8GB(页面是2MB的大页时)。
};

c、进程虚拟内存空间vma对象(vm_area_struct)

用户进程有 vma对象头节点vm_head项,钩挂进程的所有vma对象;vm_area_struct对象(简称vma对象)是指向虚拟内存空间的一段内存区域。vma对象有点类似分段内存,OACS规定:vma对象最大为2G页,最小为一页;vma对象是将“访问属性一致的虚拟地址空间(fvo流容器对象)存放在一起”,所谓访问属性在这里无非指的是“可读、可写、可执行、锁、偏移、等”。OACS的vma对象归并了许多虚拟内存空间的各种对象(数据库表、静态动态方法库、进程虚拟空间、文件目录流、显卡内存空间、缓冲区、等等),关联了文件磁盘空间、虚拟内存空间、内核物理内存空间、用户进程线程、系统调用、等等。

u8w vma. {		    // vma对象结构、32字节,可看作vmo对象的变体。
	u64 vm_pos;	    // 关联文件的偏移量、单位字节。
	u32 vm_next; 	// vma对象节点钩子,下一个对象号。钩挂到相应进程vm_head头,最大可达到64K个或4G个。
	u32 vm_prev; 	// vma对象节点钩子,上一个对象号。
	u48 vm_start;	// vma对象的fvo流容器对象虚拟线性地址开始页号,PGD.PUD.PMD.PTE.0、u48。
	u48 vm_onn;	    // 关联文件v节点号。
	u32 vm_sflags.; // vma对象状态标志。
};

u8w file. {    		// 进程打开文件描述符对象file,32B。功能类同linux的struct file、结构类同address_space对象。
	u64 f_pos;	    // 关联文件的偏移量、单位字节。
	u32 f_next; 	// file对象节点钩子,下一个对象号。钩挂到相应进程file_head头,最大可达到4G个。
	u32 f_prev; 	// file对象节点钩子,上一个对象号。
	u48 f_start;	// file对象的fvo流容器对象(窗口)虚拟内存地址开始页号,大型文件才需要(相当于文件窗口缓冲区)。	
	u48 f_onn;	    // 相应打开文件表的文件v节点对象号。
	u32 f_sflags.; 	// file对象状态标志。
};

u32 vm_sflags. {			// 也是f_sflags状态标志。
	bit0    VM_READ;		// 进程对vma对象、从而流容器对象、从而页的读权限。1、可读,0、 否。
	bit1    VM_WRITE;		// 进程对vma对象、从而流容器对象、从而页的写权限。1、可写,0、 否。
	bit2    VM_EXEC;		// 进程对vma对象、从而流容器对象、从而页的执行权限。1、可执行,0、 否。
	bit3    VM_SHARED;		// 进程对vma对象、从而流容器对象、从而页的多个进程共享权限。1、可多个进程共享,0、 否。
	bit4    VM_MAYREAD;	    // 进程对关联文件的读权限。1、可读,0、 否。
	bit5    VM_MAYWRITE;	// 进程对关联文件的写权限。1、可写,0、 否。
	bit6    VM_MAYEXEC;	    // 进程对关联文件的执行权限。1、可执行,0、 否。
	bit7    VM_MAYSHARED;	// 进程对关联文件的多个进程共享权限。1、可多个进程共享,0、 否。
	bit8    VM_GROWSDOWN;	// 1、 vma对象可以向低地址扩展,0、 否。
	bit9    VM_LOCKED;		// 1、 vma对象锁着的、也不能交换出去,0、 否。
	bit10  VM_IO;		    // 1、 vma对象映射设备的I/O地址空间或类似,0、 否。
	bit11  VM_FVO;		    // 1、 vma对象只是一个关联着文件磁盘空间映射的fvo流容器对象,0、 否。
	bit12  VM_KERNEL;		// 1、 vma对象是内核对象、连续物理页内存、直接映射,0、 否。
	bit13  VM_DONTCOPY;	    // 1、 fork创建新进程时、不复制vma对象,0、 否。
	bit14  VM_DONTEXPAND;	// 1、 通过系统调用mremap()禁止vma对象扩展,0、 否。
	bit15  VM_PAGE_FILE;	// 1、 vma对象的fvo流容器对象的页是非线性映射,0、 否。

// 进程对关联文件的状态标志:
	[17:16]  VM_O_ACCMODE;	// 00、要求读权限,01、要求写权限,10、要求读写权限,11、要求特殊权限。
	bit18  VM_O_CREAT;	    // 1、 当该文件不存在时创建并打开此文件,0、 否。
	bit19  VM_O_EXCL;		// 1、 O_CREAT同时为1,当指定的文件已经存在时open失败,保证不破坏已存在的文件。0、 否。
	bit20  VM_O_NOCTTY;	    // 1、 pathname所指不是终端,0、 否。
	bit21  VM_O_TRUNC;	    // 1、 截断文件为零长度,这一选项只对普通文件有用,对诸如目录或FIFO之类的特殊文件无用。0、 否。
	bit22  VM_O_APPEND;	    // 1、 所有write()操作写数据至文件尾而不管文件位置在何处,0、 否。
	bit23  VM_O_NONBLOCK;	// 1、 非阻塞I/O方式打开文件,0、 否。
	bit24  VM_O_SYNC;		// 1、 同步I/O方式写文件,导致任何写该文件的操作都阻塞、直至相关保存操作完成。0、 否。
	bit25  VM_O_RSYNC;	    // 1、 提供同步的I/O数据完整性,等待写完成后才读。0、 否。
	bit26  VM_O_DIRECT;	    // 1、 无缓冲I/O方式,0、 否。
	bit27  VM_O_DIRECTORY;	// 1、 pathname必须是目录、否则失败,0、 否。
	bit28  VM_O_EOF;		// 1、 报告文件结束,0、 否。
	[31:29]  VM_O_PROLE;	// 进程对关联文件的角色:000、拥有者,001、root,010、root组管理员,011、组长,100、组管理员	,101、组成员,110、指定者,111、游客。
};

支持最大文件为16 Eb(64位),
64位文件磁盘地址空间的
“点地址” = db(16位).c(16位).ps(16位).(bdb + offset)(16位) = db.c.ps.bo。
式中:bo16位(bdb大数据块7位 + offset扇区内偏移9位),db数据块16位,c章(chapters)16位,ps16位(page页13位 + sector扇区3位)。
页内偏移offset:12位 = sector扇区3位 + offset扇区内偏移9位。

vma对象也可以是v节点文件打开表fot(file open table)的项(OACS文件vma对象file_vma(简化为file)、类同linux的struct file),一个具体的文件在打开后,内核会在内存中为之建立一个v节点对象;与linux不同,内核v节点、其f_sflags(描述了file文件对象状态标志),f_pos(描述了文件的偏移位置),等等、是在进程打开文件描述符对象file中,而并非在v节点打开文件表中;用户进程cao对象有file_head双向节点环表头项,可将其打开的所有打开文件描述符对象file钩挂在双向链表节点环上,最大可达到4G个、或说一个用户进程最大可打开4G个文件,取代了linux进程打开文件描述符表。进程open打开一个文件,返回当前可用的最小打开文件描述符对象号fd(u32)。v节点管理对象vmo的v_fcount项会记录通过该文件表项(v节点打开文件表的表项)打开文件的次数,当v_count计数归0时这个文件表项才会被删除,因此,对于指向同一文件表项的两个不同文件描述符对象file(如、同一进程中dup的两个文件描述符fd指向同一个文件表项),即使其中一个文件描述符fd关闭了,只要仍然有文件描述符指向这个文件表项,那么就依然能通过这个文件表项访问文件,直到所有指向该文件表项的文件描述符都关闭了才不能再进行访问。

用户进程读一个文件的某内容时,首先是据文件描述符fd找到文件vma对象file(文件打开表fot的项)做权限检查,通过后、再计算读取的文件内容的偏移量 f_pos、从而相应要读取的页;然后在对象file的流容器fvo中访问该文件的页缓存,如果页缓存命中,那么直接返回文件内容;如果页缓存缺失,那么产生一个页缺失异常、创建一个新缓存页,然后从磁盘中读取相应文件的页填充该缓存页;之后从页缺失异常中恢复,继续往下读。写文件时,首先通过所写内容在文件中的偏移量计算出相应的页,然后还是通过找到文件vma对象file、从而找到流容器fvo的页;如果页缓存命中,直接把文件内容修改更新在页缓存的页中,写文件就结束了。这时候文件修改处于流容器fvo的页缓存中,并没有写回writeback到磁盘文件中去。一个页缓存中的页如果被修改,那么会被标记成脏页。脏页需要写回到磁盘中的文件块。有两种方式可以把脏页写回磁盘,也就是flush。
1)、 手动调用sync()或者fsync()系统调用把脏页写回,
2)、pdflush进程会定时把脏页写回到磁盘。
如果脏页正在被写回,那么会被设置写回标记;这时候该页就被上锁,其他写请求被阻塞直到锁释放。系统调用与磁盘操作并不同步。

内核的fvo流容器对象file的“点地址”是物理页面地址,如设备等内核对象的操作无需经过页表映射、缺页、等等,从而高速;内核的fvo流容器对象file通常是连续物理页。用户进程的fvo流容器对象vma通常是非线性映射、是非连续的物理页组,但在虚拟内存空间是连续的页,最终是通过用户进程空间的“页表”非线性映射到物理内存;如果也是线性映射,只是起始页经过“页表”映射到物理页,速度就会有很大的提高。

注明:你也可以用C语言编写OACS操作系统的,这里提供了“思路”、将“cao等对象”看作c语言结构即可,这样,可用vscode编写、用gcc编译器。你就算是“c语言”高手,我也希望你多从“面向对象的汇编语言”角度去思考“编程方法”,而不要“满天飞的E文”和“linux与stm32之HAL库”之“臃肿庞大”模式,这样可让读者“省心”。操作系统本质上不外就是一个“大号单片机”程序吧,几十年了,人们还是在“windows、linux”上“兜风”;在“智能AI”领域上没进展,在AI领域、我等你们十六年了,现在还是那个“鸟水平”。没有“后悔药”吃,2006年后,我去玩“探索宇宙奥秘”、等等、没有多少实际意义的项目,呵呵、浪费青春、浪费表情。

4、从内核角度看,一切都是v节点对象(= vmo + xxx)。

vma对象和file对象、可看作vmo对象变体,内核所关心的、主要2种对象:v节点对象,vmo对象。
v节点对象的品种要多些:
a、对象分配器v节点对象2种:vao256 = 64B/16W = 8W/vmo + 8W/bitmap(256位图),
vao64K = 64B/16W(vao256) + 2页8KB的64k位图 = 8W/vmo + 8W/(64k位图页地址、对象空闲数、等等的属性说明)+ 2页8kB/64k位图。
b、磁盘文件v节点对象2种: 8W/vmo + 96B的i节点 = 128B,8W/vmo + 224B的i节点 = 256B。
c、应用程序可以是“大、中、小”型的磁盘文件,相应的进程也是对应于256B类型的磁盘文件v节点对象。
d、线程v节点对象:一个线程(内核或用户)的栈空间最大为一页4KB(还包含64B的cao线程对象在内),考虑到一些单片机的有限资源、线程对象及其栈(属于内核对象)的总大小也可以设为128B、256B、512B、1KB、2KB;是故,一个线程v节点对象就等于用户定义的栈空间、通常是页4KB。线程v节点对象页4KB = 64B/16W + 实际堆栈空间(4032B) = 8W/vmo + 8W/(线程属性说明)+ 实际堆栈空间(4032B = 1008W = 504DW)。
e、所有就绪线程的优先级(最大256优先级)管理rtpm_vao256(ready thread priority management vao256)的v节点对象:优先级255代表最高优先级,最低优先级0留给空闲线程使用;所有就绪线程都会根据其“线程属性说明字段中的优先级项”,来钩挂到相应的优先级队列(线程双向链表环);rtpm_vao256的v节点对象、使用vao256优先级线程对象分管器,每个优先级队列最大钩挂4G个就绪线程。调度器对象运行时,操作rtpm_vao256的v节点对象,当有比当前线程优先级更高的线程就绪时,当前线程将被换出,高优先级线程抢占cpu运行。相同优先级的线程间采用时间片的轮转调度算法进行调度,使每个线程运行相同时间;另外调度器在寻找那些处于就绪状态的具有最高优先级的线程时,所经历的时间是恒定的。
rtpm_vao256 = vao256 + 1页(256个双向链表环头节点与计数属性等、256*16B )。
f、进程线程间通信IPC(interprocess communication)的v节点对象(信号量、互斥量、事件、邮箱、消息、信号):通常就是一个vmo对象。
h、物理设备的v节点对象(定时器、串口通信类设备、并口通信类设备、等等):通常就是一个对应于128B类型的磁盘文件v节点对象。

应该还有一些其它类型的v节点对象(如睡眠、降功耗电源管理,等等),用到再说;所有v节点对象,都是按v节点类型、链表环模式布局;但对象都需要“空间容器”来存放的,DDR内存空间分配管理对象、i节点号和v节点号的分配管理对象、等等、如何设计?我们继续往前走,走不通时、再回过头做相应修改。

5、虚拟内存空间/vms管理:规定了物理内存最大4G页 = 16TB(虚拟内存的直接映射(4G页)256--287项),虚拟内存最大256TB。

PGD页表共512项、每项管理512GB,每1项512GB包含256个用户进程;最大64k个用户进程占用0--255项、用户进程虚拟地址空间128TB,每个进程有2GB独立私有线性虚拟内存空间pvma,包含进程虚拟地址静态或动态方法库区域、程序代码、等等(code段、data数据段、BSS段、堆brk(动态对象)),用户进程(应用程序)文件、兼容ELF 文件格式规范。

巨大的虚拟空间必须是分级管理,如何分级?为简化设计,虚拟内存空间的许多区域已经是固定分配区域;这样,可以大幅度减少代码量。

前面说了:在主CPU之SRAM区域cpu0_mem,建立256个vao256r根对象分配器对象(v节点  allocator root object,需占用256个*64B = 16KB = 4页);其中0号vao256r根对象分配器对象、看作为“森林根/”,管理1---255号的动态分配或释放,1---255号vao256r根对象分配器对象、看作为“树根”。我们是用空间区域(space zone)对应一“棵树”,所有的“树”都对应有vao256r根对象分配器对象,“树根”都在主CPU之SRAM区域cpu0_mem之0号vao256r根对象分配器对象上。
在此,vao256r称为“森林根/”总裁管理器,“树根”对应之vao256r[n](1--255,最大255个)根对象分配器对象、称为“树根”总管理器(简称总管)。一个总管最大有256条“环形支路”,每条“环形支路”对应一个分支总管理器对象、简称“分管”。对于内核虚拟内存空间/vms的总管,其0号分管就是一个vao64K进程对象分管、管理最大64k个每进程2GB独立私有线性虚拟内存空间pvma的64K*2GB = 128TB的虚拟内存空间;一个进程对应一个“主管”、这是第三级(0级总裁、1级总管、2级分管、3级主管、4级为vao256对象分配器),而一个进程主管管辖最大64K个线程的vao256分配器对象。是故,一个进程最大可在其2GB独立私有线性虚拟内存空间pvma中分配管理64k*256个vma对象,一个线程最大可以分配管理256个vma对象。

总裁(0级、系统只有一个)--->总管(1级、系统最大256个总管,每个总管可带最大256个分管)--->分管(2级,每个分管下可带最大256个或64K个的主管)--->主管(3级,每个主管下可带最大256个(vao256对象分配器)或64K个(vao64k对象分配器)的分配器对象)--->分配器(4级,每个分配器下可带最大256个或64K个的对象)。

初步规划:都是按需“动态伸缩”,必要的总管、主管、分管、分配器,都是在_start_init初始化时、做静态内存固定分配好。

/inode(i节点磁盘空间区域,树根节点)总管(1级,带最大256个分管、对应u16 i_fnna文件inode号所属区域之高8位)--->分管(2级,每个分管下可带最大256个的主管、对应u16 i_fnna文件inode号所属区域之低8位)--->主管(3级,每个主管下可带最大64K个(vao64k对象分配器)的分配器对象)--->分配器(4级,每个分配器下可带最大64K个的对象),256*256*(64K*64K)对应i节点号。大约是最大情形时,i节点占用磁盘空间:256T*256B - 4G*128B = 64PB - 512GB,目录和链接文件等为4G个i节点(128B)、其余i节点为256B。

/vnode总管(v节点内存空间区域,非磁盘文件,树根节点):v节点空间的情形也是类似,256(8号以上分管)*256(主管)*(64K*64K)对应v节点号;问题是没有那么大的虚拟内存空间,只是用8号以上分管(实际只用到8号分管):288--415项、内核虚拟内存区域64TB,内核v节点对象打开文件表(包含大部分的vmo对象、v节点对象),固定区域,进程共享,实际
256(8号分管)*256(主管)*(64K*64K)。

/vms(虚拟内存空间区域,树根节点)总管(1级,带最大256个分管),其中0号分管管理最大64k个每进程2GB独立私有线性虚拟内存空间pvma的64K*2GB = 128TB的虚拟内存空间。0号分管(2级,带最大64K个的主管、对应进程号)--->主管(3级,每个主管下可带最大64K个(vao64k对象分配器)的vao256分配器对象、对应线程号)--->分配器(4级,每个分配器(vao256对象分配器)下可带最大256个的vma对象),总共有64k(主管)*64k(vao256对象分配器)*256个vma对象。(/proc、存放动态变化的进程process文件,树根节点。)

1号分管:256--287项、内核虚拟内存空间16TB与物理内存的直接映射(4G页),固定区域;这实际上就是DDR物理内存的空间管理,后面论述。
2号分管:504--511项、内核映射、静态动态公共方法库区域共4TB,固定区域;OACS操作系统内核区域,只是64k*256个内核vma对象。
3号分管:496--503项、共享内核虚拟内存地址空间4TB(磁盘双缓冲页空间映射、最大0.5G个),固定区域,进程共享;共享内核虚拟内存双页缓冲区域,只是256(最大32个主管)*64k*256个双页缓冲区。
4号分管:480--495项/共享内核虚拟内存地址空间8TB(磁盘缓冲页空间、最大2G个页),固定区域,进程共享;共享内核虚拟内存单页缓冲区域,只是256(最大128个主管)*64k*256个单页缓冲区。
5号分管:448--479项、内核虚拟地址file对象区域16TB(进程打开文件描述符对象file、32B、最大512G个,平均每进程8M个),固定区域,进程共享;共享内核虚拟地址file对象区域,只是64k(最大32k个主管)*64k*256个file对象。
6号、7号分管备用,8号以上分管、用于内核v节点对象打开文件表。

线程v节点对象已经是固定分配,根据进程号线程号即可得到其相应的虚拟内存用户进程的线程栈页地址。416--447项、内核虚拟内存用户进程的线程栈vma对象4G*4KB = 16TB(线程cao对象64B包含在线程堆栈页内),固定区域。

总裁、总管、都是vao256对象分配器对象,而分管、主管或分配器、可以是vao64k(对象)分配器对象或vao256(对象)分配器对象。

5、DDR物理内存空间/ddr(非磁盘文件,树根节点)管理:规定了物理内存最大4G页 = 16TB(虚拟内存的直接映射(4G页)256--287项)。

/ddr总管(1级,带最大256个分管,只用9个分管):建立xxx内存池系列,从大块系列到小块系列按层次建立,用户可据实际物理内存来设计各层。
虚拟内存是按照连续(最大连续数4K个、16MB)小页(4KB),或者连续(最大连续数4K个、8GB)大页(2MB),来进行分配管理。一个用户进程的独立虚拟内存大小也只是2GB = 1K*2MB,以下是一种层设计例子:

0层(顶层):256k页(1GB)系列的vao256的0层分配器,16TB/1GB = 16K项,再除以256、故有最大64个vao256的0层分配器,每个分配器下可带最大256个的1GB系列对象。将最大16TB物理内存空间划分为64大块(对应64个vao256的0层分配器,每块256GB)。

1层:128K页(512MB)系列的vao256的1层分配器,最大16TB物理内存空间类推有最大128个vao256一层分配器,每个分配器下可带最大256个的512MB系列对象,从0层分配器可得到2个vao256一层分配器;1个用于本层,另一个用于下层。

以上2层使用0号分管,0号主管,0层:0号---63号的最大64个的vao256的0层分配器,1层:128号---255号的最大128个vao256的1层分配器。

2层:64K页(256MB)系列的vao256的2层分配器,最大16TB物理内存空间类推有最大256个vao256二层分配器,每个分配器下可带最大256个的256MB系列对象,从1层分配器可得到2个vao256二层分配器;1个用于本层,另一个用于下层。
0号分管,1号主管,最大256个vao256二层分配器。

3层:32K页(128MB)系列的vao256的3层分配器,最大16TB物理内存空间类推有最大512个vao256三层分配器,每个分配器下可带最大256个的128MB系列对象,从2层分配器可得到2个vao256三层分配器;1个用于本层,另一个用于下层。
0号分管,2号---3号主管,最大512个vao256三层分配器,每个主管带最大256个vao256分配器。

4层:16K页(64MB)系列的vao256的4层分配器,最大16TB物理内存空间类推有最大1k个vao256四层分配器,每个分配器下可带最大256个的64MB系列对象,从3层分配器可得到2个vao256四层分配器;1个用于本层,另一个用于下层。
0号分管,4号---7号主管,最大1k个vao256四层分配器,每个主管带最大256个vao256分配器。

5层:8K页(32MB)系列的vao256的5层分配器,最大16TB物理内存空间类推有最大2k个vao256五层分配器,每个分配器下可带最大256个的32MB系列对象,从4层分配器可得到2个vao256五层分配器;1个用于本层,另一个用于下层。
0号分管,8号---15号主管,最大2k个vao256五层分配器,每个主管带最大256个vao256分配器。

6层:4K页(16MB)系列的vao256的6层分配器,最大16TB物理内存空间类推有最大4k个vao256六层分配器,每个分配器下可带最大256个的16MB系列对象,从5层分配器可得到2个vao256六层分配器;1个用于本层,另一个用于下层。
0号分管,16号---31号主管,最大4k个vao256六层分配器,每个主管带最大256个vao256分配器。

7层:2K页(8MB)系列的vao256的7层分配器,最大16TB物理内存空间类推有最大8k个vao256七层分配器,每个分配器下可带最大256个的8MB系列对象,从6层分配器可得到2个vao256七层分配器;1个用于本层,另一个用于下层。
0号分管,32号---63号主管,最大8k个vao256七层分配器,每个主管带最大256个vao256分配器。

8层:1K页(4MB)系列的vao256的8层分配器,最大16TB物理内存空间类推有最大16k个vao256八层分配器,每个分配器下可带最大256个的4MB系列对象,从7层分配器可得到2个vao256八层分配器;1个用于本层,另一个用于下层。
0号分管,64号---127号主管,最大16k个vao256八层分配器,每主管最大256个vao256分配器。

9层:512页(2MB)系列的vao256的9层分配器,最大16TB物理内存空间类推有最大32k个vao256九层分配器,每个分配器下可带最大256个的2MB系列对象,从8层分配器可得到2个vao256九层分配器;1个用于本层,另一个用于下层。
0号分管,128号---255号主管,最大32k个vao256九层分配器,每主管最大256个vao256分配器。

10层:256页(1MB)系列的vao256的10层分配器,最大16TB物理内存空间类推有最大64k个vao256十层分配器,每个分配器下可带最大256个的1MB系列对象,从9层分配器可得到2个vao256十层分配器;1个用于本层,另一个用于下层。
0号分管,256号---511号主管,最大64k个vao256十层分配器,每主管最大256个vao256分配器。

11层:128页(512KB)系列的vao256的11层分配器,最大16TB物理内存空间类推有最大128k个vao256十一层分配器,每个分配器下可带最大256个的512KB系列对象,从10层分配器可得到2个vao256十一层分配器;1个用于本层,另一个用于下层。
0号分管,512号---1023号主管,最大128k个vao256十一层分配器,每个主管带最大256个vao256分配器。

12层:64页(256KB)系列的vao256的12层分配器,最大16TB物理内存空间类推有最大256k个vao256十二层分配器,每个分配器下可带最大256个的256KB系列对象,从11层分配器可得到2个vao256十二层分配器;1个用于本层,另一个用于下层。
0号分管,1024号---2047号主管,最大256k个vao256十二层分配器,每个主管带最大256个vao256分配器。

13层:32页(128KB)系列的vao256的13层分配器,最大16TB物理内存空间类推有最大512k个vao256十三层分配器,每个分配器下可带最大256个的128KB系列对象,从12层分配器可得到2个vao256十三层分配器;1个用于本层,另一个用于下层。
0号分管,2048号---4095号主管,最大512k个vao256十三层分配器,每个主管带最大256个vao256分配器。

14层:16页(64KB)系列的vao256的14层分配器,最大16TB物理内存空间类推有最大1M个vao256十四层分配器,每个分配器下可带最大256个的64KB系列对象,从13层分配器可得到2个vao256十四层分配器;1个用于本层,另一个用于下层。
0号分管,4096号---8191号主管,最大1M个vao256十四层分配器,每个主管带最大256个vao256分配器。

15层:8页(32KB)系列的vao256的15层分配器,最大16TB物理内存空间类推有最大2M个vao256十五层分配器,每个分配器下可带最大256个的32KB系列对象,从14层分配器可得到2个vao256十五层分配器;1个用于本层,另一个用于下层。
0号分管,8192号---16383号主管,最大2M个vao256十五层分配器,每个主管带最大256个vao256分配器。

16层:4页(16KB)系列的vao256的16层分配器,最大16TB物理内存空间类推有最大4M个vao256十六层分配器,每个分配器下可带最大256个的16KB系列对象,从15层分配器可得到2个vao256十六层分配器;1个用于本层,另一个用于下层。
0号分管,16384号---32767号主管,最大4M个vao256十六层分配器,每个主管带最大256个vao256分配器。

17层:2页(8KB)系列的vao256的17层分配器,最大16TB物理内存空间类推有最大8M个vao256十七层分配器,每个分配器下可带最大256个的8KB系列对象,从16层分配器可得到2个vao256十七层分配器;1个用于本层,另一个用于下层。
0号分管,32768号---65535号主管,最大8M个vao256十七层分配器,每个主管带最大256个vao256分配器。

0号分管总共管理18层(0---17),最大有64K个主管,每个主管下可带最大256个vao256分配器,每个分配器下可带最大256个的xxx系列对象。
0号分管(2级,带最大64K个的主管)--->主管(3级,每个主管下可带最大256个vao256分配器)--->vao256分配器(4级,每个分配器下可带最大256个的xxx系列对象),0号分管总共有最大:64k(主管)*256个vao256分配器*256个xxx系列对象。
初始化时,主管、分配器、需静态分配内存:
18层主管*64B(每层初始化1个主管的0号vao256分配器) =  18*64B。


18层:1页(4KB)系列的vao256的18层分配器,最大16TB物理内存空间类推有最大256个主管(vao64K对象分配器),每个vao64K对象分配器可带最大64K个vao256分配器,每个分配器下可带最大256个的4KB系列对象,从1层分配器可得到2个十八层vao64K对象分配器;1个用于本层,另一个用于下层。
1号分管,0号---255号主管、0号---65535号分配器,最大256个十八层vao64K对象分配器,每个主管带最大64K个vao256分配器。
1号分管(2级,带最大256个的主管)--->主管(3级,每个主管下可带最大64K个的vao256分配器)--->vao256分配器(4级,每个分配器下可带最大256个的1页(4KB)对象),1号分管总共有最大:256(主管)*64k个vao256分配器*256个1页(4KB)对象,管理最大4G页。

19层:2KB系列的vao256的19层分配器,最大16TB物理内存空间类推有最大512个主管(vao64K对象分配器),每个vao64K对象分配器可带最大64K个vao256分配器,每个分配器下可带最大256个的2KB系列对象,从2层分配器可得到2个十九层vao64K对象分配器;1个用于本层,另一个用于下层。
2号分管,0号---511号主管、0号---65535号分配器,最大512个十九层vao64K对象分配器,每个主管带最大64K个vao256分配器。
2号分管(2级,带最大512个的主管)--->主管(3级,每个主管下可带最大64K个的vao256分配器)--->vao256分配器(4级,每个分配器下可带最大256个的2KB对象),2号分管总共有最大:512(主管)*64k个vao256分配器*256个2KB对象,管理最大8G个的2KB对象。

20层:1KB系列的vao256的20层分配器,最大16TB物理内存空间类推有最大1k个主管(vao64K对象分配器),每个vao64K对象分配器可带最大64K个vao256分配器,每个分配器下可带最大256个的1KB系列对象,从3层分配器可得到2个20层vao64K对象分配器;1个用于本层,另一个用于下层。
3号分管,0号---1023号主管、0号---65535号分配器,最大1k个20层vao64K对象分配器,每个主管带最大64K个vao256分配器。
3号分管(2级,带最大1K个的主管)--->主管(3级,每个主管下可带最大64K个的vao256分配器)--->vao256分配器(4级,每个分配器下可带最大256个的1KB对象),3号分管总共有最大:1K(主管)*64k个vao256分配器*256个1KB对象,管理最大16G个的1KB对象。

21层:512B系列的vao256的21层分配器,最大16TB物理内存空间类推有最大2k个主管(vao64K对象分配器),每个vao64K对象分配器可带最大64K个vao256分配器,每个分配器下可带最大256个的512B系列对象,从4层分配器可得到2个21层vao64K对象分配器;1个用于本层,另一个用于下层。
4号分管,0号---2047号主管、0号---65535号分配器,最大2k个21层vao64K对象分配器,每个主管带最大64K个vao256分配器。
4号分管(2级,带最大2K个的主管)--->主管(3级,每个主管下可带最大64K个的vao256分配器)--->vao256分配器(4级,每个分配器下可带最大256个的512B对象),4号分管总共有最大:2K(主管)*64k个vao256分配器*256个512B对象,管理最大32G个的512B对象。

22层:256B系列的vao256的22层分配器,最大16TB物理内存空间类推有最大4k个主管(vao64K对象分配器),每个vao64K对象分配器可带最大64K个vao256分配器,每个分配器下可带最大256个的256B系列对象,从5层分配器可得到2个22层vao64K对象分配器;1个用于本层,另一个用于下层。
5号分管,0号---4095号主管、0号---65535号分配器,最大4k个22层vao64K对象分配器,每个主管带最大64K个vao256分配器。
5号分管(2级,带最大4K个的主管)--->主管(3级,每个主管下可带最大64K个的vao256分配器)--->vao256分配器(4级,每个分配器下可带最大256个的256B对象),5号分管总共有最大:4K(主管)*64k个vao256分配器*256个256B对象,管理最大64G个的256B对象。

23层:128B系列的vao256的23层分配器,最大16TB物理内存空间类推有最大8k个主管(vao64K对象分配器),每个vao64K对象分配器可带最大64K个vao256分配器,每个分配器下可带最大256个的128B系列对象,从6层分配器可得到2个23层vao64K对象分配器;1个用于本层,另一个用于下层。
6号分管,0号---8191号主管、0号---65535号分配器,最大8k个23层vao64K对象分配器,每个主管带最大64K个vao256分配器。
6号分管(2级,带最大8K个的主管)--->主管(3级,每个主管下可带最大64K个的vao256分配器)--->vao256分配器(4级,每个分配器下可带最大256个的128B对象),6号分管总共有最大:8K(主管)*64k个vao256分配器*256个128B对象,管理最大128G个的128B对象。

24层:64B系列的vao256的24层分配器,最大16TB物理内存空间类推有最大16k个主管(vao64K对象分配器),每个vao64K对象分配器可带最大64K个vao256分配器,每个分配器下可带最大256个的64B系列对象,从7层分配器可得到2个24层vao64K对象分配器;1个用于本层,另一个用于下层。
7号分管,0号---16383号主管、0号---65535号分配器,最大16k个24层vao64K对象分配器,每个主管带最大64K个vao256分配器。
7号分管(2级,带最大16K个的主管)--->主管(3级,每个主管下可带最大64K个的vao256分配器)--->vao256分配器(4级,每个分配器下可带最大256个的64B对象),7号分管总共有最大:16K(主管)*64k个vao256分配器*256个64B对象,管理最大256G个的64B对象。

25层:32B系列的vao256的25层分配器,最大16TB物理内存空间类推有最大32k个主管(vao64K对象分配器),每个vao64K对象分配器可带最大64K个vao256分配器,每个分配器下可带最大256个的32B系列对象,从8层分配器可得到2个25层vao64K对象分配器;1个用于本层,另一个用于下层。
8号分管,0号---32767号主管、0号---65535号分配器,最大32k个25层vao64K对象分配器,每个主管带最大64K个vao256分配器。
8号分管(2级,带最大32K个的主管)--->主管(3级,每个主管下可带最大64K个的vao256分配器)--->vao256分配器(4级,每个分配器下可带最大256个的32B对象),8号分管总共有最大:32K(主管)*64k个vao256分配器*256个32B对象,管理最大512G个的32B对象。

这8层初始化时,主管、分配器、需静态分配内存:
18层的0号主管vao256主管64B + 7层*0号主管(2页 + 64B) + 8层*0号主管的0号vao64k对象分配器(2页 + 64B)*0号主管的0号vao64k对象分配器的0号vao256分配器64B  = 8*64B + 56KB + 8*4KB + 4MB = 1046页 + 8*64B = 523*2页 +  8*64B。
 
分配一个v节点对象简化过程:分配v节点号--->分配一个vmo对象(25层32B系列对象):如果vao256的32B对象分配器有空闲位、则分配,没有、新建一个vao256的32B对象分配器(向17层双页系列对象申请)、分配,如果主管下的64K个的vao256分配器已满、则还需新建一个主管...。

或许进程分配一块内存、比如333MB,在虚拟内存是连续的、为虚拟内存空间vma对象 = 连续167大页(2MB)、最后一个大页有空隙;在物理内存分配时、是不连续的,256MB块(2层对象) + 64MB块(4层对象)+ 8MB块(7层对象)+ 4MB块(8层对象)+ 1MB块(10层对象);是故,进程线程分配的内存块、需要“层分配器号(地址)”单向链表环串接起来,还需要内存块的属性说明(块大小,实际使用大小,位置,等等);每个内存块需要包含16B的内存块头部,以方便系统释放内存块。

6、disk space area磁盘空间区域/dsa(非磁盘文件,树根节点)管理:

磁盘虚拟空间有16字节的地址表示,最小单位一个扇区s(扇区sector);最高字节表示为类型,次高6字节对应以太网MAC地址,为机器节点地址,
一个机器节点 = 256卷rl (roll)= 256*4G*4G*512b = 2 Yb 。
全局磁盘GDPT( Global Disk PartitionTable全局硬盘分区表 )用64位8字节整数来表示扇区号LBA(小端格式,扇区地址、逻辑块地址Logical Block Address),最低半字为扇区号
(1章 = 64K个扇区)、低半字为章号(1db数据块 = 64K章)、中半字为数据块号
(1bdb大数据块 = 64k db)、高半字为大数据块号(1卷rl (roll)= 64K bdb);一个局域本地机器组节点支持64k(卷)个全局磁盘GDPT阵列,1卷rl (roll)= 4G*4G*512b = 8 Zb,一个分区一个卷,每卷最大文件数256T个。当编写极大容量数据库文件时,对象的磁盘虚拟空间引用地址必须足够大,这是没办法的,将来的BOS、COS都需要大、大、大。

/dsa(磁盘空间区域,树根节点)总管(1级、一个vao256分管分配器,带最大256个分管、分管号对应8位卷号)--->分管(2级、一个vao64k主管分配器,每个分管(卷号)下可带最大64K个的主管、主管号对应大数据块号)--->主管(3级、一个vao64k组分配器,每个主管下可带最大64K个的组、组号对应数据块号)--->组(4级、一个vao64k班分配器,每个组可带最大64K个的班、班号对应章号)--->班(5级、一个vao64k的xxx系列对象分配器,每个分配器下可带最大64k个的xxx系列对象)。

1级总管(vao256分管分配器)带最大256个分管(8位卷号)--->2级分管(vao64k主管分配器)带最大64K个的主管(16位大数据块号)--->3级主管(vao64k组分配器)带最大64K个的组(16位数据块号)--->4级组(vao64k班分配器)带最大64K个的班(16位章号)--->5级班(vao64k的xxx系列对象分配器)带最大64K个的xxx系列对象(16位xxx系列“单粒”对象)。其实、班的基本对象是“扇区”,如果以“双扇区”为对象、班(1章)最大可带32K个“双扇区”;如果以“页”为对象、班(1章)最大可带8K个“页”,如果以“双页”为对象、班(1章)最大可带4K个“双页”;如果以“i节点的128B”为对象、班(1章)最大可带256K个“i节点的128B”对象,如果以“i节点的256B”为对象、班(1章)最大可带128K个“i节点的256B”对象。因为xxx系列对象的“不专一”,我们并不一定是用“班号对应章号、一个班对应64K个扇区”,而是一个班对应64K个xxx系列对象。

如果用层模式、则与DDR物理内存相类似,但支持连续页、或连续章、或连续数据块、或连续大数据块、或单粒分配管理模式。
我们换另一种玩法:左青龙粒、右白虎块(连续粒)。在一个64K个的xxx中,左起按一粒粒(对应位图一位一位)分配模式,右起是按照连续粒(对应位图的连续位)分配模式。这样一来,可以不分层数;xxx系列对象有单粒:i节点的128B、256B,哈希映射表FNHT的vao256双扇区、vao256双页;还有模式:单扇区或连续扇区,单页或连续页,单章、连续章,单数据块、连续数据块,单大数据块,连续大数据块。反推:我们可以用这种玩法改造前述的物理内存分配管理,为让读者清楚整个改造过程、不会删除前面的内容。

5级班(vao64k的xxx系列“单粒”对象)分配器:

0号分管、0号主管、0号组,组2TB作为i节点的128B或256B对象分配管理:
i节点的128B(最大有4G个),一个扇区有4个128B系列“单粒”对象,最大需要16K章 = 512GB。
0组的0---16383的16K个章号作为i节点的128B“单粒”对象分配管理,而16384---65536的48K个章号作为i节点的256B“单粒”对象分配管理,只有6G个的256B系列“单粒”对象,不够用时、从其它非指定组动态分配。

0号分管、0号主管、1号组,组2TB作为“扇区”对象分配管理:
64K个的班(vao64k的扇区系列对象分配器、带最大64K个的扇区系列对象)。
组1db( data block 数据块)  = 64Kc章 = 4Gs(扇区sector),支持4G个单扇区或连续扇区分配管理,不够用时、从其它非指定组动态分配。

0号分管、0号主管、2号组,组2TB作为“双扇区”对象分配管理:
32K个的班(vao64k的双扇区系列对象分配器、带最大64K个的双扇区系列对象)。
组1db( data block 数据块)  = 64Kc章 = 4Gs(扇区sector),支持2G个双扇区或连续双扇区分配管理,不够用时、从其它非指定组动态分配。

0号分管、0号主管,3号组,组2TB作为“页”对象分配管理:
8K个的班(vao64k的页系列对象分配器、带最大64K个的页系列对象)。
组1db( data block 数据块)  = 64Kc章 = 512MP(页page),支持512MP个单页或连续页分配管理,不够用时、从其它非指定组动态分配。

0号分管、0号主管,4号组,组2TB作为“双页”对象分配管理:
4K个的班(vao64k的双页系列对象分配器、带最大64K个的页系列对象)。
组1db( data block 数据块)  = 64Kc章 = 512MP(页page),支持256MP个双页或连续双页分配管理,不够用时、从其它非指定组动态分配。

0号分管、0号主管,5号组及以上是非指定组,系统内核按需分配管理。有了“连续xxx系列对象”的分配管理,不用再按照“多层”分配模式;文件内容的“单向链表环”个数也是大幅减少,但通常文件内容每个“数据段”还是需要有一个16B的“数据段头部”:8B的“分配器号(地址)”以便单向链表环串接起各个“数据段”,8B的“数据段”属性说明(块大小,实际使用大小,位置,等等);除非有另外方式的“表述”,如哈希映射表FNHT文件。

1c(章chapters)= 64Ks(扇区sector) = 1Mr(行row)= 8Mw(字word)= 16Mz(半字z)
= 32Mb(字节byte)= 256Mbit(位bit)。
1db( data block 数据块)  = 64Kc章 = 4Gs(扇区sector) = 512Gw(字word)= 1Tz(半字z)
= 2Tb(字节byte)= 16Tbit(位bit)。
1bdb(big data block 大数据块) = 64K db( data block 数据块)  = 4Gc章 = 256Ts(扇区sector) = 32Pw(字word)= 128Pb(字节byte)。
1卷rl (roll)= 64K bdb = 4G db = 256Tc = 16Es(扇区sector) = 2Zw(字word)
= 8Zb(字节byte)。
磁盘空间分配有:
连续大数据块、连续数据块、连续章、连续页(1页page为8个扇区4Kb)、等等。
1 Kb ( Kilobyte 千字节 ) =1024b,1024 = 2^10 ( 2的10次方);
1 Mb ( Megabyte 兆字节、简称“兆”) = 1024 Kb,
1Gb ( Gigabyte 吉字节、又称“千兆”) = 1024 Mb,
1 Tb ( Trillionbyte 万亿字节、太字节 ) = 1024 Gb,
1 Pb(Petabyte 千万亿字节、拍字节)= 1024 Tb,
1Eb(Exabyte 百亿亿字节、艾字节)= 1024 Pb;
1 Zb ( Zettabyte 十万亿亿字节、 泽字节 ) = 1024 Eb,
1 Yb (Yottabyte 一亿亿亿字节、 尧字节 ) = 1024 Zb,
1 Bb ( Brontobyte 一千亿亿亿字节 ) = 1024 Yb。   

DDR物理内存新式分配管理:兼容了虚拟内存的连续页分配模式,统一物理内存空间、虚拟内存空间、磁盘空间、的空间分配管理。

/ddr总管(物理内存空间区域,树根节点,1级、一个vao256分管分配器,带最大256个分管、实际只用8个分管0---7,每个分管2TB、对应数据块号)--->分管(2级、一个vao64k主管分配器,每个分管下可带最大64K个的主管32MB、主管号对应章号)--->主管(3级、一个vao256组分配器,每个主管下可带最大256个的组128KB(32页))--->组(4级、一个vao256班分配器,每个组可带最大256个的班512B(1个扇区))--->班(5级、一个vao256的xxx系列对象分配器,每个分配器下可带最大256个的xxx系列对象)。因为xxx系列对象的“不专一”,我们并不一定是用“班对应1个扇区”,而是一个班对应256个xxx系列对象。

5级班(vao256的xxx系列“单粒”对象)分配器:

0号分管、0号主管、0号组,组128KB(32页)作为32B(vmo)对象分配管理:
vmo对象的32B(对应25层分配器,最大512G个的32B对象),一个班有256个32B对象、
8KB = 2页,一组有16个班。
0组的0---15的班号作为“单粒”32B(vmo)对象初始分配管理,总共有16*256 = 4K个32B对象。
不够用时、从其它非指定组动态分配,一次申请分配一组16个班。

0号分管、0号主管、1号组,组128KB(32页)作为64B对象分配管理:
64B系列“单粒”对象(对应24层分配器,最大256G个的64B对象),一个班有256个64B对象、16KB = 4页,一组有8个班。
1组的0---7的班号作为“单粒”64B对象初始分配管理,总共有8*256 = 2K个64B对象。
不够用时、从其它非指定组动态分配,一次申请分配一组8个班。

0号分管、0号主管、2号组,组128KB(32页)作为128B对象分配管理:
128B系列“单粒”对象(对应23层分配器,最大128G个的128B对象),一个班有256个128B对象、32KB = 8页,一组有4个班。
1组的0---3的班号作为“单粒”128B对象初始分配管理,总共有4*256 = 1K个128B对象。
不够用时、从其它非指定组动态分配,一次申请分配一组4个班。

0号分管、0号主管、3号组,组128KB(32页)作为256B对象分配管理:
256B系列“单粒”对象(对应22层分配器,最大64G个的256B对象),一个班有256个256B对象、64KB = 16页,一组有2个班。
1组的0---1的班号作为“单粒”256B对象初始分配管理,总共有2*256 = 512个256B对象。
不够用时、从其它非指定组动态分配,一次申请分配一组2个班。

0号分管、0号主管、4号组,组128KB(32页)作为512B扇区对象分配管理:
512B系列“单粒”对象(对应21层分配器,最大32G个的512B对象),一个班有256个512B对象、128KB = 32页,一组有1个班。
1组的班号作为“单粒”512B对象初始分配管理,总共有1*256 = 256个512B对象。
不够用时、从其它非指定组动态分配,一次申请分配一组1个班。

0号分管、0号主管,5号组及以上是非指定组,系统内核按需分配管理。有了“连续x主管或连续x组或连续虚拟内存页”的分配管理,不用再按照“多层”分配模式;内存块的“单向链表环”个数也是大幅减少,但通常内存块还是需要有一个16B的“内存块头部”:8B“分配器号(地址)”以便单向链表环串接起各个“内存块”,8B的“内存块”属性说明(块大小,实际使用大小,位置,等等)。
虚拟内存是按照连续(最大连续数4K个、16MB,等效连续128组动态分配为1个班)小页(4KB),或者连续(最大连续数4K个、8GB,等效连续256主管动态分配为1个班)大页(2MB),来进行分配管理。一个用户进程的独立虚拟内存大小也只是2GB = 1K*2MB,连续物理内存是按照连续x主管或连续x组分配管理。

1KB系列“单粒”对象(对应20层分配器,最大16G个的1KB对象),一个班有256个1KB对象、256KB = 64页,连续2组动态分配为1个班。
2KB系列“单粒”对象(对应19层分配器,最大8G个的2KB对象),一个班有256个2KB对象、512KB =128页,连续4组动态分配为1个班。
4KB(页)系列“单粒”对象(对应18层分配器,最大4G个的4KB对象),一个班有256个4KB对象、1MB = 256页,连续8组动态分配为1个班。
8KB(双页)系列“单粒”对象(对应17层分配器,最大2G个的8KB对象),一个班有256个8KB对象、2MB = 512页,连续16组动态分配为1个班。
16KB系列“单粒”对象(对应16层分配器,最大1G个的16KB对象),一个班有256个16KB对象、4MB = 1K页,连续32组动态分配为1个班。
32KB系列“单粒”对象(对应15层分配器,最大512M个的32KB对象),一个班有256个32KB对象、8MB =2K页,连续64组动态分配为1个班。
64KB系列“单粒”对象(对应14层分配器,最大256M个的64KB对象),一个班有256个64KB对象、16MB = 4K页,连续128组动态分配为1个班。
128KB系列“单粒”对象(对应13层分配器,最大128M个的128KB对象),一个班有256个128KB对象、32MB = 8K页,1个主管动态分配为1个班。
256KB系列“单粒”对象(对应12层分配器,最大64M个的256KB对象),一个班有256个256KB对象、64MB = 16K页,连续2主管动态分配为1个班。
512KB系列“单粒”对象(对应11层分配器,最大32M个的512KB对象),1班有256个512KB对象、128MB = 32K页,连续4主管动态分配为1个班。
1MB系列“单粒”对象(对应10层分配器,最大16M个的1MB对象),一个班有256个1MB对象、256MB = 64K页,连续8主管动态分配为1个班。
2MB系列“单粒”对象(对应9层分配器,最大8M个的2MB对象),一个班有256个2MB对象、512MB = 128K页,连续16主管动态分配为1个班。
4MB系列“单粒”对象(对应8层分配器,最大4M个的4MB对象),一个班有256个4MB对象、
1GB = 256K页,连续32主管动态分配为1个班。
8MB系列“单粒”对象(对应7层分配器,最大2M个的8MB对象),一个班有256个8MB对象、
2GB = 512K页,连续64主管动态分配为1个班。
16MB系列“单粒”对象(对应6层分配器,最大1M个的16MB对象),一个班有256个16MB对象、4GB = 1M页,连续128主管动态分配为1个班。
32MB系列“单粒”对象(对应5层分配器,最大512K个的32MB对象),一个班有256个32MB对象、8GB = 2M页,连续256主管动态分配为1个班。
64MB系列“单粒”对象(对应4层分配器,最大256K个的64MB对象),一个班有256个64MB对象、16GB = 4M页,连续512主管动态分配为1个班。
128MB系列“单粒”对象(对应3层分配器,最大128K个的128MB对象),1班有256个128MB对象、32GB = 8M页,连续1k主管动态分配为1个班。
256MB系列“单粒”对象(对应2层分配器,最大64K个的256MB对象),1班有256个256MB对象、64GB = 16M页,连续2k主管动态分配为1个班。
512MB系列“单粒”对象(对应1层分配器,最大32K个的512MB对象),1班有256个512MB对象、128GB = 32M页,连续4k主管动态分配为1个班。
1GB系列“单粒”对象(对应0层分配器,最大16K个的1GB对象),1班有256个1GB对象、
256GB = 64M页,连续8k主管动态分配为1个班。

前面例子:内存块333MB = 320MB内存块(连续10个主管32MB)+ 13MB内存块(某一主管下连续104个组128KB)。
进程线程分配的内存块、需要“层分配器号(地址)”单向链表环串接起来,还需要内存块的属性说明(块大小,实际使用大小,位置,等等);每个内存块需要包含16B的内存块头部,以方便系统释放内存块。

简单地:不管是vao256对象分配器、或者vao64k对象分配器,其前半部分位图用于“左青龙单粒(位)”分配管理、右半部分位图用于“右白虎块(连续位)”分配管理。分配器大小总是64B,vao256的位图被包含在64B内,vao64k的位图需要另外的双页空间。也可以指定vao64k对象分配器只作为“单粒”对象分配器或“连续粒”对象分配器,有时会有大于连续32K位的情形。

如果想再次简化,那么vao256对象分配器只是“单粒”对象分配器,vao64k对象分配器才具有“连续粒”对象分配管理功能;一个2TB分管带最大64K个主管32MB,一个32MB主管带最大64K个扇区(组),班是“vao256的xxx系列“单粒”对象分配器”的别名;这样,只是vao64k对象分配器才具有“连续主管或连续组(扇区)”功能。

/ddr总管(物理内存空间区域,树根节点,1级、一个vao256分管分配器,带最大256个分管、实际只用8个分管0---7,每个分管2TB、对应数据块号)--->分管(2级、一个vao64k主管分配器,每个分管下可带最大64K个的主管32MB、主管号对应章号)--->主管(3级、一个vao64k组分配器,每个主管下可带最大64K个的组512B(扇区))--->组(4级,每个组对应1个扇区)--->班(5级、一个vao256的xxx系列对象分配器,每个分配器下可带最大256个的xxx系列对象)。因为xxx系列对象的“不专一”,我们并不一定是用“班对应1个扇区”,而是一个班对应256个xxx系列对象。

5级班(vao256的xxx系列“单粒”对象)分配器:0号主管、作为连续扇区vao64k对象分配器。

0号分管、0号主管、0号---15号扇区(组),2页作为32B(vmo)对象分配管理:
vmo对象32B(对应25层分配器,最大512G个的32B对象),1班有256个32B对象、8KB = 2页。
不够用时、从其它非指定扇区动态分配,一次申请分配连续16个扇区为1班。

0号分管、0号主管、16号---47号扇区(组),4页作为64B对象分配管理:
64B系列“单粒”对象(对应24层分配器,最大256G个的64B对象),1班有256个64B对象、4页。
不够用时、从其它非指定组动态分配,一次申请分配连续32个扇区为1班。

0号分管、0号主管、48号---111号扇区(组),8页作为128B对象分配管理:
128B系列“单粒”对象(对应23层分配器,最大128G个128B对象),1班有256个128B对象、8页。
不够用时、从其它非指定组动态分配,一次申请分配连续64个扇区为1班。

0号分管、0号主管、112号---239号扇区(组),16页作为256B对象分配管理:
256B系列“单粒”对象(对应22层分配器,最大64G个256B对象),1班有256个256B对象、16页。
不够用时、从其它非指定组动态分配,一次申请分配连续128个扇区为1班。

依次类推...
以下开始空间管理正式规范,改动大,前面的只作参考!

其实,虚拟内存的大页、可看作为32MB(主管),小页看作为DP(双页8KB(double page)、组);这样,连续x主管或连续x组就可与连续“虚拟内存页”相对应了。若主管的下属“粒度”看作为DP,则一个主管只有4K个DP、只需12位表述;这时,一个组表述为一个DP、而非一个扇区。最常用的系列“单粒”对象有:vmo(32B)、分配器(64B)、磁盘文件v节点(128B、或256B),当分配xxx系列对象时,若相应的班都没有“位置”、需新建一个班;这时,需寻找一个“有空闲位置的主管”来新建一个“班”、之后分配。vmo(32B)班对应一个DP、分配器(64B)班对应连续2个DP、128B班对应连续4个DP、256B班对应连续8个DP、512B班对应连续16个DP、1KB班对应连续32个DP、2KB班对应连续64个DP、4KB(页)班对应连续128个DP,再往上、就是按照连续组(DP)或连续主管来分配管理,而非“班粒”处理。

0号分管、0号主管、通常作为ddr_init的“单粒”对象静态基本内存分配,0号主管32MB分为2部分各16MB,后部16MB为2K个DP用于2K个vao64k分配器的64K位之位图管理等;前部16MB划分为8份,每份2MB = 256DP,静态固定分配应用于:
vmo(32B)有256个班(1DP),或说初始化分配了256 * 256 = 64K个vmo对象的内存池;
分配器(64B)有128个班(连续2DP)、32K个64B对象内存池,0班为256个vao256总管分配器对象,1班---4班为1K多个vao64k2分管分配器或vao64k分配器,5班---28班是对应x号主管之静态vao4k分配器、占有768DP、共24个班6k个vao4k分配器,28班---127班为99*256个vao256分配器或说24.75K个64B对象的内存池,总共25K个vao256分配器或说25K个64B对象内存池;
128B有64个班(连续4DP),16K个128B对象的内存池;
256B有32个班(连续8DP),8K个256B对象的内存池;
512B有16个班(连续16DP),4K个512B对象的内存池;
1KB有8个班(连续32DP),2K个1KB对象的内存池;
2KB有4个班(连续64DP),1K个2KB对象的内存池;
4KB(页)有2个班(连续128DP),512个4KB对象的内存池。
不够用时、从其它非指定组动态分配,一次申请分配连续xxxDP相应的一个班。

主管下属有最大4K个DP(组),通常是分为13种类型环形队列主管:1DP(单粒)、连续2DP、连续3DP---4DP、连续5DP---8DP、连续9DP---16DP、连续17DP---32DP、连续33DP---64DP、连续65DP---128DP、连续129DP---256DP、连续257DP---512DP、连续513DP---1KDP、连续1025DP---2KDP、连续2049DP---4KDP。

一个分管下属有最大64K个主管,划分为16段、每段4K个主管;同理,有13种类型的环形队列段:单粒主管、连续2主管、连续3---4主管、连续5---8主管、连续9---16主管、连续17---32主管、连续33---64主管、连续65---128主管、连续129---256主管、连续257---512主管、连续513---1K主管、连续1025---2K主管、连续2049---4K主管。

这种分配管理模式是会存在“空隙”的,比如32DP主管、用户只是申请分配一个连续17DP,就会产生15DP的“空隙”;“空隙”是可用于分配为其它应用,如果连续3DP“满”(没能找到更多的3DP主管“空间”),这时、会寻找这些“高阶空隙”来分配;这将产生一个略为复杂的分配管理代码,或许需要“移动内存”。

广而推之:一个分管下属有最大64K个主管,划分为16段、每段4K个主管;一个主管下属有最大64K个扇区或数据块db,划分为4K组、每组为DP(16扇区双页8KB)或者为磁盘空间的连续16数据块db(16*2TB)组。连续主管或连续组等等的分配管理通常是分为13种类型环形队列:1、2、4、8、16、32、64、128、256、512、1K、2K、4K。磁盘空间的一个班(8GB)对应4K个大页* 4k个扇区对象,内存空间一个班对应256个xxx系列对象。磁盘空间有连续主管(128PB)或连续数据块组(32TB)或连续班(8GB)或连续大页(2MB)的分配管理,内存空间只是连续主管(32MB)连续DP组(8KB)的分配管理。这样做法,只是想统一磁盘空间、虚拟内存空间、DDR空间的分配管理,尽量减少代码。分管号8位,主管号16位(高4位段号、低12位主管号),数据块组号12位(内存只是到DP组号12位)、班号12位、大页号12位、扇区号12位;空间分配管理通常是2种模式连续或“单粒”:连续xxx对象 + 单粒xxx对象,空间的分配器环形队列单粒对象。

0号分管的0号主管已经是静态固定分配,v节点对象 = vmo对象 + xxx;0号主管已经是包含了256个班(256*256 = 64K个)的vmo对象,不够用时,从0号分管的1号主管(1DP主管)动态分配;1DP主管(32MB)最大可有4K个vmo班,2DP主管(32MB)最大可有2K个的vao(分配器)班,4DP主管(32MB)最大可有1K个的v128(磁盘文件128B的v节点对象)班,...,4KDP主管(32MB)最大只是1个4KDP班。我们必须先建立好分配器对象队列,才能更好地分割和管理DDR物理内存。

不管“下属内容”多么多么地复杂,我们最终只是希望编写通用的2种空间管理方法(分配与释放)而已;OACS操作系统而言,不外是分配与释放一个“空间对象”或者v节点对象。不会是新建或删除一个线程、或进程、或IPC对象、或物理设备、或磁盘文件、等等,需要另外编写相应一套方法,而是全都统一到通用空间管理方法“分配与释放”。“分配”方法的结果会返回一个相应v节点号、或者内存块或磁盘空间初始地址,返回0则自然是“失败”,其第一个参数自然是类型“u16 type”,u16指示:磁盘空间、物理内存空间、虚拟内存空间、等,连续分配或“单粒”分配,12位连续分配的数量或“单粒”分配时的v节点类型等等,第二个参数通常是u64的实际空间长度,...。

7、空间的分配器环形队列
最近在看一部小说、有3千多章,其它事情也多一些;只是有上午1个多小时的工作量,总体进度会慢下来,不急的、慢慢玩。
“精神世界”学科和现实物理世界学科是有区别的,有其特有的概念和体系:空间锚位(抛锚位置),想象力,意念力,瞬移(超光速),通透,0质量,意境(意念--成--实物场景(虚转实),或说想象的场景),灵魂,灵体,联想、学习、思维、推理,数据库,方法,对象,属性,类,基因、遗传,太极、阴阳两仪、三才、四象、五行、六合、七音、八卦、九宫,中医,道德经,等等。从阴阳角度看:任何事物都有正反两面、或说阴阳两面,精神世界和物理世界可看作为一阴一阳,不存在先有阴、或先有阳的说法;阴极生阳、阳极生阴,无限阴阳循环圆。

内存空间v节点对象的分配器环形队列:0号分管、0号主管(32MB)、分配器(64B)0号班(连续2DP)(256个64B的vao256分配器对象)。
0号班之0号64B分配器对象:vao256r“森林根/”总裁管理器(0级、系统只有一个),“树根”对应之vao256r[n](1--255,最大255个)根对象分配器对象、称为“树根”总管理器(简称总管)。0号班之1号---255号64B分配器对象,对应最大255个总管,实际数量取决于系统软硬件;1号通常是设置为、/ddr总管(物理内存空间区域,树根节点,1级、一个vao256总管分配器,带最大256个分管、实际只用8个分管0---7,每个分管2TB、对应数据块号),2号为、/vms(虚拟内存空间区域,树根节点)总管(1级,带最大256个分管),其中0号分管管理最大64k个每进程2GB独立私有线性虚拟内存空间pvma的64K*2GB = 128TB的虚拟内存空间;3号为、/dsa(磁盘空间区域,树根节点)总管(1级、一个vao256总管分配器,带最大256个分管、分管号对应8位磁盘空间卷号),其它...,终是一个“填表规划”过程;0号主管(32MB)有128个班(连续2DP)的分配器(64B)对象,总共32K个64B对象、作为静态规划分配安排;依次规划各个空间的分配器环形队列之“节点头部、或说根部”,1班以上通常作为物理内存空间区域的v节点对象的分配器环形队列、规划,总是会存在一些“鸡生蛋、蛋生鸡”疑惑的“自举”。

/vms虚拟内存空间区域总管的分管已经作为虚拟分管被包含到1号/ddr总管中,2号总管分配器就留空备用了。0号分管、0号主管(32MB)、分配器(64B)0号班之0号64B分配器对象vao256r总裁管理器(0级、系统只有一个),管理255个vao256r[n](1--255,最大255个)总管分配器;1号、为/ddr总管(物理内存空间区域,树根节点,1级、一个vao256总管分配器,带最大256个分管、DDR实际只用8个分管0---7,每个分管2TB、对应数据块号,/vms虚拟内存空间区域的虚拟分管,1班配置),2号总管备用,3号/dsa(磁盘空间区域,树根节点)总管(1级、一个vao256总管分配器,带最大256个分管、分管号对应8位磁盘空间卷号,2班配置),4号---255号作为其它CPU核的总管分配器(带最大256个分管)。

一个主管32MB最大可有16*128个班(连续2DP)分配器(64B),或说2K*256 = 512K个64B对象内存池,但0号分管、0号主管(32MB)只有128个分配器班、或说32K个64B对象内存池;其中0班作为256个vao256总管分配器(带最大256个分管),1班作为1号/ddr总管分配器之下辖分管分配器,钩挂到0班之1号总管分配器上、再钩挂到0班0号vao256r总裁管理器上;3班作为3号/dsa总管分配器之下辖分管分配器,钩挂到0班之3号总管分配器上、再钩挂到0班0号vao256r总裁管理器上。

(虚拟)分管分配器有2种:vao64k2分管分配器(管理16段最大连续4K主管或最大64K单粒主管)和vao64k分管分配器(管理最大64K单粒主管),前者主要应用于连续主管分配管理,后者应用于空间的分配器环形队列单粒主管分配管理,(虚拟)分管分配器都钩挂到0班之1号或3号总管分配器上、再钩挂到0班0号vao256r总裁管理器上。1班之0号---7号64B(+2DP)为DDR物理内存8个vao64k2分管分配器(每个分管2TB、对应内存数据块号,划分为16段、每段4K个主管、最大64K个的主管32MB,主管号对应章号),1班之8号---15号64B(+2DP)为8个物理映射虚拟内存空间vao64k2分管分配器(256--287项、内核虚拟内存空间16TB与物理内存的直接映射(4G页),固定区域;每个分管2TB、对应内存数据块号,划分为16段、每段4K个主管、最大64K个的主管32MB,主管号对应章号),2班的256个64B(+2DP)为磁盘空间区域的256个vao64k2分管分配器对象(磁盘空间卷号虚拟分管)。一个(虚拟)内存主管32MB下属有最大64K个扇区512B,划分为4K组、每组为DP(16扇区双页8KB),一个磁盘空间主管(对应大数据块128PB)下属有最大64K个数据块2TB,划分为4K数据块组、每组为连续16数据块32TB;一个数据块组32TB,划分为4K个班8GB,一个班8GB、划分为4K个大页2MB;一个大页2MB,划分为4K个扇区512B。vao64k2分管分配器的下辖主管是vao4k(64B+2DS)主管分配器,vao64k分管分配器的下辖主管是vao64k(64B+DP)主管分配器;vao4k(64B+2DS)主管分配器下辖vao4k(64B+2DS)组分配器(磁盘空间还有数据块组分配器下辖vao4k(64B+2DS)班分配器,班分配器下辖vao4k(64B+2DS)大页分配器,大页分配器下辖最大4K个扇区),而vao64k(64B+DP)主管分配器下辖vao64k(64B+DP)班分配器、班下辖最大256个xxx系列对象、一个分管下最大64K*64K*256 = 1T个xxx系列对象。(虚拟)内存虚拟vao64k分管下的班分配管理还是需要在(虚拟)内存vao64k2分管分配器下获取、或说做相应钩挂。

静态分配之vao64k对象分配器,约有1K多个、全部放在1班---4班。
1班之0号---7号64B(+2DP)的vao64k2分配器对象,对应8个物理内存空间分管,钩挂到/ddr物理内存总管上;每个分管2TB、对应内存数据块号(2级、一个vao64k2分管分配器,每个分管下可带最大64K个的主管32MB、主管号对应章号),0号---7号分管之16段0号vao4k(64B+2DS)主管(32MB)是静态分配、5班8分管16段0号主管之0号---127号vao4k,每段1号---4095号主管则是动态分配;一个分管下属有最大64K个主管,划分为16段、每段4K个主管。一个内存主管下属有最大64K个扇区,划分为4K组、每组为DP(16扇区双页8KB)。

1班之8号---15号64B(+2DP)的vao64k2分配器对象,对应8个物理映射虚拟内存空间分管,或说虚拟内存空间1号分管:256--287项、内核虚拟内存空间16TB与物理内存的直接映射(4G页),固定区域;每个分管2TB、对应虚拟内存数据块号(2级、一个vao64k2主管分配器,每个分管下可带最大64K个的主管32MB、主管号对应章号),8号---15号分管之16段0号vao4k(64B+2DS)主管(32MB)是静态分配、5班8分管16段0号主管之128号---255号vao4k,每段1号---4095号主管则是动态分配;一个分管下属有最大64K个主管,划分为16段、每段4K个主管。一个虚拟内存主管下属有最大64K个扇区,划分为4K组、每组为DP(16扇区双页8KB)。

1班之16号64B(+1DP)的vao64k分配器,对应v节点对象的vmo对象环形队列虚拟分管(内存单粒分配模式);vmo虚拟分管下辖有64K个vmo主管,一个vmo主管下属有64K个班(1DP、16扇区双页8KB);vmo对象环形队列最大可有64K*64K*256 = 1T个vmo对象,0号vmo主管的
0号---255号的256个班已经是静态分配。vmo虚拟分管下0号vao64k的vmo主管分配器也静态分配、对应1班之17号64B(+1DP)。

1班之18号64B(+1DP)的vao64k分配器,对应64B对象分配器的v节点对象环形队列虚拟分管(内存单粒分配模式);分配器虚拟分管下辖有64K个分配器主管,一个分配器主管下属有64K个班(连续2DP、32扇区4页16KB);分配器v节点对象环形队列最大可有64K*64K*256 = 1T个分配器v节点对象,0号分配器主管的0号---127号的128个班已经是静态分配。64B虚拟分管下0号vao64k的64B主管分配器也静态分配、对应1班之19号64B(+1DP)。

1班之20号64B(+1DP)的vao64k分配器,对应128B磁盘文件v节点对象环形队列虚拟分管(内存单粒分配模式);128B虚拟分管下辖有64K个128B主管,一个128B主管下属有64K个班(连续4DP、64扇区8页32KB);128B的v节点对象环形队列最大可有64K*64K*256 = 1T个128B的v节点对象,0号128B主管的0号---63号的64个班已经是静态分配。128B虚拟分管下0号vao64k的128B主管分配器也静态分配、对应1班之21号64B(+1DP)。

1班之22号64B(+1DP)的vao64k分配器,对应256B磁盘文件v节点对象环形队列虚拟分管(内存单粒分配模式);256B虚拟分管下辖有64K个256B主管,一个256B主管下属有64K个班(连续8DP、128扇区16页64KB);256B的v节点对象环形队列最大可有64K*64K*256 = 1T个256B的v节点对象,0号256B主管的0号---31号的32个班已经是静态分配。256B虚拟分管下0号vao64k的256B主管分配器也静态分配、对应1班之23号64B(+1DP)。

1班之24号64B(+1DP)的vao64k分配器,对应512B内存对象环形队列虚拟分管(内存单粒分配模式);512B虚拟分管下辖有64K个512B主管,一个512B主管下属有64K个班(连续16DP、256扇区32页128KB);512B内存对象环形队列最大可有64K*64K*256 = 1T个512B的内存对象,0号512B主管的0号---15号的16个班已经是静态分配。512B虚拟分管下0号vao64k的512B主管分配器也静态分配、对应1班之25号64B(+1DP)。

1班之26号64B(+1DP)的vao64k分配器对象,对应1KB内存对象环形队列虚拟分管(内存单粒分配模式);1KB虚拟分管下辖有64K个1KB主管,一个1KB主管下属有64K个班(连续32DP、512扇区64页256KB);1KB内存对象环形队列最大可有64K*64K*256 = 1T个1KB的内存对象,0号1KB主管的0号---7号的8个班已经是静态分配。1KB虚拟分管下0号vao64k的1KB主管分配器也静态分配、对应1班之27号64B(+1DP)。

1班之28号64B(+1DP)的vao64k分配器对象,对应2KB内存对象环形队列虚拟分管(内存单粒分配模式);2KB虚拟分管下辖有64K个2KB主管,一个2KB主管下属有64K个班(连续64DP、1K扇区128页512KB);2KB内存对象环形队列最大可有64K*64K*256 = 1T个2KB的内存对象,0号2KB主管的0号---3号的4个班已经是静态分配。2KB虚拟分管下0号vao64k的2KB主管分配器也静态分配、对应1班之29号64B(+1DP)。

1班之30号64B(+1DP)的vao64k分配器对象,对应4KB(页)内存对象环形队列虚拟分管(内存单粒分配模式);4KB虚拟分管下辖有64K个4KB主管,一个4KB主管下属有64K个班(连续128DP、2K扇区256页1MB);4KB内存对象环形队列最大可有64K*64K*256 = 1T个4KB的内存对象,0号4KB主管的0号---1号的2个班已经是静态分配。4KB虚拟分管下0号vao64k的4KB主管分配器也静态分配、对应1班之31号64B(+1DP)。

线程v节点对象的虚拟内存空间已经是固定分配,根据进程号线程号即可得到其相应的虚拟内存用户进程的线程栈页地址。416--447项、内核虚拟内存用户进程的线程栈vma对象
4G*4KB = 16TB(线程cao对象64B包含在线程堆栈页内),固定区域。
每进程有2GB独立私有线性虚拟内存空间pvma、是取决于用户程序的自定义分配方案,用户进程有多少个线程、每线程有多少个vma的虚拟内存对象,这些都是动态变化的;一个进程最大可在其2GB固有独立私有线性虚拟内存空间pvma中分配管理64k*256个vma对象,一个线程通常是最大可以分配管理256个vma对象。

1班之32号64B(+1DP)的vao64k分配器对象,对应虚拟内存空间区域的0号分管(管理最大64k个每进程2GB独立私有线性虚拟内存空间pvma的64K*2GB = 128TB的虚拟内存空间)之vma对象环形队列虚拟分管(虚拟内存分配模式);vma进程虚拟分管下辖有64K个vma进程主管(对应进程号),一个vma进程主管下属有64K个班(对应线程号、每个班是vao256的vma对象分配器);vma进程对象环形队列最大可有64K*64K*256 = 1T个vma的虚拟内存对象,只是提供了进程2GB固有独立私有线性虚拟内存空间pvma的空间动态锚位。只是静态分配256个vma进程主管,对应vma进程虚拟分管下0号---255号vao64k的vma进程主管分配器、4班之0号---255号64B(+1DP)。(/proc、存放动态变化的进程process文件,进程树根节点)

1班之33号64B(+1DP)的vao64k分配器对象,对应虚拟内存空间区域的2号--7号分管之vma对象环形队列虚拟分管(虚拟内存分配模式);vma虚拟分管下辖有64K个vma主管,一个vma主管下属有64K个班(每个班是vao256的vma对象分配器);vma对象环形队列最大可有
64K*64K*256 = 1T个vma的虚拟内存对象,如下:
2号分管:504--511项、内核映射、静态动态公共方法库区域共4TB,固定区域;OACS操作系统内核区域,只是最大64k*256个内核vma对象。对应vma虚拟分管下0号vao64k的vma主管分配器也静态分配、1班之34号64B(+1DP)。
3号分管:496--503项、共享内核虚拟内存地址空间4TB(磁盘双缓冲页映射、最大0.5G个),固定区域,进程共享;共享内核虚拟内存双页缓冲区域,只是256(最大32个主管)*64k*256个DP(双页缓冲区)。对应vma虚拟分管下1号---32号vao64k的vma主管分配器也静态分配、1班之35号---66号64B(+1DP)。
4号分管:480--495项/共享内核虚拟内存地址空间8TB(磁盘缓冲页空间、最大2G个页),固定区域,进程共享;共享内核虚拟内存单页缓冲区域,只是256(最大128个主管)*64k*256个单页缓冲区。只是静态分配64个主管,对应vma虚拟分管下33号---96号vao64k的vma主管分配器也静态分配、1班之67号---130号64B(+1DP)。
5号分管:448--479项、内核虚拟地址file对象区域16TB(进程打开文件描述符对象file、32B、最大512G个,平均每进程8M个),固定区域,进程共享;共享内核虚拟地址file对象区域,只是32k(最大32k个主管)*64k*256个file对象。只是静态分配108个主管,对应vma虚拟分管下
97号---204号vao64k的vma主管分配器、1班之131号---238号64B(+1DP)。

1班之239号64B(+1DP)的vao64k分配器对象,对应虚拟内存空间区域的8号以上分管之内核v节点对象打开文件表环形队列虚拟分管(虚拟内存分配模式);v节点虚拟分管下辖有64K个v节点主管,一个v节点主管下属有64K个班(每个班是vao256的v节点对象分配器);v节点对象环形队列最大可有64K*64K*256 = 1T个v节点虚拟内存对象。288--415项:内核虚拟内存区域64TB,内核v节点打开文件表,固定区域。只是静态分配256个主管,对应v节点虚拟分管下0号---255号vao64k的v节点主管分配器、3班之0号---255号64B(+1DP)。
1班之240号---255号为16个vao64k分配器,但其DP需要另外动态申请分配,1班总共静态占有256DP。

2班的256个64B(+2DP)的vao64k2分管分配器,对应磁盘空间区域的256个分管(磁盘空间卷号)之磁盘空间对象环形队列虚拟分管(磁盘空间分配模式、占有512DP);每个分管8ZB,可带最大16段64K个的vao4k主管分配器、主管号对应大数据块128PB;每个vao4k主管分配器,可带最大4K数据块组(16*2TB = 32TB)64K个数据块、组对应连续16数据块32TB;每个vao4k组分配器,可带最大4K个的班、班对应连续256章8GB;每个vao4k班分配器,可带最大4K个的大页、大页对应连续连续256DP(2MB);每个vao4k大页分配器,可带最大4K个的扇区512B。如果说、每个vao64k2分管分配器需要静态分配:16个16段0号vao4k主管分配器,需要256*16 = 4K个vao4k分配器,16个班;每个分管下的0段---1段的0号vao4k主管分配器的0号vao4k数据块组分配器--->及其下辖的0号vao4k班分配器--->及其下辖的0号vao4k大页分配器,需要256*3*2 = 6个vao4k分配器班;总共需要22个班、7班---28班。

8、连续与单粒、分配模式共存
 

一个vao64k分管分配器下属有最大64K个主管,划分为16段、每段4K个主管;有单粒或连续、主管分配模式,需64B(+2DP)的内存。
一个vao4k主管分配器下属有最大4K个组,磁盘空间有连续主管(大数据块128PB)连续连续组(32TB)或连续班(8GB)或连续大页(2MB)或连续扇区(512B)的分配管理,(虚拟)内存空间只是连续DP组的分配管理;有单粒或连续、组分配模式,需64B(+2DS双扇区)的内存。
连续主管或连续组的分配管理通常是分为13种类型环形队列:1、2、4、8、16、32、64、128、256、512、1K、2K、4K。需要的位图表述:
4K、1位表示,空闲1、使用0;连续2k的空闲位置则需要2位表示,空闲1、使用0;连续1k的空闲位置则需要4位表示,空闲1、使用0;连续512的空闲位置则需要8位表示,空闲1、使用0;连续256的空闲位置则需要16位表示,空闲1、使用0;
连续128的空闲位置则需要32位表示,空闲1、使用0;连续64的空闲位置则需要64位表示,空闲1、使用0;连续32的空闲位置则需要128位表示,空闲1、使用0;连续16的空闲位置则需要256位表示,空闲1、使用0;
连续8的空闲位置则需要512位表示,空闲1、使用0;连续4的空闲位置则需要1k位表示,空闲1、使用0;连续2的空闲位置则需要2k位表示,空闲1、使用0。总共需4K位1个扇区,而单粒1的空闲位置则需要4k位表示,空闲1、使用0,这样,共需要2个扇区。
一个vao64k2分管分配器,有16段、则需要32扇区(2DP),而一个vao4k(连续主管或连续组或连续班或连续大页)的分配器需要2扇区(2DS)。

在一个vao4k的xxx分配器中分配一个连续对象,比如连续111的对象;先是在连续128的位图区域查找,如果有空闲位、则分配,同时、相应变动下属连续xxx位的位图:1、2、4、8、16、32、64,一个“拆分”过程;没有则往上找,连续256的位图区域...;当释放时,相应变动上属连续xxx位的位图,有一个“伙伴合并”过程。有连续主管、连续组、连续班、连续大页、的分配模式。

这样,会有2种类型的vao64k分管分配器:64B(+1DP)的vao64k分配器和64B(+2DP)的vao64k2连续主管模式分配器。1班之0号---7号64B(+2DP)的vao64k分配器对象,对应8个物理内存空间分管;1班之8号---15号64B(+2DP)的vao64k2分配器对象,对应8个物理映射虚拟内存空间分管,2班的256个64B(+2DP)的vao64k2分配器对象,对应磁盘空间区域的256个分管(磁盘空间卷号)之磁盘空间对象环形队列虚拟分管(磁盘空间分配模式、占512DP);vao64k2静态共占有544DP,vao64k静态共占有736DP。主管分配器也是有2种:vao64k和vao4k。

/dsa(磁盘空间区域,树根节点)总管(1级、一个vao256总管分配器,带最大256个分管、分管号对应8位卷号8ZB,2班的256个64B(+2DP)的vao64k2分配器对象)--->分管(2级、一个vao64k2分管分配器,每个分管(卷号)下可带最大16段64K个的主管、主管号对应大数据块128PB)--->主管(3级、一个vao4k主管分配器,每个主管下可带最大4K数据块组(16*2TB = 32TB)64K个数据块、组对应连续16数据块32TB)--->组(4级、一个vao4k组分配器,每个组可带最大4K个的班、班对应连续256章8GB)--->班(5级、一个vao4k班分配器,每个班分配器下可带最大4k个大页连续256DP(2MB)对象)--->大页(6级、一个vao4k大页分配器,每个大页分配器下可带最大4k个扇区对象)。

/ddr总管(物理内存空间区域,树根节点,1级、一个vao256总管分配器,带最大256个分管;实际只用8个分管0---7(1班之0号---7号64B(+2DP)的vao64k2分配器对象,对应8个物理内存空间分管);1班之8号---15号64B(+2DP)的vao64k2分配器对象,对应8个物理映射虚拟内存空间分管;每个分管2TB,对应数据块号,余下的是虚拟分管)--->(虚拟)分管(2级、一个vao64k2或vao64k分管分配器,每个分管下可带最大16段64K个的主管32MB、主管号对应章号)--->主管(3级、一个vao4k主管分配器,每个主管下可带最大4K个DP组(16扇区双页8KB)。

v节点对象 = vmo对象 + xxx,vmo对象也视为v节点对象;vma对象和file对象、可看作vmo对象的变体,内核所关心的、主要是v节点对象。空间分配管理有2种,连续x主管或连续x组或连续x班或连续x大页的的空间分配管理、“班粒”之v节点对象分配管理。由v节点对象分配器环形队列,自然可以得到v节点类型和v节点号。

分配器有:vao64k2,vao64k,vao4k,vao256;前3种需要另外的“位图”表述,vao64k2大约 =  16*vao4k;vao64k的“位图DP”只是表述单粒1的64k位空闲1或使用0之状况,而vao64k2的“位图2DP”除表述单粒1的64k位,还需表述16段的vao4k之连续2位、连续4位、...、连续4K位、状况。

u16w vao256. {    	// 8W的vmo对象 + 8W的256位之位图 ,vao256分配器对象。
	u8w  vmo.; 	    // 分配器vmo对象 。	
	u8w  bitmap;	// 256位图,对应最多256个vmo对象项。
};

u8w  vmo. {    		// 文件打开表v节点管理对象8字/8w(v node management object),嵌入(被包含)到v节点中、为其成员。
	u32 v_pdnn; 	// 对象父目录v节点(parent directory node number),根目录节点为0。
	u32 v_hnext; 	// 对象v节点head头钩子,本对象v节点单向环下一个子v节点,钩挂对象的子节点(头插入),文件体系v节点树环。
	u16 v_type; 	// 对象v节点所属类的类型。
  u16 v_fcount;	// 本对象v节点单向环的实际子节点计数。高8位根目录下最大256项,低8位对象v节点树双向环计数。
  u32 v_count;	// 对象v节点引用计数。为0、暂时不使用。
	u32 v_next; 	// 对象v节点钩子,下一个v节点。自定义对象v节点双向环,空间分配管理体系对象节点树双向环、头节点。
	u32 v_prev; 	// 对象v节点钩子,上一个v节点。
	u32 v_sflags; 	// 对象v节点状态标志。
	u32 v_fpbuf;      	// 对象v节点物理内存缓冲区页起始地址,类同this指针 。空间(如CPU之SRAM区域cpun_mem)初始页号。
};

u16w vao4k. {    	// 8W的vmo对象 + 8W的属性项 ,vao4k对象分配器。
	u8w   vmo.; 	// 分配器vmo对象 。	
	u40   bitmaps;	// 双扇区DS起始地址(起始DP页、起始扇区),第一扇区是12种连续位的位图,第二扇区是4k位图。
	u8    idlen1K;	// 连续1K位的空闲数(idle number),最大4。
	u8    idlen512;	// 连续512位的空闲数(idle number),最大8。
	u8    idlen256;	// 连续256位的空闲数(idle number),最大16。
	u8    idlen128;	// 连续128位的空闲数(idle number),最大32。
	u8    idlen64;	// 连续64位的空闲数(idle number),最大64。
	u8    idlen32;	// 连续32位的空闲数(idle number),最大128。
	u8    idlen16;	// 连续16位的空闲数(idle number),最大256。
	u16   idlen8;	// 连续8位的空闲数(idle number),最大512。
	u16   idlen4;	// 连续4位的空闲数(idle number),最大1K。
	u16   idlen2;	// 连续2位的空闲数(idle number),最大2K。
	u16   idlen1;	// 1位的空闲数(idle number),最大4K。
	u3w  reserve;	// 保留、将来扩充。
};

u16w vao64k. {    	// 8W的vmo对象 + 8W的属性项 ,vao64k对象分配器。
	u8w  vmo.; 	    // 分配器vmo对象 。	
	u32  bitmaps;	// 64k位图、双页DP起始页号地址,对应最多64k个对象项。
	u16  idlen1;	// 1位的空闲数(idle number),最大64K。
	u16  reserve;	// 保留、将来扩充。
	u6w  reserve;	// 保留、将来扩充。
};

u16w vao64k2. {    	// 8W的vmo对象 + 8W的属性项 ,vao64k2对象分配器。
	u8w  vmo.; 	    // 分配器vmo对象 。	
	u32   bitmaps;	// 四页2DP起始页号地址,64k位图DP,12种连续位的位图DP。
	u8    idlen4K;	// 段的空闲数(idle number),最大16。
	u8    idlen2K;	// 连续2K位的空闲数(idle number),最大2*16。
	u8    idlen1K;	// 连续1K位的空闲数(idle number),最大4*16。
	u8    idlen512;	// 连续512位的空闲数(idle number),最大8*16。
	u16   idlen256;	// 连续256位的空闲数(idle number),最大16*16。
	u16   idlen128;	// 连续128位的空闲数(idle number),最大32*16。
	u16   idlen64;	// 连续64位的空闲数(idle number),最大64*16。
	u16   idlen32;	// 连续32位的空闲数(idle number),最大128*16。
	u16   idlen16;	// 连续16位的空闲数(idle number),最大256*16。
	u16   idlen8;	// 连续8位的空闲数(idle number),最大512*16。
	u16   idlen4;	// 连续4位的空闲数(idle number),最大1K*16。
	u16   idlen2;	// 连续2位的空闲数(idle number),最大2K*16。
	u32   idlen1;	// 1位的空闲数(idle number),最大64K。
	u32  reserve;	// 保留、将来扩充。
};

三、设备文件节点树

设备树是采用树形结构来描述板子上的设备信息的设备文件目录树,每个设备都是一个节点、设备文件节点;有2种类型的设备树:物理设备树根/dev,协议设备树根/pdev;在内存文件目录体系中,设备树根挂靠在、/ddr总管之0号128B的vao64k虚拟分管(挂钩在/ddr总管之64B的0号分管0号主管的1班之20号64B(+1DP))下辖0号vao64k的128B主管分配器(挂钩在/ddr总管之64B的0号vao64k虚拟分管0号vao64k主管的1班之21号64B(+1DP))下的0班vao256班分配器中的0号128B文件对象(/dev)和1班vao256班分配器中的0号128B文件对象(/pdev)。静态分配、128B对象有64个班(连续4DP),16K个128B对象的内存池、2MB。一个实际系统没有那么多的设备,最大256个物理设备、最大256个协议设备。

设备树根(根目录)静态固定后,就需考虑设备的分类(子目录)问题。i_mode.F_DEV = 15表示物理设备文件,如果 i_flags.I_DIR = 1表示i节点为目录文件(微型文件)D(directory file),或说是设备子目录文件;如果是虚拟设备文件,i_mode.有相应数值表示,如字符设备、或块设备、等等。尽管设备品种繁多,但实际上的种类并不多;我们用成员u8   i_type; // 设备i节点类型(最大256种):物理设备类型、协议设备类型(cdev字符设备大类、bdev块设备大类、等),来表述设备或设备子目录的代表数值;用成员u8   i_layers; // 设备i节点对象的层数,来表述设备所在的设备目录树层次。

1、物理层设备分类:
❏通信类:
a、单端串口类/dev/sesp(Single ended serial port)/:
1)、单线协议接口SWPI(Single wire protocol interface):双方通过一根IO信号线的电平或电流数字接收或发送数据、进行的低速(最大2Mbps)半(全)双工通讯模式。节省I/O资源,结构简单、成本低廉、便于总线扩展维护等优点,将地址线、数据线、控制线合为一根信号线。

2)、TWI(Two wire Serial Interface)双线串行接口:兼容Philips公司开发的I2C总线,由一根双向时钟I/O线SCL和一根双向传输数据I/O线 SDA组成,以字节为单位进行传输。在TWI总线上传送数据,先送最高位,由主机发出启动信号,SDA在SCL 高电平期间由高电平跳变为低电平,然后由主机发送一个字节的数据。数据传送完毕,由主机发出停止信号,SDA在SCL 高电平期间由低电平跳变为高电平。

3)、I2C总线(Inter-Integrated Circuit Bus 内部集成电路总线IICB、简写I2C)是一个真正的多主机总线,如果两个或多个主机同时初始化数据传输,可以通过冲突检测和仲裁防止数据破坏,每个连接到总线上的器件都有唯一的地址,任何器件既可以作为主机也可以作为从机,但同一时刻只允许有一个主机。数据传输和地址设定由软件设定,非常灵活。总线上的器件增加和删除不影响其他器件正常工作。I2C总线可以通过外部连线进行在线检测,便于系统故障诊断和调试,故障可以立即被寻址,软件也利于标准化和模块化,缩短开发时间。连接到相同总线上的IC数量只受总线最大电容的限制,串行的8位双向数据传输位速率在标准模式下可达100Kbit/s,快速模式下可达400Kbit/s,高速模式下可达3.4Mbit/s。I2C总线为开漏输出、具有极低的电流消耗,需通过上拉电阻接电源VCC、抗高噪声干扰;增加总线驱动器可以使总线电容扩大10倍,传输距离达到15m;兼容不同电压等级的器件,工作温度范围宽;当总线空闲时,两根线都是高电平,负载能力为400pF。主器件用于启动总线传送数据,并产生时钟以开放传送的器件,此时任何被寻址的器件均被认为是从器件。在总线上主和从、发和收的关系不是恒定的,而取决于此时数据传送方向。如果主机要发送数据给从器件,则主机首先寻址从器件,然后主动发送数据至从器件,最后由主机终止数据传送;如果主机要接收从器件的数据,首先由主器件寻址从器件。然后主机接收从器件发送的数据,最后由主机终止接收过程。在这种情况下。主机负责产生定时时钟和终止数据传送。

4)、UART通用异步收发传输器(Universal Asynchronous Receiver/Transmitter):一种通用的双I/O线(TXD发送线、RXD接收线)串行通信接口(SCI),用于异步双向通信,可以实现全双工传输和接收。发起方为主机、响应方为从机,主、从机以相同同步时钟通信即是同步通信,需要建立同步过程;可主机时钟同步,也可从机时钟同步。如果时钟信号嵌入在通信线TXD或说RXD中,接收方需要从数据信号中恢复时钟信号,那么这就是异步通;需要异步通信的时钟信号标记,如UART通信的数据起始位和停止位是必不可少的。
起始位:先发出一个逻辑“0”的信号,表示传输字符的开始。
数据位:起始位之后,数据位个数可以是7、8、9、16、32、64、128、256、等等,常用ASCII码构成一个字符;从最低位开始传送,靠时钟定位。
奇偶校验位:数据位加上这一位后,使得“1”的位数为偶数(偶校验)或奇数(奇校验),以此来校验数据传送的正确性。
停止位:它是一个字符数据的结束标志,可以是1位、1.5位、2位的高电平。 因主、从机有各自的时钟,停止位不仅仅是表示传输的结束,并且提供计算机校正时钟同步的机会。
空闲位:处于逻辑“1”状态,表示当前线路上没有数据传送。
波特率:衡量数据传送速率的指标,表示每秒钟传送的符号数(symbol)。如果每8bit代表一个符号,数据传送速率为120字符/秒,或说波特率120baud,比特率是120*8 = 960bit/s = 960bps。如果1bit代表一个符号,则波特率等同比特率。如果通信双方规定了相同的比特率、每个符号的位数,那么、接收方只需检测起始位来同步;如果事先不知道系统的通信速度,可根据接收一个字符作自动波特率检测并设置,通常前者应用较多。16倍或8倍过采样、检测起始位从而产生同步接收的位时钟。

5)、 UARTMPC多处理器通信( UART multi_processor communication):多个 UART 连接在一个网络中,其中一个 UART为主机,其 TXD 输出与其他 UART 的 RXD 输入相连;而其他 UART 为从机,其各自的 TXD 输出在逻辑上通过与运算连在一起,并与主机 UART 的 RXD 输入相连。在多处理器配置中,理想情况下通常只有预期的消息接收方主动接收完整的消息内容,从而减少由所有未被寻址的接收器造成的冗余 UART 服务开销,可通过静默功能将未被寻址的器件置于静默模式下。

6)、UART Modbus 通信:UART 为 Modbus/RTU(一个半双工块传输协议,一个块的结束通过超过 2 个字符时间(例如 22 个位时间)的“静默”(空闲线路)来识别,此功能通过可编程的超时功能实现。如果在此期间接收线路空闲,则在接收到最后一个停止位后,将生成中断,同时通知软件当前块接收已完成。) 和 Modbus/ASCII 协议(块结束通过特定 (CR/LF、回车和换行,特征字符中断) 字符序列识别)的实现提供基本支持。 该协议的控制部分(地址识别、块完整性控制和命令解析)必须用软件实现,UART 为块结束检测提供基本支持,无需软件开销或其它资源。

7)、SPI同步串行设备接口(Serial Peripheral Interface):支持与外部器件进行双线半双工、三线全双工和双线单工同步串行通信,比UART多了通信同步时钟 SCK(serial clock)线,TXD改为主出从入(master output slave input)MOSI、RXD改为主入从出(master input slave output)MISO。该接口可配置为主模式或从模式,并且能够在多从或多主配置中运行。在配置为主器件时,它为外部从器件提供通信同步时钟 SCK;从器件选择信号slave select(SS)可以由主器件提供,也可以选择由从器件接收;默认情况下使用 Motorola 数据格式,但也支持某些其他特定模式。多用于Flash存储器(如NOR Flash&Nand Flash),ADC、LCD控制器等外围器件的通讯接口,大大增强了处理器的外设扩展能力。

8)、SCI智能卡接口(Smart Card Interface):智能卡模式采用单线半双工通信协议。对于 ISO/IEC 7816-3 标准中定义的智能卡,支持 T=“0”(字符模式,奇偶校验错误在保护时间周期内的每个字符结束时指示。)和 T=“1”(块模式)异步协议,支持 0.5 和 1.5 个停止位,发送数据会经过至少0.5个时钟周期的延迟;连接到智能卡时,TXD 输出会驱动一条双向线(它也由智能卡驱动),须将TXD引脚配置为开漏引脚。

9)、IrDA(infrared data association红外线数据标准协会)红外数据通讯接口(Serial InfraRed) SIR: 通过对串行数据脉冲的波形压缩和对所接收的光信号电脉冲的波形扩展这一编码解码过程(3/16 EnDec)实现红外数据传输,ENDEC 模块。SIR(IRDA1.0)的最高通讯速率只有115.2Kbps,FIR(Fast InfraRed、IRDA1.1标准)其最高通讯速率可达到4Mbps,VFIR技术(Very Fast InfraRed、IRDA1.1标准)通讯速率高达16Mbps的。

10)、RS232 硬件流控制串行接口:相比UART多了2根I/O线,CTS(清除以发送)如果驱动为高电平,则该信号用于在当前传输结束时阻止数据发送;RTS(请求以发送)如果为低电平,则该信号用于指示 USART 已准备好接收数据。

11)、RS485 硬件控制串行接口:相比UART多了1根I/O线,DE(驱动器使能)该信号用于激活外部RS485收发器的发送模式;DE 和 RTS 共用同一个引脚,SPI的SS 和 CTS 共用同一个引脚。RS(Recommended Standard )推荐标准,RS485定义的是使用平衡(也称作差分)多点传输线的驱动器(driver)和接收器(receiver)的电气特性。RS485通常是半双工(Half-Duplex)的一主机带多从机模式,连接RS485通信链路时只是简单地用一对双绞线将各个接口的“A”、“B”端串接起来,以及将各个从机的信号地(连接到从机电源地)串接到主机地的信号地线,常采用4芯小电缆(信号地、供给低功耗从机的12V或5V电源线,AB双绞线)。10米时,RS485的数据最高传输速率可达35Mbps,在1200米时,传输速度可达100Kbps;抗共模干扰能力增强,即抗噪声干扰性好;传输距离远,支持节点多。从机到从机的通信,只能是经过主机转发;任一时刻的通信只能是主机发送数据到某一地址的从机,或从机响应而发送数据到主机的半双工通信主站轮询模式,应用层通信协议自定。

12)、SCAN(Simple Controller Area Network)简单化硬件的CAN控制器局域网络串行接口:CAN总线的国际标准(ISO 11898)及ISO11519,是应用广泛的现场总线控制系统FCS(Fieldbus Control System)之一。CAN总线支持多个设备节点(Node)挂载在总线上,支持多主机、多从机模式,设备节点间直接可以相互通讯;物理层面类同RS485,协议较为复杂、硬件实现协议成本高和逻辑复杂;SCAN是试图利用RS485简单硬件扩充,而CAN协议使用软件实现的方案。 SCAN总线控制器在发送数据的同时监控总线电平,如果电平不同,则停止发送并做其他处理,相比于RS485需增加这部分逻辑硬件电路以及报文发送失败后的总线空闲时重发机制电路等等(发送缓冲区空或报文接收缓冲区满、错误、等中断);如果该位位于仲裁段,则退出总线竞争;如果位于其他段,则产生错误事件。

13)、SPDIF(Sony/Philips Digital Interface Format)、Sony/Philips格式的光纤同轴数字音频串行接口:IEC-60958 和 IEC-61937 标准的SPDIF 块包含 192 个帧。每个帧由两个 32 位的子帧构成,通常一个子帧用于左通道A,一个子帧用于右通道B。每个子帧由一个 SOPD 模式(4 位)构成,用于指定该子帧是否为块的开始(报头B),或者是否标识块中某处通道 A(报头M),或者是否指代通道 B(报头W);接收和发送2倍位流的比特流双相符号编码,192khz*64位(帧) = 12288kbps、双相符号编码后为24576kbps;双相符号编码后,以测量两个连续边沿之间的位时间间隔UI为基础;持续 3个 UI、称为 TL(连续111或连续000),仅在报头期间出现,等效为UART串口子帧的开始和结束合一的符号。这些标准支持高采样率的简单立体声以及压缩的多通道环绕声,如 Dolby 或 DTS 定义的音频。
位 0 到位 3 包含同步报头之一(报头B(双相码前一位为0时11101000或前一位为1时00010111)、M(双相码前一位为0时11100010或前一位为1时00011101)、W(双相码前一位为0时11100100或前一位为1时00011011));
位 4 到位 27 包含以线性 2 的补码表示的音频采样字D0--D23,最高有效位 (MSB) 为位 27;
位 28(有效性位“V”)表示数据是否有效(例如转换为模拟数据),
位 29(用户数据位“U”)包含用户数据信息,如光盘的音轨编号;
位 30(通道状态位“C”)包含通道状态信息,如采样率和复制保护;
位 31(奇偶检验位“P”)包含奇偶校验位,这样位 4 到位 31(含)将包含偶数个“1”和偶数个“0”(偶校验)。
双相符号编码:要传输的各个位通过由两个连续二进制状态构成的符号表示,符号的第一个状态始终不同于前一个符号的第二个状态。如果要传输的位为逻辑 0,则符号的第二个状态与第一个状态相同;但如果该位为逻辑 1,则两个状态不同。这样32位子帧就变成64位双相码,1帧为128位双相码。
硬件对传入信号进行16倍过采样和滤波,检测连续111或连续000、块和子帧报头开始;估算时间间隔,估算符号率和同步性;解码串行数据并验证完整性,连续跟踪符号率,双相协议驱动层软件实现双相符号编解码。

14)、USART(Universal Synchronous/Asynchronous Receiver/Transmitter)通用同步/异步串行接收发送器:USART是一个全双工通用同步/异步串行收发模块、最高速率100Mbps,该接口是一个高度灵活的串行通信设备IC内部功能模块;是将上面的、1)---13)的大同小异之功能整合为一个通用模块,由用户软件灵活配置;IC芯片内部有多个USART(通常0---7个:UART0用于固件下载和串口通信,1个SPI用于Flash存储器,1---3个用于UART/SCI/IrDA/TWI/I2C,1---3个用于RS232/RS485/SCAN/SPDIF),可软件分别配置为各种功能模块。

b、单端并口类/dev/sepp(Single ended parallel port)/:

1)、QSPI(Quad SPI )4线双路SPI同步串行设备接口:实际上就是用2路同步SPI拼接而成的接口(共用CS1、CLK),有多种工作模式。

⚫双路同步I2S模式:共用CS1、CLK的二路同步SPI,常作为双路同步I2S接口;支持I2S Philips 标准,LSB 或 MSB 对齐标准,PCM 音频标准。
SDO0:    串行数据输出(Serial Data Out、映射到 SPI0_MOSI),在主模式下发送音频采样。
SDI0:    串行数据输入(Serial Data In、映射到 SPI0_MISO),在主模式下接收音频采样。
WS:    字选择(映射到 SPI0_SS ),表示帧同步,只有主模式、配置为输出。
BCLK:    串行时钟(映射到SPI0_SCK ),表示串行位时钟,它在主模式下被配置为输出。
SDO1:    串行数据输出(映射到 SPI1_MOSI),用于在主模式下发送音频采样。
SDI1:     串行数据输入(映射到 SPI1_MISO),用于在主模式下接收音频采样。或作为PDM 比特流数据,PDM_SDI。
作为SPI可以有主、从2种模式,但作为I2S就只是主模式;当某些外部音频设备需要使用主时钟MCLK输入时,可以考虑单独一个I/O引脚作为MCLK输出,也可以考虑用位时钟BCLK串接过去当做主时钟MCLK。
MCLK:主时钟(单独映射),主时钟频率固定为 256 x FWS (其中 FWS 为音频采样频率)。

⚫连接单、双或四(条数据线)SPI FLASH 存储介质的接口:
IO0/SDO:(映射到 SPI0_MOSI),双线/四线模式为双向 IO,单线模式为串行数据输出SDO。
IO1/SDI:  (映射到 SPI0_MISO),双线/四线模式为双向 IO,单线模式为串行数据输入SDI。
CS1:    片选择(映射到 SPI0_SS ),低电平有效。
CLK:    串行时钟(映射到SPI0_SCK ),表示串行位时钟,FLASH 的时钟。
IO2:    (映射到 SPI1_MOSI),在四线模式中为双向 IO。
IO3:    (映射到 SPI1_MISO),在四线模式中为双向 IO。

⚫SDIO(Secure Digital Input and Output)安全数字输入输出总线接口模式:支持三种不同的数据总线模式:1位(默认)、4位和8位(8位模式需2个QSPI组合),支持多媒体卡(MMC卡)、SD存储卡、SD I/O卡和CE-ATA设备等;全速的SDIO卡,传输率可以超过100Mbps,对于 8 位模式、数据传输高达 208 MB/s;低速的SDIO卡,支援的时脉速率在0至400KHz之间。SDIO总线和USB总线类似,SDIO总线也有两端,其中一端是主机(HOST)端,另一端是设备端(DEVICE),采用HOST- DEVICE这样的设计是为了简化DEVICE的设计,所有的通信都是由HOST端发出命令开始的。在DEVICE端只要能解析HOST的命令,就可以同HOST进行通信了,SDIO的HOST可以连接多个DEVICE。
SD0:    (映射到 SPI0_MOSI),双向数据信号,1BIT模式下SD0用来传输数据。
SD1:      (映射到 SPI0_MISO),双向数据信号, 复用为中断线。
CMD:    双向命令/响应信号(映射到 SPI0_SS )。
CLK:    串行时钟(映射到SPI0_SCK ),表示串行位时钟。
SD2:    (映射到 SPI1_MOSI),双向数据信号。
SD3:    (映射到 SPI1_MISO),双向数据信号。
SDR 单倍数据速率信号传输,DDR 双倍数据速率信号传输(在CLK 的两种时钟边沿上均采样数据);SD 卡系统定义了三种通信协议:SD、SPI 和UHS-II,不推荐多卡槽用共同的总线信号。

2)、SDMMC安全数字输入输出总线与多媒体卡MMC(Multi Media Card)主机接口: SDIO8位模式、eMMC ( Embedded Multi Media Card)、PSRAM、2个QSPI的组合,8位半双工总线;SDIO 多字节模式:块大小为 1---512 字节的单一数据块,MMC 流模式:连续数据流。
SD0:    (映射到 SPI0_MOSI),双向数据信号,1BIT模式下SD0用来传输数据。
SD1:      (映射到 SPI0_MISO),双向数据信号, 复用为中断线。
CMD:    双向命令/响应信号(映射到 SPI0_SS )。
CLK:    串行时钟(映射到SPI0_SCK ),表示串行位时钟,0~200MHZ。
SD2:    (映射到 SPI1_MOSI),双向数据信号。
SD3:    (映射到 SPI1_MISO),双向数据信号。

SD4:    (映射到 SPI2_MOSI),双向数据信号。
SD5:      (映射到 SPI2_MISO),双向数据信号。
DS:    data strobe(映射到 SPI2_SS ),slave device 发给host controller,主用在HS400 mode,频率与clk一致。
RST:    硬件复位线reset(映射到SPI2_SCK )。
SD6:    (映射到 SPI3_MOSI),双向数据信号。
SD7:    (映射到 SPI3_MISO),双向数据信号。

3)、24位同步并行接口(Synchronous parallel interface)SPI24:主要应用场合:中速双踪示波器与信号发生器的接口、LDTC接口(TFTLCD的RGB接口)、DCMI数字摄像头接口。

⚫LCD-TFT 显示控制器 (LTDC)同步并行输出接口:
LCD_CLK         时钟输出
LCD_HSYNC     水平同步输出
LCD_VSYNC     垂直同步输出
LCD_DE         非数据使能
LCD_R[7:0] 数据:    8 位红色数据输出
LCD_G[7:0] 数据:    8 位绿色数据输出
LCD_B[7:0] 数据:    8 位蓝色数据输出

⚫DCMI (Digital camera manageability interface)数字摄像头管理接口是一个同步并行输入接口,可接收高速同步数据流:

8 位、10 位、12 位、14 位的DCMI_D[0..13]    DCMI 数据输入
DCMI_PIXCLK                像素时钟输入
DCMI_HSYNC                水平同步/数据有效 输入
DCMI_VSYNC                垂直同步输入

⚫8位或16位的同步并行ADC/DAC接口:单端I/O线的翻转速率也就最高200MHZ,或说只能连接最高速率200MSPS的8位外部ADC或DAC芯片了。使用连续过采样,理论上可以采集2GHZ或更高的20GHZ周期信号;而这需要延迟模块 (DLYB), 用于生成输出时钟、使其与输入时钟存在相位偏移;ECO时钟采样线(上升沿采样、下降沿出结果)连接到经过延迟模块 (DLYB)的高清定时器HRTIM采样周期输出,从而“非过零触发”过采样高速周期信号。16位同步并行输入连接2路8位200MSPS的ADC,8位同步并行输出连接1路8位200MSPS的DAC作为信号发生器。

4)、FMC( Flexible Memory Controller)灵活存储控制器接口:包含了连接外设(静态SRAM, Flash/OneNAND Flash,PSRAM(4个存储区域),带有硬件 ECC 的 NAND Flash 存储器、可检查多达 8 KB 的数据,同步 DRAM (SDRAM/Mobile LPSDR SDRAM) 存储器,)所必须的接口信号,FMC 一次只能访问一个外部器件。

FMC_NL        锁存使能(部分NOR Flash器件,称地址有效 NADV),NOR/PSRAM共享信号。
FMC_CLK         时钟(用于同步访问)输出,NOR/PSRAM共享信号。
FMC_NBL[3:0]    字节选择通道,NOR/SRAM共享信号。
FMC_A[25:0]     地址总线,共享信号。
FMC_D[31:0]     双向数据总线,共享信号。
FMC_NE[x]     片选、x = 1---4,NOR/PSRAM/SRAM共享信号。
FMC_NOE        输出使能,NOR/PSRAM/SRAM共享信号。
FMC_NWE     写入使能,NOR/PSRAM/SRAM共享信号。
FMC_NWAIT/INT     FMC 的 NOR Flash 等待输入信号,NOR/PSRAM/SRAM共享信号。
FMC_SDCLK    SDRAM 时钟,SDRAM输出信号。
FMC_SDNWE    SDRAM 写入使能,SDRAM输出信号。
FMC_SDCKE[1:0]    SDRAM 存储区域 1 和2的时钟使能,SDRAM输出信号。
FMC_SDNE[1:0]    SDRAM 存储区域 1 和2的芯片使能,SDRAM输出信号。
FMC_NRAS    SDRAM 行地址选通,SDRAM输出信号。
FMC_NCAS    SDRAM 列地址选通,SDRAM输出信号。

c、双端串口类/dev/desp(double ended serial port)/:
双端I/O信号或说差分信号传输技术、与传统的单端传输方式相比,具有低功耗、低误码率、低串扰和低辐射等特点,其传输介质可以是铜质的PCB连线或平衡电缆,最高传输符号率可达约2GHZ。实际电路中只要使用低压差分信号LVDS(Low Voltage Differential Signal),350mV左右的低摆幅便能满足近距离传输的要求。假定负载电阻为100Ω,采用LVDS方式传输数据时,如果双绞线长度为 5米,传输速率可达480 Mbps;当电缆长度增加到20m时,速率降为100 Mbps;而当电缆长度为100m时,速率只能达到10 Mbps左右。 LVDS发送器由一个驱动差分线对的电流源组成通常电流为3.5mA,LVDS接收器具有很高的输入阻抗,因此发送器输出的电流大部分都流过匹配电阻,并在接收器的输入端产生大约350mV的电压。当驱动器翻转时,它改变流经电阻的电流方向,因此产生有效的逻辑“1”和逻辑“0”状态。

1)、USB2.0(Universal Serial Bus)通用串行总线接口:类同单线协议接口SWPI的半双工通讯模式,只不过是单端改为双端的差分信号;本质上就是将类同RS485收发器、或说CAN收发器,集成到芯片内吧;USB设备通信速率自适应性(检测AB线电平):高速HS(High- Speed,480 Mbps)、全速FS(Full-Speed,12Mbps)和低速LS(Low-Speed,1.5Mbps),设备即插即用,软件自动地检测、安装和配置该设备。不过,USB2.0协议非常复杂,我连阅读的兴趣都没有;应该是物理层和协议层分开表达的设计,或说USB2.0物理接口、也可以作为RS485物理接口或CAN物理接口;而实际上USB2.0部分协议是硬件实现,没能坚守物理层的清晰表达与简洁。USB 3.0(5Gbps 数据传输速率)以上、类同UART串口,有发送TXD和接收RXD。同步时钟嵌入在收发信号中,还需考虑DC 平衡;双相编码8b/16b,会浪费一倍的带宽;编码就是为了尽量把低频的码型优化成较高频的码型,从而保证低损耗的传输。USB 3.0为8b/10b编码,也就是每传送10bit资料中,只有8bit是真实的资料,剩余的2bit是做为检查码和同步时钟恢复,连续的“1”或“0”不超过5位。而新的USB 3.1则是使用128b/132b编码,在132bit的资料中,只需使用4bit做为检查码和同步时钟恢复,传输损耗率大幅下降为3%(4/132),所以USB 3.1不单只是提升频宽而已,连传输效率也增进不少,USB3.1物理层接口实现10Gbps 数据传输速率。

USB2.0,Type-A、Type-B:+5V(红)、D-(白)、D+(绿)、GND(黑)。
USB2.0,Mini型,Micro-A/B:+5V、D-、D+、空脚、GND。
Type-C接口:
A面:A1  GND、TX1+、TX1-、VBUS、CC1、D1+、D1-、SBU1、VBUS、RX2-、RX2+、GND
B面:       GND、RX1+、RX1-、VBUS、SBU2、D2-、D2+、CC2、VBUS、TX2-、TX2+、GND
常规USB3.x Type C接口公头:不分正反面。
  GND、TX+、TX-、VBUS、CC、D+、D-、SBU1、VBUS、RX-、RX+、GND
  GND、RX+、RX-、VBUS、SBU2、D-、D+、CC、VBUS、TX-、TX+、GND  
VBUS:        电源正极、+5V或+20V/5A,GND电源地。
D+、D-:        USB2.0通信线。
TX+、TX-:        USB3.0、USB3.1的发送数据线。
RX-、RX+:        USB3.0、USB3.1的接收数据线。
CC:        USB PD通信线。

建议未来USB5.x以上协议:取消D+、D-的USB2.0通信线,改为差分时钟同步符号信号CLK+、CLK-;这样,取消复杂的8b/10b编解码或128b/132b编解码或128b/130b编解码的直接数字传输硬件实现,而用QAM256等差分模拟ADC/DAC数字调制来实现更为高速可靠的同步通信。4相调制(等效相位调制2位),64种电平、或说64种差分电流的6位幅度调制,这样一来、传送每个符号是8位二进制数;调整差分总线频率f(或说符号率速度)就会得到不同的8倍f传输速度,f = 2GHZ、传输速度16Gbps,收发全双工就是32Gbps、等效PCIe 5.0。

2)、以太网 ETH(Ethernet)物理层PHY 接口:实现 100/1000/10000 Mb/s 数据传输速率,可以实现全双工发送TXD和接收RXD;类同UART串口、只不过是单端改为双端的差分信号;以MAC(Media Access Control)帧表述,自然会有通信数据的帧起始和结束符号表示;考虑双绞线DC平衡及时钟同步,得用8b/10b编码、或128b/132b编码、或以后的128/130b编码。不考虑USB2.0通信线时,实际上就与USB3.x的物理层统一起来,降低了芯片硬件设计的复杂性。取消MII(Media Independent Interface)媒体独立接口,MII接口是MAC与PHY连接的标准接口,它是IEEE-802.3定义的以太网行业标准;MII与MAC层(媒体访问控制子层协议,位于OSI七层协议中数据链路层的下半部分,主要是负责控制与连接物理层的物理介质),可以考虑用软件实现,只是少量的特征硬件实现、大幅度减少芯片硬件复杂性。取消10Mb/s同轴传输协议、或说半双工操作的 CSMA/CD 协议,简化设计。

MAC帧结构:
取消重复的IP地址(只是使用MAC地址),合拼TCP和UDP协议,TCP/IP四层协议系统改为NTCP/MAC三层协议体系;网络传输控制协议NTCP(NetWork Transmission Control Protocol)也作了很大的改进和简化、去除大部分的现有网络协议,实现代码量大幅减少。
MAC帧分为信令帧ICMP(因特网控制信息协议 Internet Control Message Protocol)和数据帧DF(Data Frame)。
帧头( Preamble )14字节【不包含前置同步码字段7字节(0和1交替的56位(55-55-55-55-55-55-55))和帧的1字节起始定界标志SFD( Start of Frame Delimiter 固定为10101011 )以及内容数据、 EOF (End of Frame)帧结束字段】= 目的物理地址DPA( Destination Physical Address ) 6字节 + 源物理地址SPA( Source Physical Address )6字节 + 类型/长度(type/lenth)2字节。
帧尾 = 帧校验序列FCS(Frame check sequence)字段4字节(也称循环冗余校验CRC字段(Cyclic Redundancy Check))。
NTCP头20字节(NTCP首部结构) = 1字节TTL跳数限制 + 1字节TOS传输优先级、流量类型(或说业务流类别Traffic Class)+2字节PLL载荷长度Payload Length(本帧的有效载荷长度值)+6位FNPP数据包的帧数(一个数据包可分为多个帧最大64帧,0表示ICMP信令帧、1为数据包不分帧)+ 6位FNP数据包的帧号(或信令帧ICMP时为6位信令连接标志)+20位DFL数据流标识Date Flow Label(标识不同的数据报)+48位源信息(16位源端口号+16位源Socket 连接文件号cfd+16位源进程号SPD)+48位目标信息。
ICMP头10字节 = 1字节Type 类型+1字节Code代码+2字节Checksum+1字节ICMP信令标志+1字节ICMP信令帧segnum附带数据项印记指针(项数n、每项16字节)+1字节源设备状态机和1字节状态标志+1字节目标设备状态机和1字节状态标志。
16字节segnum附带数据项印记(沿途路由器设备标识)= 12位设备类型标识(级数层数路由器或交换机或主机)低4位设备PMTU+6字节设备聚集地址 + 8字节发送时间戳( xmit)ns。16字节segnum附带数据项也可以是如时间戳或路由表数据、等等的数据项,取决于ICMP信令帧的类型和代码字段。
MAC帧头的类型/长度(type/lenth)2字节:
IPv4:0x0800
ARP:0x0806
PPPoE:0x8864
802.1Q tag:0x8100
IPV6:0x86DD
MPLS Label:0x8847
NTCP:0x999Y,Y为帧有效载荷最大传输单元长度值PMTU(Payload Max Transmission Unit), Y = 0--128、1--256、2--512、3--1024、4--1280、5--1440、6--2KB、7--4KB、8--8KB、9--16KB、A(10)--32KB、B(11)--64KB、C(12)--128KB、D(13)--256KB、
E(14)--512KB、F(15)--1MB。
也允许其它协议:0x99XY,X为除9外其它15种类型协议。
实际帧长度 = 帧头尾18字节 + NTCP包头长度20字节 + ICMP头10字节+ 帧载荷长度。
一个NTCP数据包DP(Date Packet)最大可分为64个数据帧,当前最大数据帧(或信令帧)为64KB、故最大数据包为64*64KB = 4MB,最小数据包(或最小信令帧:16字节icmpdata附带数据第0项(发送ICMP信令帧的源设备标识))为1包 = 1帧 = 16B。

POE RJ45通信口插座:POE供电2*30W或2*70W。收发差分线速度:最大32Gbps、等效PCIe 5.0x1,通常100 Mbps、1 Gbps、10 Gbps。
引脚:
P1、 TX_D1+ Tranceive Data+(发送数据+)

P2、TX_D1- Tranceive Data-(发送数据-)

P3、 RX_D2+ Receive Data+(接收数据+)

P4、 +20V/1.5A或+48V/1.5A  短距离(小于5米)电源,10 Gbps以上速率时为参考同步时钟信号:CLK+。
P5、 +20V/1.5A或+48V/1.5A  短距离(小于5米)电源(设备拔插自动检测IO3线),10 Gbps以上速率时为参考同步时钟信号:CLK-。
P6、 RX_D2- Receive Data-(接收数据-)
P7、 GND
P8、 GND

3)、DSPI差分同步串行设备接口(Differential Serial Peripheral Interface):将单端SPI换为差分DSPI的最大好处是通信速度超快,DSPI的主要应用:未来USB5.x以上协议接口,万兆以太网ETH接口,未来UFS5.x(Universal Flash Storage)通用闪存存储卡接口,固态硬盘SSD(Solid State Disk或Solid State Drive)接口。有了差分时钟同步符号信号CLK+、CLK-,可取消复杂的8b/10b编解码或128b/132b编解码或128b/130b编解码的直接数字传输硬件实现,而用QAM256等差分模拟ADC/DAC数字调制来实现更为高速可靠的同步通信。调整差分总线频率f(或说符号率速度)就得到不同8倍f传输速度,f = 2GHZ、速度16Gbps,收发全双工就是32Gbps、等效PCIe 5.0x1。

⚫高速(GSPS级)的DAC、ADC技术并不复杂,基础原理就那样了、简单明白;工艺上改进差分对管的速度、做到8位DAC、8GSPS(G点/秒)、没难度,2级6位差分并行比较器阵列、可做到12位4GSPS的ADC。差分输入电路之后、输出的差分基础放大信号,需经过检测64种差分电平的环节(同时有64个差分放大器转换为单极信号),编码环节(逻辑编码为6位);这应该就是6位的GHZ级高速ADC原理,想达到20GHZ级的ADC也是可以的、取决于差分放大器的IC工艺。第一级差分放大多少倍?输出串接64个电阻分压、再经过第二级差分放大检测64种差分电平的环节(同时有64个差分放大器转换为单极信号),编码环节(逻辑编码为6位)。相位调制2位:157.5度、180度、202.5度、225度,移相检测下降沿。我一个“散装业余玩家”,没条件去做实验,国内应该加大研究力度。
使用连续过采样,理论上可以采集40GHZ或更高的T级HZ周期信号;而这需要延迟模块 (DLYB), 用于生成内部输出时钟、使其与输入时钟存在相位偏移;ECO内部时钟采样线(上升沿采样、下降沿出结果)为经过延迟模块 (DLYB)的高清定时器HRTIM采样周期输出,从而“非过零触发”过采样高速周期信号。这样,一对差分线就可作为高速ADC或高速DAC,通过256位内部设备总线DB(Device bus)连接到缓冲区或DDR主内存:主频2GHZ,速度64GB(字节)/S,DDR5.0双通道速度51.2GB(字节)/S。

⚫跳变沿过补偿:比如差分驱动电源是1.8V,弄个开关管、上半桥在跳变沿瞬间接通3.3V电源(不用担心过电流、线路上等效串联电阻有2*100欧的)约30ps;因为哪一个瞬间、下半桥的下臂还没断开(有死区时间的)上臂也没导通,之后、即使存在下半桥上下臂导通的情形,而时间太短暂、功耗也可忽略不计;即使存在下半桥上下臂都断开的情形,电流也可以通过下半桥上臂二极管流到1.8V电源。这样做的因素,就是使得接收端的100欧电阻跳变哪一瞬间有相对较大的电流,线路电容影响减弱;终是使得跳变沿的斜率变陡峭,可以走更高的符号频率、如8GHZ,或许64Gbps可以实现。至于接收端的高频补偿,那是差分放大器之工艺实现。上下半桥是差分相对的!

d、双端并口类/dev/depp(double ended parallel port)/:

我们需要尽量简化和清晰表述物理层,PCIe 5.0显然不符合要求;高速同步串行通信无非是一对差分接收和一对差分发送,与SPI是类似的,也可以是半双工的2对差分接收或差分发送;直接数字通信模式:考虑DC 平衡、同步时钟嵌入在收发信号中,需8b/10b编解码或128b/132b编解码或128b/130b编解码;而用QAM256等差分模拟ADC/DAC数字调制通信模式,可实现更为高速可靠的同步通信,使用差分同步符号时钟信号CLK+、CLK-。

多对差分接收或差分发送就构成了各种双端并口,将来大多会用多路QDSPI数字调制差分同步串行设备接口,共用一对差分同步符号时钟信号、有多路差分接收对信号或差分发送对信号。机械物理接口或DP或HDMI插头插座不变,但差分对信号、可以是直接数字通信模式或QDSPI模式。

1)、PCI总线已经发展到PCI-Express时代,这是一个串行高速直接数字通信模式总线,分为X1、X2、X4、X8、X12、X16和X32七种模式;X1模式有2对差分线,1对收1对发,X2模式有4对差分线,2对收2对发,其它类推。
PCIe 1.0 x1,1组2对差分线(1对收1对发)全双工速率共为2.5Gbps(250MB/S),8/10b编码;
PCIe 2.0 x1,1组2对差分线(1对收1对发)全双工速率共为5Gbps(500MB/S),8/10b编码;
PCIe 3.0 x1,1组2对差分线(1对收1对发)全双工速率共为8Gbps(1GB/S),128/130b编码;
PCIe 4.0 x1,1组2对差分线(1对收1对发)全双工速率共为16Gbps(2GB/S),128/130b编码;
PCIe 5.0 x1,1组2对差分线(1对收1对发)全双工速率共为32Gbps(4GB/S),128/130b编码;

DDR5.0内存、单颗Die的容量达到64Gb,工作电压低至1.1V;On-die ECC纠错机制,双32位寻址通道的引入,每通道32/40位(ECC)、增加预取的Bank Group数量以改善性能等;另外在DDR5中RCD每侧提供四个输出时钟,允许每组5个DRAM(单等级、半通道)接收独立时钟,其大大提高了信号的完整性,有助于解决因降低VDD而产生的较低噪声问题;DDR5.0内存使用PCIe 5.0 x32分为双通道PCIe 5.0 x16,全双工速率共为2*16*32Gbps(128GB/S)。

SDRAM在一个时钟周期内只传输一次数据,它是在时钟的上升期进行数据传输;而DDR内存则是一个时钟周期内传输两次数据,它能够在时钟的上升期和下降期各传输一次数据,因此称为双倍速率同步动态随机存储器(Double Data Rate SDRAM)。内存控制器与DDR内存模组之间是点对点(P2P)的关系(单物理Bank的模组),或者是点对双点(Point-to-two-Point,P22P)的关系(双物理Bank的模组),从而大大地减轻了地址/命令/控制与数据总线的负载。DDR内部的最小存储单元(1bit)是一个晶体管+一个电容,电容会放电,需要不断的“刷新”(充电)才能保持正常的工作状态,由于电容充放电需要时间,DDR内部的频率受限于此,很难提高,目前技术一般在100~200MHz。因此需要用Prefetch技术来提内部数据高吞吐率(其实就是串并转换原理);Prefetch位宽的提高,是DDR2,3,4非常显著的变化。DDR1---DDR4使用的是单端通信技术,也就是灵活FMC:/DDR4/LPDDR4/DDR3/DDR3L/LPDDR2/LPDDR3/NAND Flash/PSRAM,到DDR4内存将会是Single-endedSignaling( 传统SE信号)方式与DifferentialSignaling( 差分信号技术 )方式并存。

将来的SDRAM主内存会作为内存模块而存在,类似SDMMC卡之类的模组;内存模组与主CPU芯片通过PCIe 5.0 x32或者QDSPI x32来作为通信连接(通信总线传输地址、数据、控制命令信号),大幅简化主CPU芯片的内存控制器之复杂性;至于“刷新”、预取Prefetch、等等,在模组内实现。使用QDSPI x32全双工或半双工通信,若差分同步符号时钟信号CLK+、CLK-调整为4GHZ,则DDR7.x(暂取名称)内存通信速率可达到2*16*64Gbps(256GB/S)。

2)、多用途DP/eDP(DisplayPort / Embedded DisplayPort)插座20P(DP或mini DP):全双工或半双工通信模式。4对高速差分信号线,1对差分同步符号时钟信号线或类似RS485模式或USB2.0模式的双向半双工AUX(D+、D-)收发差分线;类同PCIe5.0X2,最大速度64Gbps(8GB(字节)/S)。可作为eDP或Dual MIPI_DSI_TX或LVDS_TX的4对视频输出差分信号、最大速率为4*16Gbps(8GB/S),或作为MIPI_CSI_RX的4对差分CAMERA输入(可以是双路摄像头)、最大速率为4*16Gbps(8GB/S)。
P1、ML_Lane0(p)    通道0正端        等效对应PCIe5.0X2的    PCIe_TX0P
P2、GND        屏蔽地
P3、ML_Lane0(n)    通道0负端        等效对应PCIe5.0X2的    PCIe_TX0N
P4、ML_Lane1(p)    通道1正端        等效对应PCIe5.0X2的    PCIe_RX0P
P5、GND        屏蔽地
P6、ML_Lane1(n)    通道1负端        等效对应PCIe5.0X2的    PCIe_RX0N
P7、ML_Lane2(p)    通道2正端        等效对应PCIe5.0X2的    PCIe_TX1P
P8、GND        屏蔽地
P9、ML_Lane2(n)    通道2负端        等效对应PCIe5.0X2的    PCIe_TX1N
P10、ML_Lane3(p)    通道3正端        等效对应PCIe5.0X2的    PCIe_RX1P
P11、GND    屏蔽地
P12、ML_Lane3(n)    通道3负端        等效对应PCIe5.0X2的    PCIe_RX1N
P13、GND    屏蔽地
P14、GND
P15、AUX_CH(p)     辅助通道正端    定制aux口、或差分同步符号时钟信号CLK+
P16、GND    屏蔽地
P17、AUX_CH(n)    辅助通道负端    定制aux口、或差分同步符号时钟信号CLK-
P18、Hotplug Detect(HPD)热插拔检测信号、单向通道,用于检测与实现线路的连接和中断。
P19、DP_PWR Return 接头电源返回
P20、DP_PWR 接头电源(+3v、等)

3)、多用途HDMI(High Definition Multimedia Interface 高清多媒体接口)插座19P(HDMI或mini HDMI):主要作为显示器接口,也可作为全双工或半双工通信模式扩展接口。
P1、TX2+        通道2正端        等效对应ML_Lane2(p)    
P2、GND        屏蔽地
P3、TX2-        通道2负端        等效对应ML_Lane2(n)
P4、TX1+        通道1正端        等效对应ML_Lane1(p)    
P5、GND        屏蔽地
P6、TX1-        通道1负端        等效对应ML_Lane1(n)
P7、TX1+        通道0正端        等效对应ML_Lane0(p)
P8、GND        屏蔽地
P9、TX1-        通道0负端        等效对应ML_Lane0(n)
P10、CLK+    通道3(时钟)正端    等效对应ML_Lane3(p)
P11、GND    屏蔽地
P12、CLK-    通道3(时钟)负端    等效对应ML_Lane3(n)
P13、CEC(consumer electronic control),供厂家自己定制HDMI消息扩展功能
P14、HEC数据- 或保留    等效对应DP_PWR Return 接头电源返回
P15、I2C_SCL    等效对应AUX_CH(p)     辅助通道正端、或差分同步符号时钟信号CLK+
P16、I2C_SDA    等效对应AUX_CH(n)    辅助通道负端、或差分同步符号时钟信号CLK-
P17、GND    DDC/CEC/HEC地
P18、+5V        等效对应DP_PWR 接头电源(+3v、等)
P19、HPD    Hotplug Detect(HPD)热插拔检测信号,HEC数据+。

e、无线通信接口类/dev/wcp(wireless communication port)/:
通常是半双工通信、一个天线模拟引脚。

1)、BT(BlueTooth 蓝牙)/WIFI无线局域网(WLAN)合一接口:Wi-Fi与BT蓝牙技术一样,同属于短距离无线技术,需先建立连接;网络传输标准协议复杂,工作在ISM2.4GHz公共频段(Wi-Fi的工作频段通常为2.4 GHz和5 GHz ISM)。BT蓝牙技术:低成本、低功耗的数据和语音传输,是无线局域网(WPAN)的主流技术之一;工作标准基于IEEE802.15.1,工作频段在2.4GHz,信道带宽1MHz,连接距离小于10m;兼容性和抗干扰能力较差,传输距离较短,有经典蓝牙 (Bluetooth Classic,或BR/EDR))和低功耗蓝牙 BLE(Bluetooth LE)。wifi标准802.11 a/b/g/n/ac/ax对应 WiFi1/2/3/4/5/6,WiFi 1/2/3:速率为1---54Mbps,在5.8GHz频段最高速率54Mbps,在2.4GHz频段速度为1Mbps—11Mbps;WiFi 4速率为6.5---600Mbps,WiFi 5速率为6.5---6933.3Mbps,WiFi 6速率为1---9600Mbps。

2)、Zigbee短距低功耗简洁无线“接力”通信接口:IEEE 802.15.4 协议,协议简单、低复杂度、自组织、低功耗5mA,主要适合用于自动控制和远程控制领域的各种嵌入设备;传输距离50-300M,最大速率250kbps,可自组网、网络节点数最大可达65000个。类似现有移动通信的CDMA网或GSM网,一个ZigBee的子网络最多包括有255个ZigBee网路节点,其中一个是主控(Master)设备(集中器或说全功能设备FFD(Full-Function Device)),其余则是从属(Slave)设备(精简功能设备RFD(Reduced-Function Device)、采集器);通过网络协调器(Coordinator、或说FFD)自动建立网络,采用载波侦听/冲突检测(CSMA-CA)方式进行信道接入,实际上就是“集中、接力中转”的自组网模式。设备搜索时延一般为30ms,休眠激活时延为15ms,活动设备信道接入时延为15ms;由于工作时间较短、收发信息功耗较低且采用了休眠模式,使得ZigBee节点非常省电。发送的每个数据包都必须等待接收方的确认信息,并进行确认信息回复;若没有得到确认信息的回复就表示发生了碰撞,将再传一次,提高系统信息传输的可靠性。采用ZigBee技术的产品可以在2.4GHz(QPSK调制技术)上提供250kbit/s(16个信道)、在915MHz(BPSK调制技术)提供40kbit/s(10个信道),AES-128 加密算法。

这样,以上设备文件目录有:
USART(SWPI/TWI/I2C/UART/UARTMPC/UART Modbus/SPI/SCI/IrDA/RS232/RS485/SCAN/SPDIF),QSPI/SDIO/SDMMC,SPI24/LDTC/DCMI,FMC/DDR4/LPDDR4/DDR3/DDR3L/LPDDR2/LPDDR3/NAND Flash/PSRAM,USB2.0/AUX/RS485,USB3.x/UFS3.x/SSD3.x/RJ45,DP/eDP/HDMI/PCIe5.0 x2,DDR7.x,BT/WIFI/Zigbee。

建议:取消SPI24/LDTC/DCMI和FMC/DDR4/LPDDR4/DDR3/DDR3L/LPDDR2/LPDDR3/NAND Flash/PSRAM,可节省大量I/O线,简化主CPU的芯片设计;设置USB2.0接口2--3个,也可作为AUX或RS485接口;作为QDSPI x1技术的USB3.x外部接口则有2--3个、UFS3.x/SSD3.x等板级接口若干;作为QDSPI x2技术的DP/eDP/HDMI/PCIe5.0 x2接口2--3个,QDSPI x32技术的DDR7.x一个;USART板级接口6个以上,SDMMC板级接口有2个、其中一个分解为2个QSPI/2*I2S/SDIO,BT/WIFI/Zigbee板级接口1个。

❏时间类/dev/time/:

1)、复位和时钟控制RCC(Reset and clock control )
复位模块:
a、复位类型:上电/掉电复位(pwr_por_rst)由电源控制器模块 PWR 生成(它在输入电压 VDD 低于阈值电压时激活),系统复位nreset可将所有寄存器均复位为其默认值,本地复位(CPU 软件设置复位,退出待机模式DStandby 时的域复位)。
b、系统复位信号源:
 通过 NRST 引脚复位(外部双向引脚复位,可复位微处理器或外部器件)
 通过上电/掉电复位模块 (pwr_por_rst) 复位
 通过欠压复位BOR模块 (pwr_bor_rst) 复位
 通过独立看门狗 (iwdg1_out_rst) 复位
 通过 CPU 内核实现软件复位SFTRESET
 通过窗口看门狗复位,具体取决于 WWDG 配置 ( wwdg1_out_rst )
 通过低功耗模式安全复位实现复位,具体取决于选项字节配置 ( lpwr[2:1]_rst )
某些内部复位源(例如 pwr_por_rst、pwr_bor_rst、iwdg1_out_rst)可执行电路的系统复位,这也会传播到 NRST 引脚以复位其连接的外部器件。脉冲发生器可确保每个内部复位源的复位脉冲都至少持续 20 µs。对于外部复位,在 NRST 引脚处于低电平时产生复位脉冲。
c、复位时序:从复位到 CPU 能执行代码的时间间隔取决于系统状态及其配置,先复位外设,再复位核心。

RCC 时钟模块:
HSI(高速内部振荡器)时钟:~ 8 MHz、16 MHz、32 MHz 或 64 MHz,无需外部晶振、启动时间更短(几微秒),即使经频率校准、精度略低。
HSE(高速外部振荡器)时钟:4 MHz --- 48 MHz,外部晶振/陶瓷谐振器、外部时钟源。
LSE(低速外部振荡器)时钟:32 kHz,外部晶振/陶瓷谐振器、外部时钟源,主用于RTC。
LSI(低速内部振荡器)时钟:~ 32 kHz,供独立看门狗 IWDG 和自动唤醒单元 AWU 使用。
CSI(低功耗内部振荡器)时钟:~ 4 MHz,
HSI48 (高速 48 MHz 内部振荡器)时钟:~48 MHz,主用于通过特殊时钟恢复系统 CRS 电路为 USB 外设提供高精度时钟。
时钟输出生成 (MCO1/MCO2):2个时钟输出 (MCO) 引脚,每个输出带预分频器的时钟源。
8---12路的PLL:内核时钟、各种总线时钟、各种外设时钟。

2)、时钟恢复系统 CRS(Clock recovery system):一个作用于内部精细粒度可调 RC 振荡器 HSI48 的高级数字控制器。
CRS可通过与可选同步信号进行比较来评估振荡器输出频率,能够根据测得的频率误差值自动调整振荡器微调,同时还可以进行手动微调。CRS 非常适合为 USB 外设提供精密时钟。在这种情况下,同步信号可由 USB 总线上的帧起始 (SOF) 数据包信号提供,USB 主机以 1 ms 的时间间隔精确发送该信号。同步信号也可由 LSE 振荡器输出提供,或者由用户软件生成。

3)、电源控制PWR(Power control):不同电源域(内核域 (V_CORE ,VDD 域,备份域V_SW 和V_BKP,模拟域 VADD,VREF 、ADC 和 DAC的外部参考电压)的电源架构以及电源配置控制器。 电源架构与配置:LDO稳压器、USB 稳压器, 电源监控:POR/PDR监控器、BOR监控器、PVD监控器、 AVD监控器、 VBAT 电池阈值监控、VBAT电池充电控制,电压调节控制、低功耗模式,温度监测。

4)、时间戳定时器TST(timestamp timer ):1路PLL产生4.294967296GHZ的时钟(也可以是x.xxGHZ)、32位可编程预分频器驱动的递增自动重载计数器,多达 4 个独立输出比较通道,可用于生成内部时基;其中一路产生标准1秒时钟输出到RTC模块,也可以程控连接到MCO1/MCO2引脚为外部提供标准1秒时钟;另外三路的单脉冲模式比较输出还可连接到延迟模块 DLYB,产生“非过零触发”过采样高速周期信号时钟,作为驱动数模转换器DAC或模数转换器ADC的时基信号。

延迟模块 DLYB(Delay block) 用于生成输出时钟,其与输入时钟存在相位偏移。首先必须通过用户应用程序对输出时钟的相位进行编程。然后,输出时钟用于对由另一个外设 (例如 SDMMC 或QUADSPI 接口、等等)接收的数据进行计时。该延迟与电压和温度相关,可能需要重新配置应用程序和重新确定输出时钟与接收数据之间的相位关系。

5)、通用控制定时器UCT(Universal control timer):
通用控制定时器包含一个 16 位递增或递减或递增/递减自动重载计数器,该计数器由可编程预分频器(分频系数介于 1 到 65535 之间)驱动。它们可用于测量输入信号的脉冲宽度( 输入捕获 )或生成输出波形( 输出比较和 PWM、带死区插入的互补 PWM)。使用定时器预分频器和 RCC 时钟控制器预分频器,可将脉冲宽度和波形周期从纳秒或皮秒级调制到毫秒级。多达 4 个独立通道,可用于:输入捕获、或输出比较、或PWM 生成(边沿和中心对齐模式)、或单脉冲模式输出、或带可编程死区的互补输出。使用外部信号控制定时器且可实现多个定时器互连的同步电路,重复计数器、用于仅在给定数目的计数器周期后更新定时器寄存器,2 个断路输入、用于将定时器的输出信号置于用户可选的安全配置中。支持定位用增量(正交)编码器和霍尔传感器电路,触发输入用作外部时钟或逐周期电流管理。芯片通常集成多个UCT,主要应用:输入信号脉冲宽度检测,开关电源,三相电机控制,音响数字直推功放电路。计数时钟频率最大8GHZ,定时器分辨率125ps。
发生如下事件时生成中断请求:
更新:计数器上溢/下溢、计数器初始化(通过软件或内部/外部触发),触发事件(计数器启动、停止、初始化或通过内部/外部触发计数),输入捕获,输出比较。

6)、实时时钟RTC(real-time clock):
实时时钟 RTC 提供用于管理所有低功耗模式的自动唤醒单元。
实时时钟 RTC 是一个独立的 BCD 定时器/计数器,RTC 提供具有可编程闹钟中断功能的日历时钟/日历。两个 32 位寄存器包含 BCD 格式的秒、分钟、小时(12 或 24 小时制)、星期几、日期、月份和年份;此外,还可提供二进制格式的亚秒值;可以自动将月份的天数补偿为 28、29(闰年)、30 和31 天,软件可编程的夏令时补偿;其它 32 位寄存器还包含中断功能的可编程闹钟亚秒、秒、分钟、小时、星期几和日期,可通过任意日历字段的组合触发闹钟;此外,还可以使用数字校准功能对晶振精度的偏差进行补偿。
RTC 还包含具有中断功能的周期性可编程唤醒标志。备份域复位后,所有 RTC 寄存器都会受到保护,以防止可能的非正常写访问。无论器件状态如何(运行模式、低功耗模式或处于复位状态),只要电源电压保持在工作范围内,RTC 便不会停止工作。带可配置过滤器和内部上拉的入侵检测事件, 32 个备份寄存器。

标准1秒时间戳输入RTC_TSI,64位正负秒数递增可重载计数器;它们以1970年1月1日(unix元年)表示为0,正数表示之后至今的秒数,最大表示约2147.5亿年;负数表示之前的秒数,最小表示约负2147.5亿年。

7)、独立看门狗 IWDG( Independent watchdog ):
由专门的 32Khz (内部 RC 低精度阻容时钟,喂狗时应该给出一定的裕量)低速内部时钟LSI(Low speed internal clock)驱动一个独立定时器来计时,一旦看门狗超时、系统来不及存储当前运行状态就会重启;可以在要求不高的场合使用,即使主时钟发生故障,它也仍然有效。在一段代码开始前、使能看门狗,如果“程序跑飞”(代码以及硬件设计缺陷或是外界电磁干扰、使之无法正常运行到该段代码后面的喂狗指令),看门狗计时时间到将导致系统复位,从而保证系统不会死机(重新运行)。

8)、系统窗口看门狗 WWDG(Window watchdog):
用来监测由外部干扰或不可预见的逻辑条件造成的应用程序背离正常的运行序列而产生的软件故障。窗口看门狗WWDG的计数器在窗口值之外被刷新会产生复位,当WWDG的计数器值减到窗口下限值的时候,可以产生中断;进入WWDG中断服务函数,可进行一些必要的操作,比如清中断、保存数据……等关键操作、或重新喂狗;自然的、喂狗要快,否则当窗口看门狗计数器值再减1时、就会引起软复位了。WWDG用系统内部高速时钟源比较精确。

9)、IRM中断请求模块(interrupt request module):
嵌套向量中断控制器 NVIC (Nested Vectored Interrupt Controller ),用于为中断分组,从而分配抢占优先级和响应优先级,包含以下特性:
■支持 256 个中断,中断(interrupt)是一种特殊的异常(exception)。中断编号为 0-15,专用于系统异常;所有其他中断(即 16-255)称为用户或外设中断IRQ。由外设产生的中断信号,除了 SysTick的之外,全都连接到 NVIC的中断输入信号线。除了个别异常的优先级被定死外,其它异常的优先级都是可编程的,用一个中断向量表管理起来。把编号从-3至6的中断向量定义为系统异常,编号为负的内核异常不能被设置优先级,如复位(Reset)、不可屏蔽中断 (NMI)、硬错误(Hardfault)。从编号 7开始的为外部中断,这些中断的优先级都是可以用户更改的。
■最大16 个可编程抢占式优先级(使用了 4 位中断抢占式优先级(NVIC_IRQ Channel Preemption Priority)),从而表示中断优先级的分组。抢占优先级值越小,优先级越高;具有高抢占式优先级的中断可以在具有低抢占式优先级的中断处理过程中被响应,即中断嵌套,或者说高抢占式优先级的中断可以嵌套低抢占式优先级的中断,相同抢占优先级的中断不能嵌套。
■最大16 个可编程响应优先级(使用了 4 位中断响应优先级(NVIC_IRQ Channel Sub Priority),或称作‘子优先级’、'亚优先级'、或'副优先级'),每个中断源都需要被指定抢占式优先级和响应优先级。当两个中断源的抢占式优先级相同时,这两个中断将没有嵌套关系;当一个中断到来后,如果正在处理另一个中断,这个后到来的中断就要等到前一个中断处理完之后才能被处理;如果这两个中断同时到达,则响应优先级值越小的中断首先执行(不能嵌套);如果他们的抢占式优先级和响应优先级都相等,则根据他们在中断向量表中的排位顺序决定先处理哪一个,向量表中越靠前的中断先响应。
■低延迟异常和中断处理,晚到中断的高效处理,中断屏蔽,向量化的异常入口。
■电源管理控制(power supply control)。
■系统控制模块(SCB)的实现。系统控制空间(SCS)中包含了许多系统管理的映射到系统地址空间的寄存器,有些寄存器控制休眠模式和系统异常配置,另外还有个寄存器中包含了处理器的识别代码(调试器可以使用该代码识别处理器的类型),一些可编程寄存器控制着中断管理功能。
■每个配置为输入方式的GPIO引脚都可以配置成外部中断/事件方式EXTI,每个中断/事件都有独立的触发和屏蔽,触发请求可以是上升沿、下降沿或者双边沿触发。一些EXTI线的连接方式可为:连接到PVD中断,连接到RTC闹钟中断,连接到USB唤醒中断,连接到以太网唤醒中断,等等。

■256位内部设备总线DB(Device bus):主频4GHZ,速度128GB(字节)/S,DDR7.x双通道速度256GB(字节)/S。专门一个多核管理:空间管理员Sadm(APU多核结构、内存空间MMU管理),含外部DDR7.x总线单通道A的IP核。
各种设备都视为大小不一的统一映射到系统地址空间的收发兵乓FIFO(First In First Out)缓冲区(256位/32字节一个单元,缓冲区:1--n个单元),设备处理完一个FIFO缓冲区后、转到另一个FIFO缓冲区工作并发出中断,Sadm对相应设备发送片选和初始地址、再读或写处理完的FIFO缓冲区,之后将处理后的相应数据读或写到DDR主存。Sadm的一小部分工作量就是:设备与DDR主存的等效DMA传输,其它CPU节点与DDR主存的数据包传输。

这样一来,统一了各种设备的物理层驱动;不同的设备(不管是高速、低速、千奇百怪,还是各类多核单元),都统一视作对设备之FIFO缓冲区以及DDR主内存的设备相应区域之内存操作(多核单元是独立物理内存区,但都对应到相应的虚拟内存空间)!没有DMA传输了,已经被空间管理员Sadm代替;硬件中断也是极大地被弱化,转化到各个多核单元的是“中断消息包”。简单说:DMA和中断都是存在的,但已是系统硬件统一处理了,编写操作系统时、无需过多考虑;万千设备物理层驱动程序归化为一,不同的设备物理层驱动程序、其不同点只是在DDR主存的设备初始地址和长度以及设备配置寄存器的副本(正本自然是初始化时、已写在设备的配置寄存器组内)。将设备看作文件,设备物理层驱动程序需有“设备文件操作接口”;linux、windows、等等操作系统,对不同的设备需编写不同的设备驱动程序,这是它们千万行以上代码量的原因!AOS的物理层驱动程序会有多少代码量?估计就几十行!AOS的设备物理层驱动程序是一个“设备物理层驱动代码类A”、只有一份,不同设备的物理层驱动程序是A的具体对象、只是有不同的“内存”属性;这样,会形成各种设备的“内存”属性表,我们可以用“网页”来对各种设备动态配置,甚至可以显示芯片引脚的动态配置图像,这就是“生态环境”;STM32单片机在这方面就做得比较好,其对程序员的亲和度较高、编程“生态环境”很好。

设备物理层驱动程序之上是各种设备协议层驱动程序。OSI模型是分层方法中的一种通用功能划分方法,OSI模型分为七层:
a、物理层:
主要对物理连接方式,电气特性,机械特性等制定统一标准,传输“位(比特)流”;如网线的接口RJ类型、光纤的接口类型、各种传输介质的传输速率,FIFO缓冲区及配置控制寄存器的初始地址和大小、时钟、中断、模式、等配置与控制。设备物理层为软硬件实现,设备物理层之上通常是协议层驱动程序的软件实现。连续的位流或连续的帧或连续的数据包就称为数据流Data stream(也可以m帧为一个数据包DPK(Data packet)),有2种相对方向的数据流,数据流输入DSI(Data stream input),数据流输出DSO(Data stream output);物理层往上层走称为数据流输入DSI,反之、称为数据流输出DSO。有单向输入或输出的设备,也有双向通信的设备。从设备输出数据流DSO、自然会有明确的相关上层协议驱动程序操控,问题是从设备进入的数据流输入DSI该走那一条道路?如果从WIFI来了一个数据帧(它可能是键盘数据、也可能是鼠标信息、也可能是话筒信号数据)、那么该是给上层的谁负责?又比如SPI口、它可能接收到的数据帧、或许是音频数据包也或许是FLASH数据、也可能是以太网MAC格式数据包、等等,AOS应该如何应对?我们需要一个24位的“流标识”符、来表述进入帧所代表的数据流输入DSI(键盘、鼠标、MAC、SATA3.0磁盘数据、USB2.0、USB3.0、音频、视频、视音频、等等)。我们需要尽量简化和清晰表述物理层,而各类信号的帧(或包)长是不一样的、实时性要求不一样,不一定能用定长的FIFO去规划。是故,FIFO缓冲区设计为也可以用指定地址去读写缓冲区,实时帧会有一个中断位,如果收到这种实时帧、硬件会发出中断,让空间管理员Sadm读往DDR并运行相关驱动;高速串行通信端口一个帧最少为一个单元256位,帧头必须有24位“流标识”符、24位实际有效字节数(实际只是21位、2MB,最高位乃中断位、其余2高位备用)和16位帧长度(单元数)。24位“流标识”符:第一个字节、数据流类型,第二个字节、协议规则(压缩标准(低4位)、源接口等等)、第三个字节、数据流通道(最高位1输入,0位输出)。比如:音频数据流ADS_MP3_USB2.0_LIN3,MP3压缩来源USB2.0接口的音频数据流第三输入左通道,文件数据流FDS_N_SATA3.0_文件动态通道号(文件号等信息在协议内表示)。数据流类型通常有:音频流、视频流、视音频混合流、文件流、MAC网络数据流(里面又包含各种数据流)、分离后的二级流、中间数据流、中间混合流、AI流、原始流、等等,具体有待规划。

任一个层驱动程序,我们都可以抽象出一个最多三端口的层驱动模型:连接上层的数据流端口CULDSP(Connect the upper level data stream port),连接下层的数据流端口CLLDSP(Connect the lower level data stream port ),连接文件操作的控制流端口CFOCSP(Connect the file operations control stream port )。没有上层时,就只有CFOCSP和CLLDSP;物理层的下层就是位流数据,也只有2层、CULDSP和CFOCSP。编写AOS应用程序,就是画图、画出数据流程图!其编程“生态环境”就是“网页画图”、可以用“C#、VB、C++、JAVA、等等”高级语言制作“编程生态环境”。应用程序(巨大的虚拟空间):进程(主线程)模块、线程模块,控制流模块,应用程序数据流协议驱动模块,设备数据流驱动模块(物理层驱动、各种协议层驱动);用线将各种模块连接就构成了应用程序,除公用模块外、应用程序的各种模块,“编程生态环境”都会生成模块程序框架,程序员在程序框架内用C语言编写相应模块程序。模块就是一种方法类库,应用程序专有的就是动态库;公用的是AOS自带的标准类库(设备驱动库、标准方法库),用户可以酌情用“网页”选择安装。应用程序数据流协议驱动模块或许会有多个数据流输入DSI和多个组合变换后的中间混合数据流输出DSO,设备数据流协议驱动模块的CFOCSP也可能连接多个应用程序、如键盘鼠标数据流(但更新信息还是发给焦点应用程序为主)。
b、数据链路层:
该层的作用包括了物理地址寻址(如媒体访问控制MAC地址的封装和解封装),数据的成帧,流量控制,数据的检错,重发等。为了保证传输,从网络层接收到的数据被分制成特定的可被物理层传输的帧。由n位比特bit构成帧,n是多少得看具体协议;帧是n位比特的数据结构,它不仅包括原始数据,还包括发送方和接收方的物理地址以及纠错和控制的信息。其中的地址确定了帧将发送的位置,纠错和控制信息则保证帧的准确到达。如果传送数据的过程中,接收点检测到数据有错误,就通知发送方重新发送这一帧。交换机就处在这一层,最小的传输单位——帧。
c、网络层:
控制子网的运行,如逻辑编址,分组传输,路由选择最小单位——分组(包)报文IP地址工作在OSI参考模型的第三层网络层。两者之间分工明确,默契合作,完成通信过程。IP地址专注于网络层,将数据包从一个网络转发到另外一个网络;而MAC地址专注于数据链路层,将一个数据帧从一个节点传送到相同链路的另一个节点。
d、传输层:
定义了一些传输数据的协议和端口号(WWW端口80等),如:TCP(传输控制协议,传输效率低,可靠性强,用于传输可靠性要求高,数据量大的数据),UDP(用户数据报协议,与TCP特性恰恰相反,用于传输可靠性要求不高,数据量小的数据,如QQ聊天数据就是通过这种方式传输的), 主要是将从下层接收的数据进行分段和传输,到达目的地址后再进行重组,常常把这一层数据叫做段。传输协议同时进行流量控制,或是根据接收方接收数据的快慢程度,规定适当的发送速率,解决传输效率及能力的问题。
e、会话层:
通过传输层(端口号:传输端口与接收端口)建立数据传输的通路,主要在你的系统之间发起会话或者接受会话请求(设备之间需要互相认识可以是IP也可以是MAC或者是主机名)。维持和终止通信,在一层协议中,可以解决节点连接的协调和管理问题。
f、表示层:
确保一个系统的应用层发送的消息可以被另一个系统的应用层读取,编码转换,数据解析,管理数据的解密和加密。例如,PC程序与另一台计算机进行通信,其中一台计算机使用扩展二一十进制交换码(EBCDIC),而另一台则使用美国信息交换标准码(ASCII)来表示相同的字符。如有必要,表示层会通过使用一种通格式来实现多种数据格式之间的转换。
g、应用层:
是最靠近用户的OSI层,这一层为用户的应用程序(例如电子邮件、文件传输和终端仿真)提供网络服务。

不同设备的时钟不一样,从而速度也不一样,单端IO口最大翻转速度200MBPS。
FIFO(First In First Out) 是一种先进先出的数据缓存器;只能顺序写入数据,或顺序的读出数据,其数据地址由内部读写指针自动加1完成,不能像普通存储器那样可以由地址线决定读取或写入某个指定的地址。FIFO一般用于不同时钟域之间的数据传输。

❏模拟类/dev/analog/:

1)、逐次逼近式模数转换器 SAR_ADC(successive approximation register_Analog-to-Digital Converter)主要分成四个部分:采样保持电路、模拟比较器、SAR逐次逼近寄存器和DAC数字模拟转换器。
原理:从高位开始、逐位比较,取一个数字量加到DAC上,于是得到一个对应的输出模拟电压;将这个模拟电压和输入的模拟电压信号相比较,如果两者不相等,则调整所取的数字量;直到两个模拟电压相等为止,最后所取的这个数字量就是所求的转换结果。比较过程正如同用天平去称量一个未知重量的物体时所进行的操作一样,而所使用的砝码一个比一个重量少一半。
逐次逼近模数转换器是采样速率低于5Msps的中高分辨率ADC应用的常见结构,SAR式ADC的分辨率一般为8-16位;具有低功耗,小尺寸等特点。
如果是n位输出的ADC,则完成一次转换的所需的时间将为n+1个输入时钟周期,采样时间通常为3个输入时钟周期;如果ADC 时钟周期2倍于输入时钟周期,例如16位ADC结果的情形,则ADC转换时间为8.5个ADC 时钟周期、采样时间为1.5个ADC 时钟周期,总共10个ADC 时钟周期。

SAR_ADC模块特点:
多达 3 个 ADC,ADC1 和 ADC2可在双重模式下运行;可配置 16 位、14 位、12 位、10 位或 8 位分辨率,可通过降低分辨率来缩短转换时间;可管理单端输入或差分输入(可按通道进行编程),自校准(偏移校准和线性度校准);可独立设置各通道采样时间,多达四条注入通道(对常规通道或注入通道的模拟输入分配完全可配置);每个ADC最多有16个外部通道(ADC1、ADC2)或内部通道(ADC3),芯片内部的温度传感器Vsense、内部参考电压Vrefint、V_BAT 监测通道 ( V_BAT /4 )、内部 DAC 通道 1 和通道 2、内部的 VSS、连接到了ADC3;每个ADC的FIFO 单元256位(16信道*16位),16信道可以配置为对应16个规则通道和注入通道、或其中某个或某几个通道;各通道的A/D转换可以单次、连续、扫描或间断执行,ADC转换的结果可以左对齐或右对齐储存在16位数据寄存器中;数据可连接到 DFSDM 进行后期处理,4 个专用数据寄存器供注入通道使用;每个 ADC 有 3 个模拟看门狗,ADC 输入范围:Vref– ≤ Vin ≤ Vref+;在 ADC 准备就绪、采样结束、转换结束(常规转换或注入转换)、序列转换结束(常规转换或注入转换)、模拟看门狗 1/2/3 事件或溢出事件时可设置生成中断。
模拟看门狗事件:当输入的模拟量(电压)不在阈值范围内就会产生看门狗事件,就是用来监视输入的模拟量是否正常。
ADC1 和 ADC2 的双重 ADC 模式:
通过 ADC1 主器件到 ADC2 从器件的交替触发或同时触发来启动转换。一个用途是ADC1 和 ADC2 交替转换同一通道以缩短转换时间,提高为2倍的采样速率;比如一个 ADC 的最大采样率为 1M/ 秒,使用双 ADC 快速交替模式,可实现 2M/秒的采样率。
使用连续过采样,理论上可以采集G级HZ周期信号;而这需要延迟模块 (DLYB), 用于生成内部输出时钟、使其与输入时钟存在相位偏移;ECO内部时钟采样线(上升沿采样、下降沿出结果)为经过延迟模块 (DLYB)的高清定时器HRTIM采样周期输出,从而“非过零触发”过采样高速周期信号。

2)、数模转换器 DAC(Digital-to-Analog Converter):
双输出通道12 位电压输出数模转换器,DAC 可以按 8 位或 12 位模式进行配置;每个DAC通道的16个信道数据可以采用左对齐或右对齐,每个通道可以单独进行转换与校准;当两个通道组合在一起同步执行更新操作时,也可以同时进行转换。
可以联合PWM实现更高精度、如24位的DAC输出。

3)、电压参考缓冲器VREFBUF:内部电压基准源,既可用作 ADC 和 DAC 的参考电压,也可通过VREF+ 引脚用作外部元件的参考电压。

4)、比较器 COMP:
应用于在模拟信号的触发下从低功耗模式唤醒,模拟信号调理,与定时器的 PWM 输出结合使用时,构成逐周期电流控制环路,等等。

5)、运算放大器OPAMP:
器件内置两个运算放大器,每个运算放大器具有两个输入和一个输出。可以将(这两个)运算放大器在内部配置为一个跟随器和一个放大器,放大器具有程控增益;正输入可连接到内部 DAC,其中一个输出可连接到内部 ADC。轨到轨输入和输出电压范围,低输入偏置电流(低至 1 nA),低输入失调电压(校准后为 1.5 mV,出厂校准时为 10 mV);7 MHz 增益带宽积,高速模式提供更高的压摆率。

❏辅助加速类/dev/aaa(Assistance and acceleration)/:

天气太热、无心工作,暂时修整几个月

待续...

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值