思维之海

——在云端,寻找我的星匙。

南国行记

本文记载深圳OS项目实习的一些见闻。

8月2日 向南

疫情后的湖北(宜昌),还是一种比较严肃的气氛。

似乎高速公路的通行上仍存在一定问题(这个问题应该存在了几年了),跨省界时需要转小型车,再转为宜昌交运客车。当地的客车似乎更高级一些,设备更新,座位有重力感应,这样与安全带插扣联合在一起,便可以保证安全带的使用——只是,空座位上确实不能放置物品了。

听说这几天深圳强降水,有些庆幸选择了高铁前往。如果是飞机,可能又要延误(之后发现确实有人延误。。)。我为数不多的飞行体验中,就有一次接近半天的延误。人们常常夸赞航班的超高安全性,但我却不以为然。飞机的安全性是通过全面“规避风险”来获得的,这意味着飞行本身是一件高风险的事。而火车或者汽车则不一样,它们的基础风险是很低的,它们规避风险的需求也更少。

但,“规避风险”是一件非常强调主观能力的事情。

窗外突然开始下雨。刮大风。并且能见度变得很低。可以在空中看到明显的风雨轨迹。隧道中的应急车道上停靠了大量避雨的私家车。但过了一段距离,雾渐散了。雨也消了。

看到崇山峻岭间有些鬼斧式的地貌。公路和车辆在森林中一闪而过。

人对自然的改造。也是脉络式的改造。

崇山峻岭也隐去了,平原,城市的轮廓浮现出来。

世界太大了。单独的人,单独的建筑,都显得很渺小。思维超出个体时,行为是否能超出个体呢?


高铁上可以明显感到与之前的交通工具在速度上的差异。出发时还是早晨,天气晴朗,云海只淡淡的一层,并形成起伏的波浪线。

没想到中途的站点竟经停武汉。

病毒的风险,何尝又不是一种主观能力上的风险规避。跟航班也有一些相似性。

体验了一把在高铁上点外卖的感觉。结论:太贵。

无论如何舒适的环境,坐久了都会变得不是很舒适。可能还不够舒适?


深圳的城市从宏观上跟北京之类的大都会没有什么区别。但是,细节之处却相当不同。深圳有专门的出租车集散地,这是我在其他省市所从未见过的,深圳的交通似乎更加严格,也许这是一种“先行区”的表现吧?深圳是一座很有活力的城市,从街景的设计中可以看出,一些蓝色的吉祥物(没有认出来是什么),还有雕塑。深圳的非机动车道和人行道镶嵌粘合在一起,这也是其他城市我所未见的新。深圳也许暂时我没有体味到创造的新,但是标新立异的新,确实令人侧目。

到了酒店,直观的感受就是,高端的生活方式真是难以想象的舒适。

室友是来自数学系的大佬,听说为了契合自己的计划,甚至故意挂了科从而可以留校留级。这种认知是反常的,然而在了解之后又立马显得十分自然。

8月3日 实验室

六点多醒了。悠哉游哉到鹏程实验室,脚程大约3分钟。

早餐自助。还是很好吃的。

安排也大致有了:https://github.com/rcore-os/zCore/wiki/zcore-summer-of-code。

今天大概是:rCore 开发历史和选题介绍。

与同学交流选题

上午11:00 B栋一楼合影,3楼参观

中午二楼就餐

晚上:聚餐和小活动

安排。:)


中午吃多了。。控制控制。。


第二届开源操作系统技术研讨会


没有做完实验的,先把前面六个实验全部做完。

操作系统的用户态、内核态的转换,在rust设计中得到了优化。通过异步的办法,让操作系统的性能有一个巨大的提升。(用户态中断?)

对于传统操作系统,异步的编写很麻烦。在rust中,则可以由编译器来负责完成。rust语言有可能对操作系统有一个本质性的影响。

信号:比如键盘信号,用户态的一个信号。信号处理函数在用户态,平时不激活。很诡异地一个设计,需要把很多东西凑合到一起。

RISC-V中有一个用户态中断。这件事完成后,那么就可以实现在用户态完成信号机制。


第二阶段没有什么参考,所以需要自己规划。

目的:做开源社区

明天下午国科大本科毕设分享:RISC-V处理器流片背后的故事。

对于树莓派,PCB开源但GPU不开源,ucore移植的图形显示很不好搞,图形渲染不好弄,只能弄图形点阵。

目前有一个对标树莓派的全开源项目,似乎。

周四去华为参观?

龙芯杯似乎有点内卷。。QAQ

我的树莓派4已经吃灰一年了感觉。。未来10年间主流指令集会从x86过渡到arm?


关于zCore-Tutorial的一些特点。自顶向下。逐步替换底层实现。


网络集群的特点就是,每个人都很有特点。这其实有点循环论证的问题。

大二的同学竟然有7位。不禁感叹时光流逝。当年我在大二时,大概才开始学习算法,那年的算法课我也不过是60分飘过。

开源协议赶紧再记一下:


今晚真的要聚餐

8月4日 一生一芯

今天迟到了。不过好像问题不大。匆匆吃完外带的早餐。

貌似github.io被墙了。

说实话zCore-Tutorial这个东西,现在想参与还是比较无力的。作者wrj本身也就写了一点点内容。但他把一些大纲拟好。

hal(硬件抽象层,Hardware Abstraction Layer),与硬件隔离。

目前支持裸机(Bare Metal),和Linux/Mac OS环境。

rust-analyzer听说很好用。clion听说很好用。

大概了解了一下zCore的结构。


进度资料:2019年操作系统专题训练大实验-Fuchsia OS调研。抽时间了解一下他们都做了些什么,以及进度。

关于Fuchsia OS:http://os.cs.tsinghua.edu.cn/oscourse/OsTrain2019/g1?action=AttachFile&do=view&target=%E5%BC%80%E9%A2%98%E6%8A%A5%E5%91%8A.pdf。

“非典型”微内核。(勉强算微内核)

Fuchsia是Google开发的,可能将用于取代Android。

rCore有实现微内核的潜力,这最终形成了zCore?

国科大本科毕设研讨会——“一生一芯”项目访谈

今天的研讨会终于给人比较正式的感觉。上午的自由讨论,最终只剩下自由,而没有讨论。

注意:一生一芯是指,每一个学生设计一个芯片。


介绍,开发经验,经历分享,未来展望。

余子濠、金越(验证测试)、王华强(前端/DEBUG)、王凯帆(核参数/应用)、张林隽(TLB)、张紫飞(微结构)

第一环节 介绍

  1. 芯片基本情况
    1. “果壳”,NutShell
    2. 一款功能完整的RISC-V处理器
    3. 国产110nm工艺完成流片(面积10 mm^2),流片一次二十万???
    4. 有对应的果壳板卡
    5. SDRAM大型内存操作系统只能跑200MHz。其他内存占用小的OS可以到350MHz。
      1. SDRAM中途还换了颗粒,一开始只能测试小程序最多128K左右
    6. 跑分一般
    7. 4个月的前端开发
    8. 自产自销QAQ
    9. 疫情原因,芯片测试并没有实际参与
    10. 第一版芯片电路(电源线)接错,取指成功,但是会烧掉板子(烧了两块,然后回厂)
  2. 现在回过头来看, 流片难吗?
    1. 五位同学主要接触的是前端设计的工作
      1. 与流片相关的工作:时序逻辑设计要求比较严格
    2. 流片的时间节点的压力比较大
      1. 如果之后有问题的话,无法修改
      2. 爆肝
    3. 王凯帆同学中途出国被反复鞭尸QAQ,他的一些软件任务由余博士完成
  3. 什么时候认识到项目的复杂性? 如何应对?
    1. 课程中老师常常把一些东西黑盒化,但是在项目中需要接触验证的环境(测试程序的正确性),DEBUG比较艰难——了解每一行代码的细节
    2. 加强版的龙芯杯QAQ版本管理很重要
    3. 前期可以黑盒,但后期必须了解硬件外设的细节,比如几千行的 verilog 代码
    4. 后期开始参与用户态使用时,感觉到复杂性。可能需要引入编程范式?
      1. 一步一步,任务驱动,一层一层慢慢解开黑盒
      2. 阅读大型项目的方法~~~

第二环节 开发

  1. 使用 Chisel 有什么感想?

    1. Scala (相对于 Rust)更强调函数式编程、面向对象编程
    2. Chisel 就是基于 Scala
    3. Chisel 描述硬件的语言方式是非常抽象高级的,Verilog 的抽象层次很低,可以视作“电路设计中的汇编语言”
    4. Chisel 里面 DEBUG 一般直接打印信息
      1. 传统看波形:通过信号周期(几千几万的那种)跟踪,太难了
    5. 有些功能 Chisel 解决不了或者实现会很复杂
      1. 多时钟可以搞,但是会更复杂一点
      2. DDR的复杂度很高,Contrler很难搞
        1. CPU和SDRAM的时钟频率不一样,需要转换桥?
  2. 使用chisel如何调试?

    1. 处理器在线差分测试仿真验证
      1. nemu是一个简版的qemu,在qemu里面自定义DEBUG很麻烦,而且封装过度当需要很小(获取一个寄存器的值)开销很大
        1. nemu里面可以直接通过函数调用来获取DEBUG信息
        2. nemu和qemu可以相互映证
        3. 直接用qemu可能会有一些坑
      2. 模拟器作为动态链接库连接到仿真程序
      3. 处理器在指令完成时发出比对信息,当比对信息不一致时立刻报错并输出当前处理器状态
  3. 如何测试验证模块的正确性?

    1. 设计对比实验,如果结果相同则认为正确

    2. TLB中可以自行设计测例,来验证多种的功能

    3. 行为是否符合预期?

    4. 没有BUG的情况下,如果提升性能?

      1. 微结构设计?。。

      2. 写一些比较小的模块/程序,观察一个请求究竟做了什么事情,做周期级别的时间分析(打日志)。定位性能倒退的原因。

    5. (参数化框架)配置的组合数很大,可能需要用到回归测试,遍历所有的系统模块的组合

  4. 适配操作系统的过程中遇到哪些困难? 如何克服?

    1. 流片前开发(六个系统软件/OS)
      1. Nanas-lite:用户空间和内核空间共用同一个1GB空间,导致PTE覆盖
      2. FreeRTOS
      3. RT-thread:Idscript有ALIGN(4),4全部改成8跑通了
      4. xv6:不刷TLB(qemu里面没有刷TLB的概念)此时fork的时候Copy on Write机制会出现问题,还有load的时候?
        1. 只有运行一些很小的程序才会高几率出现此BUG,大程序可能会把TLB刷下去
      5. Linux kernel:编了一份SMP
        1. 运行的时候随机爆炸
        2. 上周的多核linux刷TLB又重新弄了一下
        3. 其他没有太多的坑
      6. Debian:跨页的4字节指令
    2. 流片后测试
      1. 4字节flash读取会导致一些读写取指相关的错误
      2. XIP(eXecute In Place):用flash取指执行,用sdram来读写数据
        1. 只适合“一个程序”
          1. 多个独立程序加载时会产生覆盖
          2. 程序段之间有2MB的空洞,如果直接全部加载进来,很浪费(总共只有4MB的内存)
          3. 因此将BBL和linux做成了一个程序
        2. linux数据段默认按页对齐,但XIP要求存储连续
          1. 修改链接脚本,把所有数据段合并成一个
            1. 段间空洞改为段内空洞,对XIP透明化
      3. 内核识别到的内存大小为0
        1. 实际RAM地址超出了默认内存地址空间的范围(1GB的间隔)
        2. 强行硬编码增加了1GB的空间。。
      4. 执行内核线程hello
      5. 执行用户线程hello
        1. 由于前面设计的锅,sdram中不能直接执行代码,所以分页的时候对进程页面要拦截并进行手动地址映射设置到flash
        2. 对flash读8字节,将ld指令魔改位lw的4字节指令
      6. vDSO(Virtual dynamic shared object)
        1. 一个映射到用户空间的so文件,可以在不陷入内核的情况下执行一些简单的系统调用
      7. 每次取指都需要从flash中取,需要成千上万个周期,变成了实际意义上的多周期

第三环节 经历

  1. 印象最深刻的bug
    1. 使用测试框架定位复杂BUG
      1. 模拟器和处理器的行为不太一样,33亿条指令时捕捉到错误。。。
      2. 边界测例:一条指令横跨了两个页面(前半和后半被分开,会产生PAgeFault)
      3. 特殊的Page Fault需要在指令集手册上查找,需要往特定的寄存器中写入值
    2. 硬件引脚输出问题
      1. 换成显式的硬件逻辑,突然就跑通了
      2. 对硬件手册信息(约定)的理解有错,“N”,低位全部接成了高位引脚
    3. TLB取地址
      1. TLB转换对了,但取出来的值不对
      2. 看了4天log信息,在x86中打印流程
      3. 最终师兄2小时找出,是x86的软件的一个BUG(没有刷TLB)
    4. Cache(SRAM)黑盒爆炸
      1. BUG不断修锅,然后不断出新BUG
    5. 去Cache中间层
      1. 整个核的行为发生很大变化
      2. 握手信号初始化的小问题
        1. 但是性能显著降低
        2. 分支预测器隐含的条件,去掉Cache后就不满足了
  2. 有没有坑过队友/被队友坑过?
    1. 主要还是硬件方面的事情
    2. Cache流水线(同时访问)有仲裁级相关的问题
  3. 和龙芯杯相比有什么不同?
    1. 验证环境更好(极大提高DEBUG生产效率)
    2. 代码质量需要一定的水平
  4. 第一次对项目进行可配置化, 感觉如何?
    1. 相比 verilog 好上很多了,要改的东西更少——敏捷开发(3周)
  5. 外设的验证工作有什么挑战?
    1. 多维度的复杂性:设备多样性、场景多样性、扩展多样性。
  6. 课堂上没讲过硬件填充的TLB, 你是如何实现正确的?
    1. TLB实现需要满足实验手册的约定,但需要自己去实现
    2. 状态机开始,不断扩充、成型(有点搞科研的味道;不确定性)
  7. Nextline预取器听上去很简单, 但你花了两个月才实现正确, 有什么坑?
    1. 功能:给一个地址,取这个地址+1
    2. 最初实现预取器发现性能倒退:L1 Cache访问比较频繁,如果放到L1前面就会性能下降(每次预取器加倍消耗)。所以又采用了L2 Cache,放到了L2 Cahce的前面,

第四环节 未来

  1. 一生一芯的经验对大家做毕设有什么帮助?
    1. 假设论证、心态。。
    2. 坚持、走通一条路。
    3. quick and dirty麻雀原则:先弄出来,再疯狂改进。
      1. 对前景要有认识,要意识到后续工作的改进瓶颈
      2. 保证良好的可扩展性
      3. 第一次设计推倒重来很正常,多次之后前景逐渐明朗
  2. 对参加下一届一生一芯项目的学弟学妹有什么建议?
    1. 基础设施很重要
      1. 对linux的魔改都是现在nemu中运行
        1. 其它的硬件环境运行测试起来都很难
    2. 系统能力很重要
      1. 不要害怕犯错
      2. 注重代码质量,commit水平,版本管理
      3. 总揽全局,对整个项目有接口性把握
    3. 对下一届的期望?
      1. 看实力水平,改进或者从头来走一遍(试错)?
      2. 水平不够,走一些弯路也是可以的?

zCore整体设计

前面讲的和以前的差不多。

async

async-await 用同步风格编写异步代码。Rust的一个特性。

  • 本质:无栈协程(共享同一个栈,面向任务的轻量级线程),协作式调度(非抢占式)
    • 语法糖。同步管理被封装透明化了,所以写法上与一般代码差不多。
    • 协程特点:共享栈,满足每个协程使用栈空间的最大用量(协程运行的中间状态),同时用少量的栈空间来保存每个协程的必要信息。
  • 适用于高并发IO场景
    • 可能必须解决响应时间的问题
  • 主流编程语言均以支持:C#,C++,JavaScript,Python
  • 几乎没有在 bare-metal(裸机)中应用

工具链

  • 代码质量控制:cargo fmtcargo clippy
  • 文档和单元测试:cargo doc + cargo test + grcovgrcov 计算测试覆盖率)
    • (TODO)性能测试:cargo bench
  • carte 的拆分和发布流程:cargo publish
  • 持续集成和自动测试:GitHub Actions
  • 社区合作开发:GitHub issue + PR

突然想看看《设计模式》。

8月5日 RIOS实验室

没想到之前关注的两个:一生一芯、RIOS都被邀请过来作报告。。tql。感觉就是这个活动很高端。

好的,上午依然是自由活动的性质,所以没什么事。。


我的博客网址出锅了,想办法看看能不能补救。HSTS策略是真的烦。


https://raw.githubusercontent.com/wiki/rcore-os/zCore/files/wrj-thesis.pdf。wrj的毕设论文写得确实很详细。

https://raw.githubusercontent.com/wiki/rcore-os/zCore/files/pql-thesis.pdf。

先把这两个毕设看一看好了。


TBSI来咯。hhh

RIOS实验室研讨会

RIOS实验室研讨会


张林老师有信息论的MOOC,貌似以前是TBSI的院长。 然而信息论我都还没看完,我太菜辣。

一开始基本还是一些RISC-V的背景介绍。没啥新鲜的。在经济上和政治上都有一定优势。

PicoRio:超低成本,成熟的社区。

TBSI 谭老师的口语实在是有点泛英语化。。


现在PicoRio有开源地址吗?或者在哪里可以了解到最新进展呢?

目前还没有正式地发布,文档还在慢慢更新。秋季?

从专门网站上找documentation。

PicoRio似乎不想用BSD许可证,然后再设计一个license?但是出发点是保护社区。

其它的事情不太了解也不是很感兴趣。

Sipeed矽速工程师交流会

听说K210板子是从他们那批发的。。

矽速科技官网:https://www.sipeed.com


MaixPy:使用简单的Micropython语法在AI芯片上快速实现有趣的功能的SDK。

SDK组成:

  • CMake + Kconfig
    • CMake:自动寻找cmake文件,导入各个模块并注册
    • Kconfig:进行组件配置的选择,并生成config文件
  • 组件(驱动、micropython、模块)
  • 工程(project.py)

视觉、多媒体、机器流水线、人脸识别……、

Micropython语法:

  • 用户代码精简,易于上手,成本低(几十块钱的开发板)
  • 面向对象语法,封装性好,开发速度高
  • 解释型语言,快速验证

Micropython语法是从语法上与python不同,还是只是可以调用你们写的一些库函数?

Micropython其实就是一个解释器,大部分时候与python语法上是兼容的。

AI 模型

K210搭载了 AI 芯片吗? 它在什么方向上做了优化,和传统的芯片的不同在哪?

AI芯片就是一个可以部署和运行模型的芯片而已。

所有的算法模型都是提前训练好的? K210 本身支持训练吗?

对。一般要在电脑上训练。

KPU 是什么? 和CPU和GPU有什么不同?

针对的应用场景不同,KPU支持的是通用运算。GPU专门处理图形处理方面的运算。

KPU的K只是一个命名。KPU实现了GPU功能的一些子集。

模型压缩的方法?

浮点运算精度调低。用一些软件工具来压缩?

MaixPy常见难点

GC(垃圾回收):GC分配的内存需要标记,内存不足的时候自动回收

对齐错误:指针、内存、地址对齐的问题

MaixPy TODO:

  • LPU Flash run,PSRAM run:目前只支持6M的模型,如果可以存储到flash里面,需要的时候再读取,就很好
  • MaixUI:简单轻量化,减少内存消耗
  • MaixHub:分享训练好的模型的Hub网站
  • IDE:。。。
  • MaixPy on Linux:

JTAG(Joint Test Action Group,联合测试工作组)。

一个硬件集成式的调试工具。提供了一系列接口来调试开发板。

JTAG提供了图形界面化的IDE。

8月6日 论文研读

今天主要看rCore和zCore的本科毕业设计论文。

Rust 的零成本开销抽象意味着,抽象的运行开销为0;如果的确要在运行时使用该抽象,也可以保证运行开销最小。


文档讨论会


可能需要从头开始搭一遍 zCore。(复现 / 拆解?)

然后老师又说把每一部分的代码进行分析。

自己先理解自己的代码部分。

主线还是需要变化。

操作系统 DEBUG 门槛/难度怎么改变?

有点难度。


华为 openEuler 研讨会


Email:guanyanjie AT huawei.com

华为基于服务器linux发行版,开源在码云上的一个共享社区。

网址:openeuler.org。

openEuler是一个开源、免费的Linux发行版平台,将通过开放的社区形式与全球的开发者共同构建一个开放、多元和架构包容的软件生态体系。同时,openEuler也是一个创新的平台,鼓励任何人在该平台上提出新想法、开拓新思路、实践新方案。

openEuler 是为了让华为的芯片(麒麟、鲲鹏……)出厂即可以有配套的开源发行版。建立 openEuler 社区,使能ARM生态,让世界有第二选择。

全软件堆栈的技术优化,打造高性能、高可靠、高安全、易用的操作系统。


完全回到了原来的一个状态,自选一个项目:继续写tutorial,或者写代码的测试文档。


RVM晚间研讨会


Hypervisor: Virtual Machine Monitor(VMM)

RVM: Rcore Virtual Machine。基于 RVM 实现了 rCore/zCore 的 hypervisor。

不是很感兴趣。全是实现细节。

zCore虚拟化的更多工作:

  • 完善RVM,完成更多的测试(24/28)
  • RVM从rCore中独立出来,但有些部分还没搞好
  • 跑在其它真实的环境中,目前只支持 intel 的 x86

zCore 内核对象及系统调用


Zircon微内核是Fuchsia的最底层。

  • 实用主义微内核
  • 使用 C++ 实现,支持 x86_64 和 ARM64
  • 面向对象(微内核的传统习惯):将功能划分到内核对象
  • 默认隔离:使用 Capability 进行权限管理
  • 安全考量:强制地址随机化(zCore还没实现),使用 vDSO 隔离系统调用

所有的东西都可以称为内核对象。

  • 任务:Job, …
  • 内存:VMAR, …
  • IPC: Channel, …
  • 信号:Event, …
  • 驱动:Resource, ….

Object:

  • Object:内核对象
  • Rights:对象访问权限
  • Handle = Object + Rights:对象句柄(类似 fd)

IPC:

  • Channel:进程间通信基础设施,可以传递数据和handle
  • FIFO:报文数据传输
  • Socket:流数据传输

Tasks:

  • Job:作业,负责控制权限(类似容器)
  • Process:进程,负责管理资源
  • Thread:线程,负责调度执行

一个作业可能有多个进程,一个进程可能有多个线程。进程之间没有父子关系。

Memory:

  • VMO(Virtual Memory Object)
    • Paged:分页物理内存,支持写时复制
    • Physical:连续物理内存
  • VMAR(Virtual Memory Address Region)
    • 代表一个进程的虚拟地址空间
    • 树状结构
  • Pager:用户态分页机制

Signaling and Waiting:每个 Object 有 32 个信号位,用户程序可以阻塞等待。

  • Event(pair):事件源/对
  • Timer:计时器
  • Futex:用户态同步互斥机制(快速)
  • Port:事件分发机制(类似epoll)

zCore硬件移植和驱动开发


UEFI(Unified Extensible Firmware Interface):增强版 BIOS。类似 Open SBI。

  • 省去了从古老的实模式进入现代长模式的汇编代码
  • 丰富的外设驱动支持,快速输入输出
  • Rust UEFI 开发环境方便易用(uefi-rs 库)

8月8日

今天到海南转机,结果航班取消了。被迫在海南呆了半天。

居然看到了椰树椰汁的厂子。。

海南唯一的一家呷哺呷哺。。

买了晚上的经济舱,结果被升成头等舱了。。


一系列际遇之后到家。完结。