Skip to content

Commit ee5aea5

Browse files
Merge pull request #6 from Awesome-Embedded-Learning-Studio/feat/phase4
Feat/phase4
2 parents 47c9066 + cefcda0 commit ee5aea5

62 files changed

Lines changed: 4798 additions & 201 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CMakeLists.txt

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,19 @@ if(CFBOX_ENABLE_AWK)
3838
file(GLOB_RECURSE AWK_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/applets/awk/*.cpp)
3939
list(APPEND CFBOX_APPLET_SOURCES ${AWK_SOURCES})
4040
endif()
41+
if(CFBOX_ENABLE_INIT)
42+
file(GLOB_RECURSE INIT_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/applets/init/*.cpp)
43+
list(APPEND CFBOX_APPLET_SOURCES ${INIT_SOURCES})
44+
endif()
45+
if(CFBOX_ENABLE_TOP)
46+
file(GLOB_RECURSE TOP_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/applets/top/*.cpp)
47+
list(APPEND CFBOX_APPLET_SOURCES ${TOP_SOURCES})
48+
endif()
4149

4250
# Single-file applets
4351
foreach(applet IN LISTS CFBOX_APPLETS)
4452
string(TOUPPER "${applet}" APPLET_UPPER)
45-
if(NOT applet STREQUAL "sh" AND NOT applet STREQUAL "awk" AND CFBOX_ENABLE_${APPLET_UPPER})
53+
if(NOT applet STREQUAL "sh" AND NOT applet STREQUAL "awk" AND NOT applet STREQUAL "init" AND NOT applet STREQUAL "top" AND CFBOX_ENABLE_${APPLET_UPPER})
4654
list(APPEND CFBOX_APPLET_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/applets/${applet}.cpp)
4755
endif()
4856
endforeach()

Roadmap.md

Lines changed: 48 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ CFBox 是一个 C++23 BusyBox 替代品,当前版本有 78 个 applet。项目
1818
| 1 | POSIX Shell + Coreutils I ✅ | ~17 | Shell 引擎、进程管理、信号处理 | ~34 |
1919
| 2 | Coreutils II + findutils ✅ | ~44 | 流处理管线、校验和框架 | ~78 |
2020
| 3 | 归档 + 压缩 + 文本处理 ✅ | ~15 | 终端抽象、压缩框架 | ~93 |
21-
| 4 | vi 可视化编辑器 | 1 | TUI 框架、屏幕渲染、键盘映射 | ~94 |
22-
| 5 | 进程/Init + util-linux | ~38 | /proc 解析器 | ~132 |
23-
| 6 | 网络 + 登录 + 日志 | ~35 | Socket 抽象、HTTP 解析、shadow 密码 | ~167 |
21+
| 4 | 进程/Init + util-linux 🔧 | ~21/38 | /proc 解析器、init 系统、TUI 框架 | ~114 |
22+
| 5 | vi 可视化编辑器 | 1 | TUI 框架、屏幕渲染、键盘映射 | ~133 |
23+
| 6 | 网络 + 登录 + 日志 | ~35 | Socket 抽象、HTTP 解析、shadow 密码 | ~168 |
2424
| 7 | 剩余组件 + 集成验证 | ~40+ | POSIX 验证、容器替换测试 | ~200+ |
2525

26-
**当前状态**:Phase 0-3 已完成,93 个 applet,259 单元测试 + 54 集成测试全部通过
26+
**当前状态**:Phase 0-3 已完成,Phase 4 进行中。114 个 applet,318 单元测试全部通过。CFBox 已可在 QEMU 中作为 PID 1 运行完整 init 系统。TUI 框架已就绪,为 Phase 5 vi 编辑器奠定基础
2727

2828
---
2929

@@ -154,7 +154,48 @@ Shell 已实现为第一个多文件 applet(`src/applets/sh/`,8 个模块,
154154

155155
---
156156

157-
## Phase 4:vi 可视化编辑器
157+
## Phase 4:进程管理 + Init 系统 + util-linux 🔧
158+
159+
**目标**:构建让 CFBox 适合作为完整 init 环境的系统级工具,applet 数量翻倍。
160+
161+
### 基础设施 ✅
162+
- **`/proc` 解析器** `include/cfbox/proc.hpp` ✅:集中解析 /proc/meminfo, /proc/stat, /proc/[pid]/stat, /proc/[pid]/cmdline, /proc/[pid]/status, /proc/loadavg, /proc/uptime, /proc/mounts, /proc/diskstats, /proc/partitions
163+
- **TUI 框架** `include/cfbox/tui.hpp` ✅:全屏终端应用抽象(ScreenBuffer、Key 解析、TuiApp 虚基类、SIGWINCH 处理),top 和后续 vi/less 共用
164+
165+
### Init 系统 ✅
166+
- **inittab 解析器** ✅:解析 `/etc/inittab`,支持运行级别、respawn、once 条目
167+
- **运行级别管理** ✅:sysinit, boot, single-user, multi-user
168+
- **服务监控** ✅:进程监控 + respawn 能力(指数退避)
169+
- **关机/重启** ✅:SIGTERM → 等待 → SIGKILL → sync → 卸载 → reboot
170+
- **QEMU 兼容** ✅:无 inittab 时自动回退 smoke test 模式,保持 CI 兼容
171+
- **getty 集成**:在 TTY 上生成登录提示 — 待 Phase 6
172+
173+
### procps(已完成 15/16)
174+
`ps` ✅, `kill` ✅, `free` ✅, `uptime` ✅, `pgrep`/`pkill` ✅, `pidof` ✅, `sysctl` ✅, `pwdx` ✅, `pstree` ✅, `pmap` ✅, `fuser` ✅, `iostat` ✅, `watch` ✅, `top`
175+
176+
`lsof` — 待实现
177+
178+
### util-linux(已完成 6/30)
179+
`dmesg` ✅, `hexdump` ✅, `more` ✅, `rev` ✅, `cal` ✅, `renice`
180+
181+
**存储/块设备**(待实现):`mount`/`umount`, `blkid`, `blockdev`, `fdisk`, `mkfs`, `fsck`, `losetup`, `pivot_root`, `switch_root`, `swapon`/`swapoff`
182+
183+
**系统工具**(待实现):`flock`, `getopt`, `setsid`, `nsenter`, `unshare`, `mdev`, `lspci`, `lsusb`, `hwclock`, `rtcwake`, `taskset`, `chrt`, `ionice`, `last`, `mesg`, `wall`, `script`
184+
185+
### 验证 ✅(已通过)
186+
- CFBox 作为 PID 1 在 QEMU aarch64 中启动,运行 inittab,执行 sysinit 命令,spawn shell(respawn),处理关机 ✅
187+
- `ps aux` 输出与 procps 格式匹配 ✅
188+
- `free -h``uptime``kill -l``pidof``sysctl` 在 QEMU 中正常工作 ✅
189+
- 288 单元测试全部通过 ✅
190+
- `top -b -n 1` 在批处理模式下输出进程表 ✅
191+
- `pstree -p` 显示进程树和 PID ✅
192+
- `hexdump -C /dev/null``cal``rev` 功能正确 ✅
193+
- 318 单元测试全部通过 ✅
194+
- 容器测试:CFBox 替换 Alpine 容器中的 BusyBox — 待实现
195+
196+
---
197+
198+
## Phase 5:vi 可视化编辑器
158199

159200
**目标**:实现完整的 vi 可视化编辑器——CFBox 中最复杂的单一组件,需要独立的终端交互框架。
160201

@@ -171,7 +212,7 @@ Shell 已实现为第一个多文件 applet(`src/applets/sh/`,8 个模块,
171212
- **滚动**:半页/整页滚动(Ctrl-D/Ctrl-U/Ctrl-F/Ctrl-B),长行折行显示
172213

173214
### 基础设施
174-
- **TUI 框架** `include/cfbox/tui.hpp`:全屏终端应用抽象,vi/top/less 共用
215+
- TUI 框架已在 Phase 4 实现 ✅,vi 直接复用
175216
- 屏幕缓冲区管理、增量渲染
176217
- 键盘事件映射(普通键 + 转义序列解析)
177218
- 信号处理(SIGWINCH 终端大小变化)
@@ -197,36 +238,6 @@ src/applets/vi/
197238

198239
---
199240

200-
## Phase 5:进程管理 + Init 系统 + util-linux
201-
202-
**目标**:构建让 CFBox 适合作为完整 init 环境的系统级工具。
203-
204-
### Init 系统(完整)
205-
- **inittab 解析器**:解析 `/etc/inittab`,支持运行级别、respawn、once 条目
206-
- **运行级别管理**:sysinit, boot, single-user, multi-user
207-
- **服务监控**:进程监控 + respawn 能力
208-
- **关机/重启**:SIGTERM → 等待 → SIGKILL → sync → 卸载 → 重启
209-
- **getty 集成**:在 TTY 上生成登录提示
210-
211-
### procps(解析 `/proc` 文件系统)
212-
`ps`, `top`, `kill`, `free`, `uptime`, `pgrep`/`pkill`, `pidof`, `pmap`, `iostat`, `lsof`, `watch`, `sysctl`, `pstree`, `fuser`, `pwdx`
213-
214-
### util-linux
215-
**存储/块设备**`mount`/`umount`, `blkid`, `blockdev`, `dmesg`, `fdisk`, `mkfs`, `fsck`, `losetup`, `pivot_root`, `switch_root`, `swapon`/`swapoff`
216-
217-
**系统工具**`hexdump`, `more`, `flock`, `getopt`, `cal`, `rev`, `setsid`, `nsenter`, `unshare`, `mdev`, `lspci`, `lsusb`, `hwclock`, `rtcwake`, `taskset`, `chrt`, `ionice`, `renice`, `last`, `mesg`, `wall`, `script`
218-
219-
### 基础设施
220-
- **`/proc` 解析器** `include/cfbox/proc.hpp`:集中解析 /proc/meminfo, /proc/stat, /proc/[pid]/stat 等
221-
- TUI 框架已在 Phase 4 实现,top/less 可直接复用
222-
223-
### 验证
224-
- CFBox 作为 PID 1 在 QEMU 中启动,运行 inittab,生成 getty,处理关机
225-
- `ps aux` 输出与 procps 格式匹配
226-
- 容器测试:CFBox 替换 Alpine 容器中的 BusyBox,`docker run` 成功
227-
228-
---
229-
230241
## Phase 6:网络 + 登录管理 + 系统日志
231242

232243
**目标**:添加网络工具和用户/会话管理,使 CFBox 适用于网络启动系统和多用户环境。
@@ -297,7 +308,7 @@ src/applets/vi/
297308
|------|------|---------|
298309
| **Shell 复杂度** | 最高——5000+ 行代码 | 增量构建:先非交互 → 行编辑 → 作业控制,从第一天开始测试 POSIX shell 测试套件 |
299310
| **AWK 复杂度** | 高——第二复杂组件 | 从 POSIX awk 子集开始,实现解释器而非编译器 |
300-
| **vi 复杂度** | 高——终端处理微妙、独立 Phase 4 | 使用 Phase 3 的终端抽象 + 自建 TUI 框架,自动化按键注入测试,双缓冲 diff 驱动渲染 |
311+
| **vi 复杂度** | 高——终端处理微妙、独立 Phase 5 | 使用 Phase 3 的终端抽象 + Phase 4 的 TUI 框架,自动化按键注入测试,双缓冲 diff 驱动渲染 |
301312
| **二进制体积膨胀** | 中——200+ applet | Phase 0 的 CMake 配置允许裁剪,LTO 和死代码消除,每阶段监控体积 |
302313
| **跨平台边界情况** | 中——ioctl、/proc 格式差异 | 平台特性抽象到 `include/cfbox/` 头文件,每阶段三平台测试 |
303314
| **网络安全** | 中——wget/httpd 需要 TLS | 先做 HTTP-only,HTTPS 通过可选 mbedTLS 依赖,作为 CMake 选项 |

cmake/Config.cmake

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ set(CFBOX_APPLETS
2323
xargs
2424
gzip gunzip diff cmp patch ed tar cpio ar unzip
2525
awk
26+
free uptime kill pidof ps pgrep sysctl
27+
pwdx pstree pmap fuser iostat
28+
watch top
29+
dmesg hexdump more rev cal renice
2630
)
2731

2832
foreach(applet IN LISTS CFBOX_APPLETS)

cmake/compile/CompilerFlag.cmake

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ target_compile_options(cfbox_compiler_flags INTERFACE
3636
$<$<CONFIG:Debug>:-fno-sanitize-recover=all>
3737
)
3838

39+
target_link_options(cfbox_compiler_flags INTERFACE
40+
$<$<CONFIG:Debug>:-fsanitize=address,undefined>
41+
)
42+
3943
# ── Release-specific flags ────────────────────────────────────
4044
if(CFBOX_OPTIMIZE_FOR_SIZE)
4145
target_compile_options(cfbox_compiler_flags INTERFACE

configs/qemu-inittab

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# CFBox /etc/inittab — QEMU aarch64 virt machine test
2+
# Format: id:runlevels:action:process
3+
4+
# Note: /proc, /sys, /dev are mounted automatically by init's sysinit phase.
5+
# (mount applet is not yet available, init does it internally)
6+
7+
# Boot test — verify applets work under init
8+
::sysinit:/bin/echo "=== CFBox Init (inittab mode) ==="
9+
::sysinit:/bin/uname -a
10+
::sysinit:/bin/free -h
11+
::sysinit:/bin/uptime
12+
::sysinit:/bin/ps
13+
::sysinit:/bin/echo "=== Inittab tests PASSED ==="
14+
15+
# Phase 3: Spawn shell on serial console (respawn if killed)
16+
ttyAMA0::respawn:/bin/sh
17+
18+
# Signals
19+
::ctrlaltdel:/bin/echo "Ctrl-Alt-Del pressed, rebooting..."
20+
::shutdown:/bin/echo "Shutting down..."
21+
::shutdown:/bin/sync

include/cfbox/applet_config.hpp.in

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,23 @@
9393
#cmakedefine01 CFBOX_ENABLE_AR
9494
#cmakedefine01 CFBOX_ENABLE_UNZIP
9595
#cmakedefine01 CFBOX_ENABLE_AWK
96+
#cmakedefine01 CFBOX_ENABLE_FREE
97+
#cmakedefine01 CFBOX_ENABLE_UPTIME
98+
#cmakedefine01 CFBOX_ENABLE_KILL
99+
#cmakedefine01 CFBOX_ENABLE_PIDOF
100+
#cmakedefine01 CFBOX_ENABLE_PS
101+
#cmakedefine01 CFBOX_ENABLE_PGREP
102+
#cmakedefine01 CFBOX_ENABLE_SYSCTL
103+
#cmakedefine01 CFBOX_ENABLE_PWDX
104+
#cmakedefine01 CFBOX_ENABLE_PSTREE
105+
#cmakedefine01 CFBOX_ENABLE_PMAP
106+
#cmakedefine01 CFBOX_ENABLE_FUSER
107+
#cmakedefine01 CFBOX_ENABLE_IOSTAT
108+
#cmakedefine01 CFBOX_ENABLE_WATCH
109+
#cmakedefine01 CFBOX_ENABLE_TOP
110+
#cmakedefine01 CFBOX_ENABLE_DMESG
111+
#cmakedefine01 CFBOX_ENABLE_HEXDUMP
112+
#cmakedefine01 CFBOX_ENABLE_MORE
113+
#cmakedefine01 CFBOX_ENABLE_REV
114+
#cmakedefine01 CFBOX_ENABLE_CAL
115+
#cmakedefine01 CFBOX_ENABLE_RENICE

include/cfbox/applets.hpp

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,66 @@ extern auto unzip_main(int argc, char* argv[]) -> int;
271271
#if CFBOX_ENABLE_AWK
272272
extern auto awk_main(int argc, char* argv[]) -> int;
273273
#endif
274+
#if CFBOX_ENABLE_FREE
275+
extern auto free_main(int argc, char* argv[]) -> int;
276+
#endif
277+
#if CFBOX_ENABLE_UPTIME
278+
extern auto uptime_main(int argc, char* argv[]) -> int;
279+
#endif
280+
#if CFBOX_ENABLE_KILL
281+
extern auto kill_main(int argc, char* argv[]) -> int;
282+
#endif
283+
#if CFBOX_ENABLE_PIDOF
284+
extern auto pidof_main(int argc, char* argv[]) -> int;
285+
#endif
286+
#if CFBOX_ENABLE_PS
287+
extern auto ps_main(int argc, char* argv[]) -> int;
288+
#endif
289+
#if CFBOX_ENABLE_PGREP
290+
extern auto pgrep_main(int argc, char* argv[]) -> int;
291+
#endif
292+
#if CFBOX_ENABLE_SYSCTL
293+
extern auto sysctl_main(int argc, char* argv[]) -> int;
294+
#endif
295+
#if CFBOX_ENABLE_PWDX
296+
extern auto pwdx_main(int argc, char* argv[]) -> int;
297+
#endif
298+
#if CFBOX_ENABLE_PSTREE
299+
extern auto pstree_main(int argc, char* argv[]) -> int;
300+
#endif
301+
#if CFBOX_ENABLE_PMAP
302+
extern auto pmap_main(int argc, char* argv[]) -> int;
303+
#endif
304+
#if CFBOX_ENABLE_FUSER
305+
extern auto fuser_main(int argc, char* argv[]) -> int;
306+
#endif
307+
#if CFBOX_ENABLE_IOSTAT
308+
extern auto iostat_main(int argc, char* argv[]) -> int;
309+
#endif
310+
#if CFBOX_ENABLE_WATCH
311+
extern auto watch_main(int argc, char* argv[]) -> int;
312+
#endif
313+
#if CFBOX_ENABLE_TOP
314+
extern auto top_main(int argc, char* argv[]) -> int;
315+
#endif
316+
#if CFBOX_ENABLE_DMESG
317+
extern auto dmesg_main(int argc, char* argv[]) -> int;
318+
#endif
319+
#if CFBOX_ENABLE_HEXDUMP
320+
extern auto hexdump_main(int argc, char* argv[]) -> int;
321+
#endif
322+
#if CFBOX_ENABLE_MORE
323+
extern auto more_main(int argc, char* argv[]) -> int;
324+
#endif
325+
#if CFBOX_ENABLE_REV
326+
extern auto rev_main(int argc, char* argv[]) -> int;
327+
#endif
328+
#if CFBOX_ENABLE_CAL
329+
extern auto cal_main(int argc, char* argv[]) -> int;
330+
#endif
331+
#if CFBOX_ENABLE_RENICE
332+
extern auto renice_main(int argc, char* argv[]) -> int;
333+
#endif
274334

275335
// registry — one line per applet, conditionally compiled
276336
constexpr auto APPLET_REGISTRY = std::to_array<cfbox::applet::AppEntry>({
@@ -542,4 +602,65 @@ constexpr auto APPLET_REGISTRY = std::to_array<cfbox::applet::AppEntry>({
542602
#if CFBOX_ENABLE_AWK
543603
{"awk", awk_main, "pattern-directed scanning and processing language"},
544604
#endif
605+
#if CFBOX_ENABLE_FREE
606+
{"free", free_main, "display amount of free and used memory"},
607+
#endif
608+
#if CFBOX_ENABLE_UPTIME
609+
{"uptime", uptime_main, "tell how long the system has been running"},
610+
#endif
611+
#if CFBOX_ENABLE_KILL
612+
{"kill", kill_main, "send a signal to a process"},
613+
#endif
614+
#if CFBOX_ENABLE_PIDOF
615+
{"pidof", pidof_main, "find the process ID of a running program"},
616+
#endif
617+
#if CFBOX_ENABLE_PS
618+
{"ps", ps_main, "report a snapshot of current processes"},
619+
#endif
620+
#if CFBOX_ENABLE_PGREP
621+
{"pgrep", pgrep_main, "look up processes based on name"},
622+
{"pkill", pgrep_main, "signal processes based on name"},
623+
#endif
624+
#if CFBOX_ENABLE_SYSCTL
625+
{"sysctl", sysctl_main, "configure kernel parameters at runtime"},
626+
#endif
627+
#if CFBOX_ENABLE_PWDX
628+
{"pwdx", pwdx_main, "print working directory of a process"},
629+
#endif
630+
#if CFBOX_ENABLE_PSTREE
631+
{"pstree", pstree_main, "display a tree of processes"},
632+
#endif
633+
#if CFBOX_ENABLE_PMAP
634+
{"pmap", pmap_main, "display memory map of a process"},
635+
#endif
636+
#if CFBOX_ENABLE_FUSER
637+
{"fuser", fuser_main, "identify processes using files or sockets"},
638+
#endif
639+
#if CFBOX_ENABLE_IOSTAT
640+
{"iostat", iostat_main, "report CPU and I/O statistics"},
641+
#endif
642+
#if CFBOX_ENABLE_WATCH
643+
{"watch", watch_main, "execute a program periodically"},
644+
#endif
645+
#if CFBOX_ENABLE_TOP
646+
{"top", top_main, "display Linux processes"},
647+
#endif
648+
#if CFBOX_ENABLE_DMESG
649+
{"dmesg", dmesg_main, "print kernel ring buffer"},
650+
#endif
651+
#if CFBOX_ENABLE_HEXDUMP
652+
{"hexdump", hexdump_main, "display file contents in hexadecimal"},
653+
#endif
654+
#if CFBOX_ENABLE_MORE
655+
{"more", more_main, "file perusal filter for crt viewing"},
656+
#endif
657+
#if CFBOX_ENABLE_REV
658+
{"rev", rev_main, "reverse lines characterwise"},
659+
#endif
660+
#if CFBOX_ENABLE_CAL
661+
{"cal", cal_main, "display a calendar"},
662+
#endif
663+
#if CFBOX_ENABLE_RENICE
664+
{"renice", renice_main, "alter priority of running processes"},
665+
#endif
545666
});

0 commit comments

Comments
 (0)