2025-09-19 折腾一下 DragonOS

DragonOS 会用 rust-toolchain.toml 来锁版本。试了之后发现其实最新的 nightly 是可以编译过的,不过要改的话得改好多地方,就用他们的 toolchain 好了。

DragonOS 的 Makefile 有两个主要部分,分别是 kernel 和 user。`make all` 可以同时构建这两个部分。

DragonOS 会需要把 target/ 下面的编译产物拷来拷去的,然而我的环境下把所有项目的 target/ 集中到 ~/.cargo/target 下面了。需要先运行 `for dir in $(f -iname Cargo.toml|sed 's/Cargo.toml$//'); do ( cd $dir && ln -s ~/.cargo/target ./ ); done` 来创建软链接。很坏。cargo 应该提供一些子命令来指定产物的输出路径的

编译 DragonOS 需要用到他们的土制开发工具 dadk。在构建用户程序时出现了报错:

    test_shm_info.c: In function ‘main’:
    test_shm_info.c:66:31: error: passing argument 3 of ‘shmctl’ from incompatible pointer type [-Wincompatible-pointer-types]
    66 |   if (shmctl(shmid, IPC_INFO, &shmmetainfo) == -1) { // 获取共享内存段信息
        |                               ^~~~~~~~~~~~
        |                               |
        |                               struct shminfo *
    In file included from test_shm_info.c:6:
    /usr/include/x86_64-linux-musl/sys/shm.h:62:22: note: expected ‘struct shmid_ds *’ but argument is of type ‘struct shminfo *’
    62 | int shmctl(int, int, struct shmid_ds *);
        |                      ^~~~~~~~~~~~~~~~~
    test_shm_info.c:80:31: error: passing argument 3 of ‘shmctl’ from incompatible pointer type [-Wincompatible-pointer-types]
    80 |   if (shmctl(shmid, SHM_INFO, &shm_info) == -1) { // 获取共享内存段信息
        |                               ^~~~~~~~~
        |                               |
        |                               struct shm_info *

疑似指针类型不对,不知道发生了什么。可能是写的有问题

看了下头文件发现:

    /* Obsolete, used only for backwards compatibility */
    struct	shminfo {
        int shmmax;
        int shmmin;
        int shmmni;
        int shmseg;
        int shmall;
    };

原来是过期了……但是我看头文件里面明确说明当 `IPC_INFO` 的时候第三个参数会返回 shminfo 结构体,那看来是 glibc 写的有点问题。加个 `void*` 转一下应该就好了。

别的还报了一堆 warning,懒得修了,希望没有事……

DragonOS 所有的用户程序需要用 musl 静态编译然后扔上去跑。是因为不支持 glibc 吗,感觉有点怪。可能是配 glibc 的交叉编译麻烦吧。

    Compiling mytrace-ebpf v0.1.0 (/home/jyi/dev/DragonOS/user/apps/test_tracepoint/mytrace-ebpf)
    error: failed to run custom build command for `mytrace-ebpf v0.1.0 (/home/jyi/dev/DragonOS/user/apps/test_tracepoint/mytrace-ebpf)`

    Caused by:
    process didn't exit successfully: `/home/jyi/.cargo/target/release/build/mytrace-ebpf-5e7fa21c0aa18a1e/build-script-build` (exit status: 101)
    --- stderr

    thread 'main' (339720) panicked at mytrace-ebpf/build.rs:15:42:
    called `Result::unwrap()` on an `Err` value: CannotFindBinaryPath
    note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
    warning: build failed, waiting for other jobs to finish...
    error: failed to compile `mytrace v0.1.0 (/home/jyi/dev/DragonOS/user/apps/test_tracepoint/mytrace)`, intermediate artifacts can be found at `/home/jyi/.cargo/target`.
    To reuse those artifacts with a future compilation, set the environment variable `CARGO_TARGET_DIR` to that path.

又爆了……原来是缺了 bpf-linker 导致的。这个 bpf-linker 竟然包管理器里还没有,得从 cargo 安装。https://github.com/aya-rs/bpf-linker

它的 bootstrap.sh 脚本里写了装这个东西。但是之前装 napcat 的时候安装脚本到处拉屎给留下心理阴影了,就没用。

    /bin/sh: 1: x86_64-linux-musl-ar: not found
    make[5]: *** [scripts/Makefile.build:264: archival/built-in.o] Error 127
    make[5]: *** Waiting for unfinished jobs....
    /bin/sh: 1: x86_64-linux-musl-ar: not found
    make[5]: *** [scripts/Makefile.build:264: archival/libarchive/built-in.o] Error 127
    make[5]: *** Waiting for unfinished jobs....
    /bin/sh: 1: x86_64-linux-musl-ar: not found

编译 busybox,嘻嘻又爆了。这回是缺 musl 的工具链。我记得可以从 musl.cc 上面找到一些。比如这个 https://musl.cc/x86_64-linux-musl-cross.tgz。或者是直接用他们的 `tools/install_cross_gcc.sh` 也行。我要把这个脚本自己留一份以后想编译 static 的 musl 东西时也能用。

哎神经病怎么给我安装了 loongarch 的 gcc 出来了,坏。看了下代码发现原来已经有 x64 的 gcc 的时候它会自动走到 else 分支然后给我下一个 loongarch 的 gcc 回来吗。

    make[5]: *** [scripts/Makefile.build:197: miscutils/ubi_tools.o] Error 1
    make[5]: *** [scripts/Makefile.build:197: networking/tc.o] Error 1
    networking/nameif.c:78:10: fatal error: linux/sockios.h: No such file or directory
    78 | #include <linux/sockios.h>
        |          ^~~~~~~~~~~~~~~~~
    compilation terminated.
    make[5]: *** [scripts/Makefile.build:197: networking/libiproute/rtm_map.o] Error 1
    make[4]: *** [Makefile:744: networking/libiproute] Error 2
    make[5]: *** [scripts/Makefile.build:197: networking/nameif.o] Error 1
    In file included from networking/libiproute/utils.h:5,
                    from networking/slattach.c:41:
    networking/libiproute/libnetlink.h:5:10: fatal error: linux/types.h: No such file or directory
        5 | #include <linux/types.h>
        |          ^~~~~~~~~~~~~~~

哦,缺 Linux headers。`export C_INCLUDE_PATH="$C_INCLUDE_PATH:/opt/x86_64-linux-musl-cross-gcc-9.4.0/x86_64-linux-musl/include"` 就调理好了。

编译完所有东西之后,就是创建磁盘镜像。这个 dadk 的东西会辅助创建磁盘镜像,看了一下代码发现原来是调用一堆小工具比如 fdisk 和 mkfs 之类的。

因为创建磁盘镜像需要 mount,在 lxc 里面不好搞。所以移到 WSL 里做。

难绷的是这个 dadk 缺工具也一声不吭,直接无脑地用 anyhow 把错误向上抛,最后在十万八千里的地方 panic 一个 `No such file or directory (os error 2)` 错误,闹麻了。对着代码看了半天才发现原来是没有 mkfs.fat,需要安装一个 dosfstools。哎

因为网络带宽有限,所以先创建一个 512 MB 的镜像试试水,反正到时候也可以 resize2fs,哦不对我草好像 DragonOS 不支持 ext2,那就是 fat。fat 可以 resize 吗,我不道啊。

创建好的镜像大小压缩成 xz 是 36 MB,还行。可以通过网络嗖嗖

哎,应该搞一个自己的镜像脚本出来的。不用它那个

然后是试着在 qemu 里面启动一下。我去,直接就启动好了!大成功

    [ DEBUG ] (src/driver/tty/tty_job_control.rs:83)         tty_check_change: orphaned pgrp
    read char failed: I/O error (os error 5)
    [ DEBUG ] (src/driver/tty/tty_job_control.rs:83)         tty_check_change: orphaned pgrp
    read char failed: I/O error (os error 5)
    [ DEBUG ] (src/driver/tty/tty_job_control.rs:83)         tty_check_change: orphaned pgrp
    read char failed: I/O error (os error 5)
    [ DEBUG ] (src/driver/tty/tty_job_control.rs:83)         tty_check_change: orphaned pgrp
    read char failed: I/O error (os error 5)
    [ DEBUG ] (src/driver/tty/tty_job_control.rs:83)         tty_check_change: orphaned pgrp
    read char failed: I/O error (os error 5)
    [ DEBUG ] (src/driver/tty/tty_job_control.rs:83)         tty_check_change: orphaned pgrp
    read char failed: I/O error (os error 5)
    [ DEBUG ] (src/driver/tty/tty_job_control.rs:83)         tty_check_change: orphaned pgrp
    read char failed: I/O error (os error 5)
    [ DEBUG ] (src/driver/tty/tty_job_control.rs:83)         tty_check_change: orphaned pgrp
    read char failed: I/O error (os error 5)

又试了一下不用 qemu 指定 kernel,让它自己从 grub 启动,发现报了一吨 tty 错误,不知道为什么。希望能够修好。

但是我 pve 怎么指定 qemu 的 -kernel 参数呢,有点不懂不懂喵

https://pve.proxmox.com/wiki/Manual:_qm.conf

哦,有的有的,原来可以在 root@lighthouse:/etc/pve/qemu-server# vi 101.conf 指定 args 参数
但是还是起不起来,不知道为什么

pve 导入一个磁盘:

    https://dae.me/blog/2340/how-to-add-an-existing-virtual-disk-to-proxmox/

    154  qm disk import 101 ./disk-image-x86_64.img local-lvm --format raw

试着把 busybox 的所有小工具全都放进去,结果 dragonos 只支持 fat,没有软链接,把磁盘塞爆了……

---

2025-09-21 今天继续折腾,看看能不能把网络给连上

折腾了半天老是 kernel panic,感觉不太行,不玩了。转战 asterinas