春季学期第 2 周 (3 月 3 日)

Abcoder 项目

目标

  • 使用 Abcoder 对一些复杂项目进行解析,协助改进目前开源的 Abcoder 的功能
  • 了解 Abcoder 的原理和使用方式,并能够指导其他人使用

使用方法

项目组给出了两种方法:Coze 和本地部署 ollama。我试了 Coze 并不是很稳定,而且还需要付钱。他们之前生成的 rcore 解析似乎是内部的模型 API 接口跑的,我直接在 Coze 平台上跑的模型能力和稳定性都不太行。所以我找了台服务器跑了 ollama,使用了 deepseek-coder-v2,并且手动将 context windows 调整到了 4k。速度还算过得去,并开始对 rust 项目进行解析。

这里试的时候遇到了一些问题,简单记录一下:

  • 本来是使用 llama3.2,但是这个模型不太行,所以换成了 deepseek 32b 模型。但是 deepseek32b 模型本身是一个 chat 模型,会进行所谓深度思考,然后输出的解析结果带了很多无用的思考内容,占用了篇幅的同时还让解析时间变慢。于是最后换成了 deepseek coder v2 模型。

  • 使用 ollama 跑 deepseek coder v2 的时候发现很多时候解析中断了, 看 log 发现是传入的 prompt 太长了超过了模型的 context windows。ollama 默认开了似乎是 2048 的 max-token,手动将这个模型改为了 4096 的 max-token,应该就没有太大问题了。

    context windows 大小 n 的平方和思考时间成正比,因此开太大也不太好。

具体的环境配置文档暂时不写,因为这些环境都是我临时找的,给其他人复现的可能性也不高。等之后决定给其他人使用的时候再说。

在这里简单贴一下对于 abcoder 生成结果的解析内容。因为 abcoder 是直接调用了模型的输出然后存储在了一个 json 文件里面,需要提取有效信息并且将其转化为可视文件比如 Markdown。

# demo.py
def level_log(log, title):
    print('#' * log + ' ' + title )

import json
# 需要将 abcoder 生成的结果存储在同目录下的 data.json 中
with open('data.json', 'r') as f:
    data = json.load(f)
    for module in data['Modules']:
        if data['Modules'][module]["Dir"] == "":
            continue
        level_log(1, module)
        packages = data['Modules'][module]["Packages"]
        for package in packages:
            level_log(2, package)
            print(packages[package]['compress_data'])
            funcs = packages[package]['Functions']
            level_log(3, "Functions")
            for func in funcs:
                level_log(4, func)
                print(funcs[func]['compress_data'])
            
            level_log(3, "Vars")
            vars = packages[package]['Vars']
            for var in vars:
                # print(var)
                level_log(4, var)
                print(vars[var]['compress_data'])

运行方式:

$ python3 demo.py > result.md

结果

  • 先解析了一个自己写的简单 rust 项目:dependencies-patch。得到的结果详见 dependencies-parse

  • 然后最近会尝试开始解析 ArceOS 等内核,今天试了一下似乎有点慢。

OS 比赛支持

内核测例多架构支持

将 2025 初赛测例进行修改,编译为 x86_64/riscv64/aarch64/loongarch64 四个架构的镜像。

  • 测例仓库上2025_multiarch目前可以支持同时编译生成 x86_64/riscv64/aarch64/loongarch64 四个架构的 Musl 和 glibc 测例。
  • starry-next 仓库已经通过的 riscv64 和 loongarch64 测例也可以通过 x86_64 和 aarch64 的版本。
  • 预编译好的镜像发布在 2025年初赛SD卡镜像

并且我提供了一个新的 docker 镜像。该镜像下可以支持编译比赛测例,并且运行 starry-next 内核,输出这些测例的运行信息。Docker 镜像对应的构建仓库详见 https://github.com/Azure-stars/os-contest-2024-image,可以为比赛平台评测机所用镜像和即将到来的 Github CICD 工作作参考。

内核测例 Bug 修复

pre-2025分支为本年度赛事使用的初赛测例所在分支。经过和几位同学的测试,发现测例内存在一些 Bug,并通过 PR 或者直接 commit 的形式进行了修复。共提交了 4 次修复。

初赛测例分析

在编译出 x86_64 的镜像之后,便可以在 Linux 主机上进行系统调用分析。通过解析 strace 生成的 log 可以快速得到测例在 Linux 下所需的 syscall 和相关的行为。

musl-busybox 测例为例子,在 sdcard/musl 目录执行如下指令:

strace -f -e trace='!read,write,readv,writev,lseek,dup' -o strace_musl_busybox.log ./busybox sh ./busybox_testcode.sh

即可得到 busybox 调用的 log。

-e trace='!read,write,readv,writev,lseek,dup 是为了避免 LOG 中输出过内容导致文件过大。因为 IOZONE 等测例会执行非常多次相关的 syscall 进行 benchmark 测试,因此需要过滤掉这类 syscall。

我们简单对这类 LOG 进行分析:

# Description: Extract syscall list from strace log file
import argparse
argparser = argparse.ArgumentParser()
argparser.add_argument('-s', '--strace_log', type=str, help='strace log file')
args = argparser.parse_args()

STRACE_LOG = args.strace_log
SYSCALL_LIST = []

with open(STRACE_LOG + '.log', 'r') as f:
    lines = f.readlines()
    for line in lines:
        if '(' not in line:
            continue
        # If using strace -f to trace, the first field of each line is the pid, so we need to remove it
        if line[0].isdigit():
            line = line.split(' ', 1)[1]
        syscall = line.split('(')[0]
        # Remove useless information
        if syscall.find('<') != -1 or syscall.find('+') != -1:
            continue
        if syscall not in SYSCALL_LIST:
            SYSCALL_LIST.append(syscall)

with open(STRACE_LOG + '_syscall_list.txt', 'w') as f:
    for syscall in SYSCALL_LIST:
        f.write(syscall + '\n')

即可得到支持 busybox 测例所需要的 syscall 列表 syscall_list

对所有的测例进行统计,可以得到 musl 测例下所需要的 syscall list