在2010年路由器上运行Pixelflut
摘要
作者描述了如何使用OpenWRT并交叉编译Rust代码,在一台2010年的TP-Link Archer C7路由器上运行Pixelflut(一个协作像素艺术项目),并详细介绍了技术挑战和设置过程。
<p><a href="https://lobste.rs/s/ivm0qn/running_pixelflut_on_2010_router">评论</a></p>
查看缓存全文
缓存时间: 2026/09/24 23:06
# 在2010年的路由器上运行Pixelflut
来源:http://filmroellchen.eu/blog/mipselflut/
## 搜索结果
\.\. (http://filmroellchen.eu/blog/)/mipselflut
发布于:2026\-06\-19
## 目录
- 目标混淆 (http://filmroellchen.eu/blog/mipselflut/#target-confusion)
- Breakwater崩溃 (http://filmroellchen.eu/blog/mipselflut/#breakwater-breaks)
- 大端序回归 (http://filmroellchen.eu/blog/mipselflut/#return-of-the-big-endian)
- 获取画布 (http://filmroellchen.eu/blog/mipselflut/#getting-the-canvas)
- 不过说真的,ffmpeg... (http://filmroellchen.eu/blog/mipselflut/#actually-though-ffmpeg)
- Kleines Filmröllchen的糟糕视频流 (http://filmroellchen.eu/blog/mipselflut/#kleines-filmrollchen-s-shitty-video-streaming)
- 速率限制 (http://filmroellchen.eu/blog/mipselflut/#rate-limiting)
- 成功 (http://filmroellchen.eu/blog/mipselflut/#success)
- 脚注 (http://filmroellchen.eu/blog/mipselflut/#footnotes)
我参与Pixelflut领域已有数年。在AtGPN24 (https://entropia.de/GPN24) 上,包括我在内的一些成员成立了Pixelflut的“特别兴趣小组”,建立了Codeberg组织 (https://codeberg.org/pixelflut)、新网站 (https://pixelflut.org/),并开始起草RFC。与此同时,我入手了一台TP\-Link Archer C7 \(v2\)。这是一款简洁的一体式消费路由器,内置WiFi,特别值得注意的是它是一个得到良好支持的OpenWRT (https://openwrt.org/) 平台。难怪如此,其固件更新几乎不进行任何校验,因此你可以直接将OpenWRT刷入,重启后即可进入Linux系统。
于是某晚,我萌生了将两者结合的想法:在路由器上运行Pixelflut会怎样?路由器没有屏幕,因此运行Doom(毁灭战士)会很无聊。(考虑到只需编译一个超高可移植性的Linux Doom移植版,这可能还挺容易的。)那么,不如运行一些与网络相关的东西,而这正是路由器的本职工作。考虑到它只有一个700MHz的单核CPU和大约64MB内存可供实验,效果肯定*非常糟糕*,但它应该能运行起来!而且我可以通过网络将输出流回传到显示屏。
图1:*轻拍路由器*这台厉害的宝贝能塞下这么多像素
以下帖子将按时间顺序准确记述我在Archer C7上让Pixelflut运行起来的历程,包括我途中犯的所有错误以及学到的所有东西。
---
我选择breakwater (https://github.com/sbernauer/breakwater) 作为Pixelflut服务器,原因如下:
- 它是用Rust编写的,Rust可移植性很好。
- 我熟悉其代码库,可以轻松修改。
- 我与开发者是朋友,很可能可以直接提问,甚至提交PR :)
- breakwater已经有一个“sink”插件系统,可以方便地添加其他输出。
## 目标混淆
在我看来,OpenWRT基本就是Alpine Linux,使用musl (https://musl.libc.org/) C库。因此,我为`aarch64\-unknown\-linux\-musl`交叉编译了breakwater,只需简单地指定`cargo build \-\-target aarch64\-unknown\-linux\-musl \-\-release`。
如果你还不知道,这个神奇的字符串被称为“目标描述符”、“目标标识符”或“目标三元组”,因为很明显,它包含四个部分:
- CPU架构。此处:Aarch64,即64\-位ARM。
- 供应商。此处:我不知道Linus Torvalds是谁。
- 操作系统。此处:Linux。
- C库及其调用约定。此处:musl libc。
目标描述符告诉你正在为哪个目标编译代码,这在进行类似此处的交叉编译时尤为重要。举个例子,当今桌面系统最常见的三个目标分别是`x86\_64\-pc\-windows\-msvc`、`aarch64\-apple\-darwin`和`x86\_64\-unknown\-linux\-gnu`。如果你同时使用Rust和Web,可能也听说过`wasm32\-unknown\-unknown`。但也许有一天你真的想用Rust开始开发任天堂3DS游戏,那么你就得用`armv6k\-nintendo\-3ds`。或者你工作在某个神秘地方,需要`sparcv9\-sun\-solaris`。无论如何,你都需要识别正确的编译目标。
而这正是我没有做对的地方。
因为经过进一步研究,我发现Archer C7中的处理器——高通Atheros QCA9558(即OpenWRT中的ath79 (https://openwrt.org/docs/techref/targets/ath79) 平台)——既不是64\-位ARM核心,也不是32\-位ARM核心。(它显然不是x86,否则我会更惊讶。)
它是MIPS。一款实现MIPS32 Release 2和MIPS16e的24Kc系列MIPS核心。支持大端序和小端序,无硬件浮点,32个寄存器,体现RISC的精髓。这是一个现已消亡的架构,曾用于PlayStation 1和2、任天堂N64等经典游戏机,以及从2000年代到2010年代初的大量嵌入式系统。显然,24K曾是MIPS历史上最成功的核心系列之一。安息吧,MIPS,1984\-2021。它最大的成就可能不是其架构中可见的分支延迟槽,而是其对SPARC、ARM以及最重要的RISC\-V的巨大影响。
此刻,我对这个项目更加期待了。我们不仅拥有一个过时的架构,而且很可能还能读懂它,因为它与我了如指掌的RISC\-V架构共享许多指令助记符和整体操作原理。
MIPS远非冷门,因此Rust编译器支持相当不错。有好几个目标可供选择。我需要哪一个?
```
root@Vodkafone:~# uname -a
Linux Vodkafone 6.12.87 #0 Wed May 13 22:42:09 2026 mips GNU/Linux
```
`mips`,这——没什么帮助。
```
root@Vodkafone:~# file /bin/busybox
/bin/busybox: ELF 32-bit MSB executable, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, interpreter /lib/ld-musl-mips-sf.so.1, no section header
```
谢谢你帮我查阅OpenWRT文档。
实际上,我花了大约两个小时尝试不同方法才弄明白:
- 我尝试为`mipsel\-unknown\-linux\-musl`编译,这需要我构建一个自定义的Rust编译器,而后者又需要构建相应的GCC编译器,但我未能找到一个好的来源(AUR让我失望了)。
- 不知为何我尝试了`\-gnu`目标,但可以预料的是,当它确实需要glibc时我就卡住了,我无法编译它,即使有AUR的一些额外帮助也不行。(这有大量依赖,比如特定目标的Linux头文件,这实际上需要你进行部分Linux内核构建。)
- 我实际上找对了目标,但以为我的Rust编译器没有包含它,于是我又花了一段时间重新编译自定义`rustc`,这次编译器试图为无浮点支持的处理器生成浮点指令:
图2:我不知道`ldc1`是什么指令,但`f0`看起来确实像浮点寄存器,而`$4`=`x4`是栈指针。终于为我那些RISC\-V知识找到了用武之地!
- 我意识到我还需要一个链接器,最终重新发现了musl\-cross (https://musl.cc/),于是我快速修改了AUR的aarch64 musl cross (https://aur.archlinux.org/packages/aarch64-linux-musl-cross-bin) 包,改为安装`mips`版本。
- `breakwater\-parser\-c\-bindings`仍然有问题;你将在下文看到`-\-package breakwater`选项。
为了完整解释这一点(因为在最初的三个小时尝试中,这一点对我来说也不明显):MIPS是一个庞大的架构家族,也包括一个64\-位变种。这显然是32\-位变种,但从1984年到约2010年,存在许多不同版本的32\-位MIPS。最重要的是,所有32\-位MIPS处理器都支持*双端序*(bi\-endianness),意味着它们可以根据各种设置在小端模式或大端模式下运行。在QCA9558上,只支持大端模式;或者至少Linux和OpenWRT只使用大端模式(我没有进一步检查)。无论如何,出于一些令人困惑的原因,大端MIPS在目标标识符中被称为`mips`,而小端MIPS被称为`mipsel`。我在此正式将此项目命名为*MIPSelflut*,即使它实际上并不使用MIPSel。
## Breakwater崩溃
总之,在经过所有这些捣鼓和研究之后,我终于意识到正确的目标*是*官方rustup rustc内置的,你只需要构建自己的标准库。由于breakwater本来就在使用nightly版本,我甚至不需要切换工具链,我只需要:
```
$ cargo build -Zbuild-std --config 'target.mips-unknown-linux-musl.linker="mips-linux-musl-gcc"' --target mips-unknown-linux-musl --release --no-default-features --package breakwater
-------- snip --------
error[E0432]: unresolved imports `std::sync::atomic::AtomicI64`, `std::sync::atomic::AtomicU64`
--> /home/kleines/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/prometheus-0.13.4/src/atomic64.rs:7:25
|
7 | use std::sync::atomic::{AtomicI64 as StdAtomicI64, AtomicU64 as StdAtomicU64, Ordering};
| ^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^ no `AtomicU64` in `sync::atomic`
| |
| no `AtomicI64` in `sync::atomic`
|
= help: consider importing this struct through its public re-export instead:
crate::core::AtomicI64
= help: consider importing this struct through its public re-export instead:
crate::core::AtomicU64
help: a similar name exists in the module
|
7 - use std::sync::atomic::{AtomicI64 as StdAtomicI64, AtomicU64 as StdAtomicU64, Ordering};
7 + use std::sync::at
-------- snip --------
error: could not compile `prometheus` (lib) due to 3 previous errors
```
啊,好吧,那会太容易了。显然,32\-位MIPS不会有64\-位原子操作(事实上,我很惊讶它甚至有32\-位原子操作)。但就编译器错误而言,这实际上就是全部了:一旦我通过功能标志将prometheus功能移除,它就能编译了。
将二进制文件传输到路由器本身就是一个挑战:路由器闪存非常有限,所以我绝对不想把3.5MB的breakwater二进制文件放在那里。经过一番摸索,我让USB闪存驱动器工作了,现在我有64GB的临时空间。然而,总是插拔USB驱动器有点麻烦,而且没有SFTP(即`scp`不起作用),因此我想出了以下技巧:
```
cat target/mips-unknown-linux-musl/release/breakwater | ssh root@vodkafone ash -c 'tee > /mnt/somedrive/breakwater'
```
这个技巧非常经典,在我看来在系统管理员中广为人知。如果你想让大文件更高效,可以在ssh管道的两端都使用压缩二进制。`sha256sum`确认这也没有引入任何不需要的换行符。
好,开始:
```
root@Vodkafone:/mnt/somedrive# chmod +x breakwater
root@Vodkafone:/mnt/somedrive# file ./breakwater
./breakwater: ELF 32-bit MSB pie executable, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, interpreter /lib/ld-musl-mips.so.1, not stripped
root@Vodkafone:/mnt/somedrive# ./breakwater
-ash: ./breakwater: not found
```
... 抱歉?二进制文件*就在那儿*,你这笨蛋?
我不确定原因,但这触发了我模糊的记忆,或者只是我通用的Linux知识。如果你曾经在一个可执行文件上遇到这种错误——文件类型正确,位于正确的目录——你可能知道问题所在。我很快证实了我的怀疑:
```
root@Vodkafone:/mnt/somedrive# file /bin/busybox
/bin/busybox: ELF 32-bit MSB executable, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, interpreter /lib/ld-musl-mips-sf.so.1, no section header
```
剧透警告(如果你想自己找出问题):动态链接器(即“解释器”)错了。busybox正确使用了`/lib/ld\-musl\-mips\-sf\.so\.1`,而我新编译的breakwater使用了`/lib/ld\-musl\-mips\.so\.1`。区别在于中间的`\-sf`。据我所知,它代表`softfloat`(软浮点);因为这个处理器不支持浮点,浮点操作是通过软件模拟的。我查看了编译日志,它甚至警告目标使用软浮点。Rust构建系统内部似乎对使用软浮点还是硬浮点有些混淆;Rust目标文档指定这应该是一个默认软浮点的目标。考虑到大多数较旧的MIPS处理器(该目标仍然支持它们)没有浮点支持,就像24Kc一样,这很合理。
无论如何,通过在`RUSTFLAGS`中覆盖动态链接器可以快速修复:
```
RUSTFLAGS='-Clink-arg=-Wl,--dynamic-linker=/lib/ld-musl-mips-sf.so.1' cargo build -Zbuild-std --config 'target.mips-unknown-linux-musl.linker="mips-linux-musl-gcc"' --target mips-unknown-linux-musl --release --no-default-features --package breakwater
```
开始:
```
root@Vodkafone:/mnt/somedrive# file ./breakwater
breakwater: ELF 32-bit MSB pie executable, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, interpreter /lib/ld-musl-mips-sf.so.1, not stripped
root@Vodkafone:/mnt/somedrive# ./breakwater -f 10 --network-buffer-size 64000
2026-06-15T20:26:17.631397Z INFO new{listen_addresses=[[::]:1234] network_buffer_size=64000 max_connections_per_ip=None}: breakwater::server: started Pixelflut server
```
这是一个可以工作的breakwater!在MIPS上!
...它除了`PX`get之外没有其他方式输出画布。
而且它实际上也不工作。我的Pixelflut客户端hyperflut表示无法读回画布大小。手动尝试`nc`,服务器就是不响应,尽管第一轮测试表明连接明显正常,所以机器之间的TCP本身没问题。breakwater监听所有公共IPv6地址,与我可以测试的所有其他系统服务相同(例如SSH)。那里没有问题。
然后我开始调试接收逻辑,查看接收到了什么数据以及解析器对此说了什么。立刻,我有了顿悟。
```
2026-06-15T20:51:17.212134Z DEBUG handle_connection{ip=2a04:6ec0:271:e850:f420:9a86:97fe:2fb7 network_buffer_size=64000}: breakwater::server: handling new connection
2026-06-15T20:51:19.255604Z DEBUG handle_connection{ip=2a04:6ec0:271:e850:f420:9a86:97fe:2fb7 network_buffer_size=64000}: breakwater::server: read data buffer=[72, 69, 76, 80, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
2026-06-15T20:51:19.646435Z DEBUG handle_connection{ip=2a04:6ec0:271:e850:f420:9a86:97fe:2fb7 network_buffer_size=64000}: breakwater::server: read data buffer=[69, 76, 80, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
2026-06-15T20:51:19.925548Z DEBUG handle_connection{ip=2a04:6ec0:271:e850:f420:9a86:97fe:2fb7 network_buffer_size=64000}: breakwater::server: read data buffer=[76, 80, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
2026-06-15T20:51:42.340922Z DEBUG handle_connection{ip=2a04:6ec0:271:e850:f420:9a86:97fe:2fb7 network_buffer_size=64000}: breakwater::server: read data buffer=[80, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
2026-06-15T20:51:43.443933Z DEBUG handle_connection{ip=2a04:6ec0:271:e850:f420:9a86:97fe:2fb7 network_buffer_size=64000}: breakwater::server: read data buffer=[10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
2026-06-15T20:51:43.546475Z DEBUG handle_connection{ip=2a04:6ec0:271:e850:f420:9a86:97fe:2fb7 network_buffer_size=64000}: breakwater::server: read data buffer=[10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
2026-06-15T20:51:44.391550Z DEBUG handle_connection{ip=2a04:6ec0:271:e850:f420:9a86:97fe:2fb7 network_buffer_size=64000}: breakwater::server: read data buffer=[10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
2026-06-15T20:51:44.866467Z DEBUG handle_connection{ip=2a04:6ec0:271:e850:f420:9a86:97fe:2fb7 network_buffer_size=64000}: breakwater::server: read data buffer=[10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
2026-06-15T20:51:45.474012Z DEBUG handle_connection{ip=2a04:6ec0:271:e850:f420:9a86:97fe:2fb7 network_buffer_size=64000}: breakwater::server: read data buffer=[10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
2026-06-15T20:51:45.897812Z DEBUG handle_connection{ip=2a04:6ec0:271:e850:f420:9a86:97fe:2fb7 network_buffer_size=64000}: breakwater::server: read data buffer=[10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
2026-06-15T20:51:46.471996Z DEBUG handle_connection{ip=2a04:6ec0:271:e850:f420:9a86:97fe:2fb7 network_buffer_size=64000}: breakwater::server: read data buffer=[10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
2026-06-15T20:51:46.953748Z DEBUG handle_connection{ip=2a04:6ec0:271:e850:f420:9a86:97fe:2fb7 network_buffer_size=64000}: breakwater::server: read data buffer=[10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
2026-06-15T20:51:47.557784Z DEBUG handle_connection{ip=2a04:6ec0:271:e850:f420:9a86:97fe:2fb7 network_buffer_size=64000}: breakwater::server: read data buffer=[10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
2026-06-15T20:51:48.053634Z DEBUG handle_connection{ip=2a04:6ec0:271:e850:f420:9a86:97fe:2fb7 network_buffer_size=64000}: breakwater::server: read data buffer=[10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
2026-06-15T20:51:48.684178Z DEBUG handle_connection{ip=2a04:6ec0:271:e850:f420:9a86:97fe:2fb7 network_buffer_size=64000}: breakwater::server: read data buffer=[10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
2026-06-15T20:51:49.196084Z DEBUG handle_connection{ip=2a04:6ec0:271:e850:f420:9a86:97fe:2fb7 network_buffer_size=64000}: breakwater::server: read data buffer=[10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
2026-06-15T20:51:49.815445Z DEBUG handle_connection{ip=2a04:6ec0:271:e850:f420:9a86:97fe:2fb7 network_buffer_size=64000}: breakwater::server: read data buffer=[10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
2026-06-15T20:51:50.336727Z DEBUG handle_connection{ip=2a04:6ec0:271:e850:f420:9a86:97fe:2fb7 network_buffer_size=64000}: breakwater::server: read data buffer=[10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
2026-06-15T20:51:50.943684Z DEBUG handle_connection{ip=2a04:6ec0:271:e850:f420:9a86:97fe:2fb7 network_buffer_size=64000}: breakwater::server: read data buffer=[10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
2026-06-15T20:51:51.466788Z DEBUG handle_connection{ip=2a04:6ec0:271:e850:f420:9a86:97fe:2fb7 network_buffer_size=64000}: breakwater::server: read data buffer=[10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
2026-06-15T20:51:52.083317Z DEBUG handle_connection{ip=2a04:6ec0:271:e850:f420:9a86:97fe:2fb7 network_buffer_size=64000}: breakwater::server: read data buffer=[10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
2026-06-15T20:51:52.590773Z DEBUG handle_connection{ip=2a04:6ec0:271:e850:f420:9a86:97fe:2fb7 network_buffer_size=64000}: breakwater::server: read data buffer=[10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0,
相似文章
@realfxw: 出门在外想随时连家里的 NAS、调一下台式机里的 Ollama,或者开 Moonlight 串流,最烦这几件事: 没有公网 IPv4、大内网 NAT 环境复杂、开路由器端口映射又怕天天被全网脚本扫爆。 试试 Rust 写的轻量私有组网工具…
Lantunnel是一个用Rust编写的轻量私有组网工具,允许用户在无公网IPv4或复杂NAT环境下,安全访问家庭NAS、远程调用Ollama或进行游戏串流,通过P2P直连和加密中继避免端口暴露。
Rust 与 GBA:环境搭建与像素渲染
一份教程指南,讲解如何搭建 Rust 项目以构建能在 Game Boy Advance 上运行的 ROM,涵盖项目设置和像素渲染。
我们如何(及为何)将生产环境的C++前端基础设施重写为Rust
NearlyFreeSpeech.NET 将其生产环境的C++前端基础设施(nfsncore)重写为Rust,该系统负责所有传入请求的路由、缓存和访问控制。迁移的动机是Rust的安全性保证、性能、生态系统优势以及老化的C++代码库的局限性。
@tunguz: 看到这些推文后,我决定在我那台装有 RTX 1070 GPU 的老旧 Ubuntu 电脑上试试(就是那台我刚刚……
一位用户报告成功在较老的 RTX 1070 GPU 上本地运行 Qwen3 8B,展示了现代大语言模型在十年前的硬件上也能表现出不错的性能。
Qwen3.8-Flash-Next 宇宙街机随拍生成游戏测试
本文详述了在本地 Intel V620 GPU 上测试运行 Qwen3.8-Flash-Next AI 模型的实践,使用 OMP 工具链,模型依据一个粗略的提示词在约3小时内生成了一款3D游戏。