mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-09-21 17:38:10 +00:00
refactor(shm): 变长块分配器 + 工具调用 funccall 调用帧(§13.2/§13.3)
按架构约束推进两步:
1) 分配器收回内核后,定长槽失去了唯一存在理由
(定长槽只是为了绕开"跨进程无法安全变长分配"),
于是 arena 换成**变长块分配器**:first-fit + 邻块合并,
块头 16B(size/state/owner/prevSize)。内核可以按需标定每块大小,
payload 不再受固定槽容量限制(旧上限 16KB)。
- Alloc/Put/Read/Free/ReclaimOwner 全在内核进程内,一把 sync.Mutex
- Free 走块链校验 offset 是已分配块的数据起点 + owner 匹配,
伪造引用不能改动分配器状态
- Read 允许块内偏移(调用帧的结果区就在帧块中间),但不许跨块边界
- arena 4MB,底层 memfd 惰性分配:未触碰的页不占物理内存
2) 工具调用 payload **始终**走共享内存,取消按大小切内联的分支。
按 funccall 模型,内核(caller)标定调用帧交给插件(callee):
[0, ArgsLen) 参数 JSON
[ArgsLen, Frame.Length) 结果区(内核预留的预算)
结果超出预算时插件才 `arena.alloc` 扩容块,引用上打
sharedRefFlagExpand 让内核单独归还。Cleaner 复用同一帧模型。
ToolInvokeParams.Args / ToolInvokeResult.Result 仅剩给直连 RPC 的
测试(process/bench 不建 Host);生产路径永远走帧。
测试:
- TestArena_*(分配/归属/回收/并发唯一/耗尽/超限/伪造 offset/
相邻合并/对齐/布局校验)
- TestPlugin_ToolInvokeArgsResultViaArena:大**小** payload 都经帧往返,
结果一致且 arena 归零("小 payload 同样走调用帧"是本轮行为变更)
- TestPlugin_ArenaAllocFreeAcrossProcess、TestE2E_* 保持通过
- 顺手修 process_test.go 一处预存 doc-comment 分段
This commit is contained in:
@ -30,8 +30,11 @@ type Host struct {
|
||||
seg *Segment // StageContext segment(位于 unified ctxData)
|
||||
shmSize int // 统一区域总大小
|
||||
|
||||
// arena 是跨进程共享槽池(§13.2 重设计)。分配/释放走共享位图 CAS,
|
||||
// 任意进程/goroutine 并发调用都安全,不需要任何锁。
|
||||
// arena 是跨进程共享内存分配器(§13.2 重设计),由内核独占管理:
|
||||
// 插件通过 RPC 申请/归还,不做任何分配决策。
|
||||
//
|
||||
// 分配与回收都在内核进程内进行,一把 mu 即可保证安全,
|
||||
// 不存在跨进程分配器那种“共享游标被两个进程各自更新”的竞态。
|
||||
arena *arenaRegion
|
||||
|
||||
// nextOwner 给每个插件进程分配一个不透明 owner ID,供 ReclaimOwner 使用。
|
||||
@ -77,15 +80,15 @@ func NewHost() (*Host, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 初始化 Exchange Arena 槽池
|
||||
arena, err := initArena(data, ur.arenaOff, ur.arenaCap, arenaDefaultSlotCount, arenaDefaultSlotSize)
|
||||
// 初始化 Exchange Arena(内核独占的变长块分配器)
|
||||
arena, err := initArena(data, ur.arenaOff, ur.arenaCap)
|
||||
if err != nil {
|
||||
freeShm(memfd, data)
|
||||
return nil, fmt.Errorf("槽池初始化: %w", err)
|
||||
return nil, fmt.Errorf("共享内存分配器初始化: %w", err)
|
||||
}
|
||||
if used, total := arena.Stats(); used != 0 || total != arenaDefaultSlotCount {
|
||||
if used, total := arena.Stats(); used != 0 || total != ur.arenaCap {
|
||||
freeShm(memfd, data)
|
||||
return nil, fmt.Errorf("槽池初始化异常:used=%d total=%d", used, total)
|
||||
return nil, fmt.Errorf("分配器初始化异常:used=%d total=%d", used, total)
|
||||
}
|
||||
|
||||
// 创建 StageContext segment(位于 SuperBlock 之后)
|
||||
|
||||
Reference in New Issue
Block a user