资讯详情

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

AOS与阿里的名字发生冲突,现在改为OACS;汇编对象语言OASM(Object assembly language),又带一点点C风格,改名为OACS、即是带一点C风格的汇编对象语言系统(Object assembly language C system)。相比之下,一切都是对象unix/linux一切都是文件,会显得更广;许多核心对象,如内存对象,CPU对象、IPC没有文件i节点的对象、线程对象等。c语言功能也很强大,但我认为使用好并不容易;在此期间,我阅读了许多嵌入式操作系统和相关源代码;给我的印象是,英语单词满天飞,对像我这样的小白不友好。许多缩写E文本没有给出E文本源单词,也很难查阅翻译软件;总是有一万多个函数,没有那么多时间仔细阅读。stm32f7xx_hal_rcc.c stm32f7xx_hal_rcc_ex.h stm32f7xx_hal_rcc.h三份文件近6000行,只是复位和时钟控制RCC一个小单片机30多个功能部件之一,必须大大简化!我相信用汇编语言编写单片机程序的老手不会同意使用HAL库的;估计十几行汇编代码的东东,却啰嗦地写成千行,你能忍受吗?反正我宁愿推倒重来。很多年前,我也用汇编写了单片机程序;编译后相当复杂的项目只有4个KB你现在看: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                                                               */   __I 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)对象

标签: 高精度陶瓷电容压力变送器二极管sp0402u二极管au2001p4二极管g4dts二极管微型可伸缩传感器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台