交叉编译 Nginx 1.14.2 到 RISC-V

最近又把一定的精力放到了 RISC-V 64 上的 rCore 用户态程序的支持上,同时也借到了 HiFive Unleashed 板子,所以有真实硬件可以拿来跑了。在这之前先在 QEMU 上把能跑的都跑起来。 由于 rCore 对 glibc 的支持一直有问题,RISC-V 也不例外,所以还是选择用 musl 来做这件事情。一般搜索,终于找到了 Linux 下能用的 musl-riscv-toolchain 。编译好工具链以后,很多需要 libc 的用户态都能跑了,于是想着试一下 nginx 的编译。试着编译了一下,遇到了各种问题,最后搜到了交叉编译 Hi3536 上面使用的 nginx,里面的方法解决了这个问题。最后总结出了这样的 patch : diff --git a/nginx-1.14.2/auto/cc/name b/nginx-1.14.2/auto/cc/name index ded93f5..d6ab27a 100644 --- a/nginx-1.14.2/auto/cc/name +++ b/nginx-1.14.2/auto/cc/name @@ -7,7 +7,7 @@ if [ "$NGX_PLATFORM" != win32 ]; then ngx_feature="C compiler" ngx_feature_name= - ngx_feature_run=yes + ngx_feature_run=no ngx_feature_incs= ngx_feature_path= ngx_feature_libs= diff --git a/nginx-1.14.2/auto/lib/openssl/make b/nginx-1.14.2/auto/lib/openssl/make index 126a238..7a0e768 100644 --- a/nginx-1.

Read More

在古老的 OS 上运行一个干净的新的环境

由于某些课程的原因,需要在一个 CentOS 7 上跑一些编译和运行代码。看到这么古老的软件,我心想不行,肯定要找新一些的软件来用。首先想到的是 tmux,于是按照网上的脚本 很快装了一个 tmux 2.8 版本,果然好了很多。但是常用的很多软件依然是个问题。试了一下最近比较新的 code-server,因为 ABI 问题跑不起来。 于是开始想玩骚操作。首先想到的是 Gentoo Prefix,不过既然是别人的机器,还是算了。又找了 fakeroot 配合 alpine rootfs 的方案,但编译不过,估计是内核版本问题。又试了一下 fakechroot,但它需要配合 fakeroot 使用,这就凉了。 然后又找了一些替代方案。一是 uchroot,但由于 CMake 版本太老也编译不过。最后发现了 PRoot ,直接提供 prebuilt 然后很容易就可以跑起来: $ ./proot -b /proc -b /dev -r $CHROOT /bin/busybox sh 于是就进到了 alpine 的 rootfs 中,下载地址。进去以后发现没有编辑器,于是出来把 apk 的源改了,加了 resolv.conf,就成功地安装了很多很新的软件了。

Read More

每周分享第 15 期

继续沉迷写 OS 嵌入 graphics for rust 可以绘制 bmp 了 https://wapl.es/rust/2019/03/04/embedded-graphics-0.4.7-bmp-support.html rustup component history 方便 nightly 日期选择 https://rust-lang.github.io/rustup-components-history/index.html grpcurl 用于 grpc 调试 https://github.com/fullstorydev/grpcurl grafana 6.0 is out http://docs.grafana.org/guides/whats-new-in-v6-0/ 康哥推荐的写论文工具:https://github.com/stsewd/ieee-pandoc-template

Read More

每周分享第 14 期

最近沉迷写 OS,没怎么搜罗新的东西( 用 Docker 做交叉编译 https://github.com/dockcross/dockcross#dockcross tar inplace extraction 有意思的思路 https://gitlab.com/antonok/taro los 16.0 发布 基于 Android Pie https://lineageos.org/Changelog-22/ Rust 1.33.0 Pin 进入 stable https://blog.rust-lang.org/2019/02/28/Rust-1.33.0.html Rust 用于编写 cli 软件的工具库 https://rust-lang-nursery.github.io/cli-wg/index.html 自动使用 CI 发布二进制 prebuilt 的模板 https://github.com/japaric/trust 转换 gif 到 xlsx 很神奇 https://github.com/pugwonk/gif2xlsx/blob/master/README.md Go REPL https://github.com/cosmos72/gomacro 基于区块链的论坛海星 其实是区块链数据库 https://github.com/CovenantSQL/CovenantForum Rime emoji 嵌入输入法 https://github.com/rime/rime-emoji 一个神奇的数据库 https://github.com/mit-pdos/noria 一个讲内核的 gitbook https://richardweiyang.gitbooks.io/kernel-exploring/ 用 React 写桌面控件 http://tracesof.net/uebersicht/

Read More

在 rCore 上运行 nginx

阿 西 吧 nginx 终于能在 rCore 上跑了 orrrrrrrz 通过这半个多月来的大量开发,我和王润基 @wangrunji0408 学长算是终于完成了第一个 milestone:跑起来一个 nginx。遇到了很多困难,大概有这些: syscall 实现不全。各种方面都缺,然后 nginx 在编译的时候又检测到比较新的 OS 版本,所以很多 syscall 都用了新的来替代老的,例如 readv/writev pread/pwrite accept4 等等,所以这方面做了一些工作。另外,还有很多新的 syscall 进来,太多了我就不细说了,基本上一个 commit 做一点一个 commit 做一点这个样子。 nginx 用到了 SSE 的寄存器 xmm,但是之前是没有开的。所以把 sse 打开,然后切换上下文的时候把 sse 通过 fxsave 保存和 fxrstor 恢复(有意思的是,as 居然不认这俩,只好手动写字节码),然后为了 16bit 的对齐又写了几行汇编代码。这块问题不大,今天一会就搞定了。但是如果要性能更高一些的话,可能需要在第一次使用 xmm 的时候再开始保存,大概就是加一个 bit 的事情。 文件系统有点崩。实现还是有很多 BUG,表现就是需要经常重新 mksfs 一下,再重启加载完好的 fs,有时候强制关机一下就又崩了。 内存管理做了一些改变。为了实现更加完整的 mmap mumap 和 mprotect,又发现了一些新的 BUG 在里面,然后慢慢修复了。就是实现的有点粗暴。 死锁问题。这个其实现在还会出现,只是还没调出来,也不会百分百出现。我们计划在锁上面做一些死锁检测,例如记住是谁上锁的,等等。现在就遇到一个很玄学的死锁问题。 然后代码也是一边在写一边在重构吧,很多地方现在都写得很粗暴,FIXME 和 TODO 留了很多,很多地方也写得不够优雅。以后再慢慢重构 + 优化吧。

Read More

实现网络的 syscall

有了网卡驱动,接下来要做的就做网络的 syscall 了。为了测试,首先在 busybox 里找可以用来测试的 applet,由于没有实现 poll,所以 nc telnet 啥的都用不了。最后选择到了 ping 和 pscan 上。 ping 大家都很了解,pscan 就是一个扫端口的,对一个 ip 连续的若干个端口发起 tcp 请求。这就要求我提供 raw socket 和 tcp socket 状态的支持。由于网络栈本身是异步的,但 read connect 这些函数在不调 setsockopt 的前提下又是同步的,然而现在又没有 signal 可以用,要是 block 了就再也出不来了。于是就采用了 Condvar 的办法,拿一个全局的条件变量,当 poll 不到内容的时候,先把线程拿掉,等到网络栈更新了,再恢复。这样至少不会把 cpu 也 block 住。 然后就是把 socket 部分改了又改吧,数据结构的设计改了几次,为了解决 ownership 问题上锁啊也有点多,但是也更细了,虽然实际上可能没有必要,因为上面还有大的锁。不过性能还不是现在考虑的重点,关键还要先把 send recv accept bind listen 啥的写得差不多了,然后还有把 poll/select 实现了,这个很关键。 中间遇到的最大的坑就是,接收 pci interrupt 的时候总是啥也没有,然后靠万能的 qemu trace 发现,原来是 mask 掉了,所以啥也收不了,然后最后的解决方案就是用 MSI Interrupt #55 搞定了这个问题。至于为啥是 55 呢,因为 23 + 32 = 55 啊(误

Read More

每周分享第 13 期

今天还是早点发吧 Rust concurrent work-stealing queue 可能可以放到调度器里用 https://github.com/kinghajj/deque 支持信用卡/时间等格式信息的输入控件 https://github.com/nosir/cleave.js Rust 的简单 http server https://github.com/svenstaro/miniserve Coroutines & Modules Added For C++20 http://www.phoronix.com/scan.php?page=news_item&px=Coroutines-Modules-CPP20 Implementing TCP in Rust (part 1) https://www.youtube.com/watch?v=bzja9fQWzdA 一个类似 Vuetify 的框架 https://buefy.org/ systemd tmpfiles.d 用于管理特定的临时文件夹 https://www.freedesktop.org/software/systemd/man/tmpfiles.d.html 获取 ASN 信息的 API https://bgpview.docs.apiary.io/#reference/0/asn-prefixes/view-asn-prefixes Rust getter/setter generation https://github.com/Hoverbear/getset Golang 1.12 发布:TLS 1.3 http://www.phoronix.com/scan.php?page=news_item&px=Golang-1.12-Released 一个笑话 https://redd.it/aux77g Rust 的 STM https://github.com/mtak-/swym 自动同步视频和字幕 https://github.com/smacke/subsync 用于快速开发的 http server https://zeroserver.io/ 一个自动加载的 http server https://github.com/tapio/live-server 用 markdown 写 presentation 在线版 https://github.

Read More

使用 Rust 实现 e1000 驱动

是的。我又来了。上次做了使用 Rust 实现 VirtIO 驱动之后,继续往 rCore 加更多的驱动支持。由于现在工作重点是 x86_64 下的 syscall 实现,所以选了一个比较有代表性的驱动 e1000 来实现。其实如果只是为了在 qemu 下运行的话,其实只需要支持 virtio-pci 就可以了,原来的 virtio-net 直接拿来用就可以了。 为什么挑 e1000 呢,一方面是支持的设备多,有真实硬件可以测试,虽然不一定要裸机上跑,但是可以通过 PCI passthrough 来测试驱动的正确性。另一方面是网上的资料比较多,有现成的简单的代码可以借鉴。这次主要借鉴了三个来源:一是 Biscuit OS,二是 Judge Duck OS,三是 Linux。 首先是实现了简单的 PCI 总线的枚举,然后找到对应的设备,激活,并且找到映射的内存地址,然后把原来 C 语言的实现搬运到 Rust 中。这个过程中遇到很多坑,例如一开始我以为内核里 pa 和 va 是一个固定的偏移,不过多次尝试后才发现这个假设只对 riscv 平台里的实现成立。 这个时候就可以收到外面给进来的以太网帧了。接着就是把它接入到 smoltcp 的 API 中。但是发包又不工作了,尝试了很多次,各种方法也不行。其中特别要提到的就是 qemu 的 tracing API,它在帮助我调试之前的 virtio 驱动和这次的 e1000(e) 驱动中起到了很大的帮助。不过,遗憾的是,发包相关的代码里的 trace 不足以让我找到问题的所在,我只好采用了最后一招: 下载 QEMU,自己改,然后自己编译。 这个方法果然很有效啊,经过简单的几个修改,很快就定位到问题所在了,原来就是一个简单的错误,把 4 写成了 8。这个过程中我也发现 QEMU 在 incremental build 的时候似乎会 segfault,我没管这么多,反正编译也不慢,次数也不多,每次 clean 再 build 问题也不大。

Read More

每周分享第 12 期

看脑王迟到了( Rust Embedded Graphics 库 https://github.com/jamwaffles/embedded-graphics Wireguard for macOS https://lists.zx2c4.com/pipermail/wireguard/2019-February/003853.html Wireguard-go UI https://github.com/aequitas/macos-menubar-wireguard T2 逆向 https://duo.com/labs/research/apple-t2-xpc 脑王剪辑 https://www.bilibili.com/video/av43972717 dram 推荐的工具 notion.so 带授权和审计的 sudo https://github.com/square/sudo_pair rust 的 manpage 生成器 https://github.com/rust-cli/man 才发现 Github 有 Project 功能 https://help.github.com/en/articles/about-project-boards rust 的 elf/macho 生成 https://github.com/m4b/faerie rust 的 elf/macho/pe 读取 https://github.com/m4b/goblin rust 的 glob 实现 https://github.com/rust-lang-nursery/glob 基于 BoringSSL 的 rust 加密库 https://mundane.googlesource.com/mundane 从 linux 交叉编译到 macOS 的方法 https://github.com/tpoechtrager/osxcross cargo-deb 后又有了 cargo-rpm https://github.com/RustRPM/cargo-rpm 自带 diff 的 assert_eq 宏 https://github.

Read More

预告 Learn-Project 4.0 版

不知道大家听没听说过 Google Chrome 有个插件,叫做 Learn Project,是一个网络学堂的改良前端。不过,随着网络学堂的不断更(xia)新(gao),它已经不再适用于现在的版本。于是,哈利橙(@Harry-Chen)决定利用寒假时间,在今天(2.17)之前完成 Learn Project 4.0 的开发。为什么叫 4.0 呢,因为哈利橙课程的 GPA 众数是 4.0。这个版本采用先进的 React 框架编写(Vue 塞高),使用了 Material Ui 作为界面框架(这我觉得可以),目前的一个参考图(图源哈利橙): 看那满眼的高分数,希望 Learn Project 4.0 能在 flag 倒下之前完成。

Read More