Files
MeowOS-For-R3P2/patch_v2/meow_svcd/meow_svcd.md
T

11 KiB
Raw Blame History

meow_svcd — MeowOS 服务管理器守护进程

类 systemd/systemctl 的角色:由 supervisor(meow_bootmenu/launcher)托管 fork/exec 启动的一个独立进程;每个服务又是 svcd 的独立子进程。svcd 极简: 无 dlopen、无外部依赖(仅 POSIX + Linux 基础接口),交叉编译为 mipsel 静态 打进固件(不入卡——拔卡 svcd 本体不消失)。

二进制入口:patch_v2/meow_svcd/meow_svcd(mipsel 静态,~98KB,<200KB 固件阈值)。 宿主编译:patch_v2/meow_svcd/meow_svcd_host。

本阶段(M2.54)范围:守护 + 双源 services.d + 宿主测试。接入系统启动链已定: 固件预置 etc/init.d/S89meow_svcd(开机自启,myow_svcd -f 前台 + shell 重挂在 rcS 早期, 先于 S90meow_bootmenu——因 S90 exec 引导选单后阻塞 rcS,故须排在 S90 之前)。 直接由 bootmenu/launcher fork+exec + waitpid 托管的方案仍成立(改固件有风险), 作为备选——用 -f 前台即可被 waitpid。


1. 路径契约

用途 默认值 覆盖方式
TF 卡挂载点 /usr/data/mnt/sd_0(SPEC §1.2) --card / MEOW_SVCD_CARD
板载服务目录 /usr/data/meow/services.d(首启预置/Data 区) --board / MEOW_SVCD_BOARD
TF 服务目录 <card>/MeowOS/services.d/ 随 --card
控制 socket /tmp/meow_svcd.sock --sock / MEOW_SVCD_SOCK
状态文件 /tmp/meow_svcd.status --status / MEOW_SVCD_STATUS
pid 文件 /tmp/meow_svcd.pid --pidfile
svcd 自身日志 stderr(supervisor 捕获) 追加 --log / MEOW_SVCD_LOG

状态文件写板载 /tmp(tmpfs,存活期)或可配置;svcd 日志走 stderr 便于 supervisor 捕获(-f 前台时子进程 stdout/stderr 也落到同一 sink)。

2. services.d 目录式配置(双源:板载 + TF,板载优先)

服务配置两处都读,一个服务一个 <name>.conf:

  • 板载 /usr/data/meow/services.d/<name>.conf:Data 区,恒定存在、权威优先; 首启由固件 S89meow_svcd 预置(如 meow_mdns.conf)。拔卡不丢。
  • TF <card>/MeowOS/services.d/<name>.conf:随卡存在/消失。

同名遮蔽规则:先扫板载(权威),再扫 TF;若 TF 出现与板载同名服务 → 跳过 + WARN「 板载与 TF 都存在,采用板载」。无双源冲突时行为不变。

极简 key = value,#/; 注释,空行忽略;未知键忽略(前向兼容)。行内注释可用 \# 转义。

字段 必填 类型 说明 默认
exec ✅ 路径 服务二进制绝对路径(可卡上或固件) 无(缺省 → 跳过该服务)
args 否 串 空格切分,支持单/双引号与 \ 转义 无
name 否 串 仅备忘;实际名以文件名 <name>.conf 为准 =文件名
env 否 K=V 可多条;子进程 exec 前 setenv 无
enabled 否 1/0 0=永不自动启动 0
restart 否 枚举 always/on-fail/never on-fail
backoff_ms 否 int 崩溃后重启退避毫秒(固定退避) 1000
max_restart 否 int 连续重启次数上限,超限 → failed 停止;-1=无限 5
cap 否 串 能力串如 cap_net_bind_service,cap_net_raw;本阶段仅解析保留,不实装(属后续) 无
trigger 否 枚举 boot/card-mount/wifi-up card-mount

restart 语义:

  • always:无论退出码都重启(受 max_restart 约束)。
  • on-fail:仅非零退出/被信号杀(崩溃)重启;exit 0 不重启。
  • never:崩溃不重启(记为 failed)。

cap/wifi-up 均属扩展点:本阶段解析并保留字符串 / 实现一个 /sys/class/net/<iface>/operstate 的最小判定(本平台无 WiFi 接口时恒 0),真机能力绑定(capset)留待后续。

示例:

# 网络栈辅助服务(固件二进制,卡上有配置)
exec = /usr/bin/meow_netd
args = --foreground -v
env = MEOW_LOG_LEVEL=INFO
enabled = 1
restart = on-fail
backoff_ms = 2000
max_restart = 5
trigger = card-mount

# 可选 setcap(本阶段不实装)
# cap = cap_net_bind_service,cap_net_raw

板载 mDNS 应答器示例(固件预置 /usr/data/meow/services.d/meow_mdns.conf,首启建):

# 自研 IPv4-only mDNS 应答器(固件 /usr/bin/meow_mdns;板载服务,拔卡不丢)
exec = /usr/bin/meow_mdns
args = 
enabled = 1
restart = on-fail
backoff_ms = 2000
max_restart = 5
trigger = boot        # 板载服务:boot 触发不依赖卡(恒定存在);cap 空=root 绑 5353/组播
cap =

trigger 为单值枚举(boot|card-mount|wifi-up)。板载服务用 boot(恒存在即启动); wifi-up 属扩展点(/sys/class/net/<iface>/operstate),当前平台无无线接口恒 0。

3. 状态机

DISABLED   enabled=0,永不自动启动
STOPPED    未运行(触发不满足 / 被停 / 等待退避)
RUNNING    子进程存活
STOPPING   已发 SIGTERM,等退出(SVCD_STOP_GRACE_MS=2500 后 SIGKILL 兜底)
FAILED     崩溃且不再重启(超 max_restart / restart=never)

转换(主循环事件驱动 + 周期 tick):

  • 子进程死亡(waitpid 匹配):若无 stop_requested/restart_pending → 按 restart 策略决定重建(先进 backoff_ms 退避)或落 FAILED/STOPPED; 连续稳定运行 SVCD_STABLE_MS=30s 后清零 restart_count。
  • stop 命令:STOPPING → STOPPED(置 user_stopped,抑制触发自动拉起)。
  • restart 命令:STOPPING → 收尸后原地 respawn(无视崩溃策略,清零计数)。
  • 触发/禁用:tick 中 enabled && trigger 满足 && STOPPED && !user_stopped → 启动; 运行中但 !enabled || !trigger → 停。

4. 崩溃隔离

  • 独立进程:每个服务 fork()+execv(),svcd 只通过 waitpid/SIGCHLD 感知死亡; 无中间层内存共享、无 dlopen。
  • 信号健壮:SIGPIPE 置 SIG_IGN(服务关管道不杀 svcd);SIGTERM/SIGCHLD 处理器仅写自管道字节(async-signal-safe);poll 因信号中断 EINTR 续跑。
  • 不读服务输出:子进程继承 svcd stdio(stdout/stderr 落同一 sink),svcd 不 设管道读服务体——服务写多少都不进 svcd 内存,天然规避「输出撑爆 → svcd 崩」。
  • 后退避:重启间隔受 backoff_ms 约束,防崩溃-重启热循环拖垮系统。
  • 孤儿/僵死隔离:start_daemon() 设 PR_SET_CHILD_SUBREAPER——服务若派生孙进程, 在服务(直接子进程)退出后由 svcd 收尸而非 reparent 到 init,避免游离/僵死进程;失败仅记日志继续。
  • 服务崩绝不连带 supervisor:svcd 是 supervisor 的子进程且自身不死;服务是 svcd 的子进程,服务死只影响 svcd 内部一张表。

5. 事件触发(低成本轮询)

每 SVCD_SCAN_MS=1000ms 一轮:

  • 卡挂载:card_present()=目录存在 +(services.d 在 | 真实挂载点(子目录 st_dev 不同)| MEOW_SVCD_CARD_PRESENT=0/1 测试覆盖)。拔卡 → on_card_out() 优雅停所有服务并保留 restart_count/last_exit 状态;插卡 → scan_and_reconcile() 重建并按触发拉起。
  • wifi-up:读 /sys/class/net/<iface>/operstate,无无线接口恒 0(扩展点)。
  • boot:TF 配置在卡 → 随卡存在即启动(拔卡即停);板载配置(src=board)→ 恒定存在即启动(不依赖卡,拔卡保留,供 mdnsd 等常驻服务)。

6. CLI / 控制协议

守护进程默认后台常驻(无子命令即启动);-f 前台(supervisor 托管用)。控制走 AF_UNIX 单行文本:

meow_svcd status [name|all]       # 列出各服务+全局(daemon 未运行则打印状态文件)
meow_svcd reload                 # 重读卡配置
meow_svcd start  <name|all>
meow_svcd stop   <name|all>
meow_svcd restart <name|all>
meow_svcd pid

应答:OK / ERR no-such-service / 多列对齐表格。每服务一行:服务名/状态/pid/ 重启次数+max_restart/backoff_ms/trigger/来源(board|tf)/最近退出码/退出时间/exec 路径; TTY 时带 ANSI 配色(服务名=加粗青、RUNNING=绿、FAILED=红、STOPPED·STOPPING=黄、DISABLED=灰、 数字=黄、表头/分隔线=dim),stdout 非 TTY(重定向/SSH 管道)自动去色。

6.1 systemctl 式 CLI 用法(SSH 终端示例)

守护已由固件 etc/init.d/S89meow_svcd 开机自启,SSH 登录设备后直接敲命令即可,无需先知道 socket:

meow_svcd status               # 列出所有服务 + 全局状态(TTY 带色;管道/重定向自动去色)
# meow_svcd status
# card_present=1 wifi_up=0 services=3
# NAME      STATE    PID     RESTART BACKOFF  TRIGGER     SRC   EXIT   EXIT_TIME EXEC
# ------------------------------------------------------------------------------
# mdnsd     running  1234    0/5     2000ms   boot        board -      -         /usr/bin/meow_mdns
# meow_netd stopped  0       0/5     1000ms   card-mount  tf    -      -         /usr/bin/meow_netd
# ntpc      disabled 0       0/inf   1000ms   card-mount  tf    -      -         /usr/bin/ntpc

meow_svcd status mdnsd         # 只显示单个服务(其余列同;`status all` 等效于无参)

meow_svcd restart mdnsd         # 重启单个服务(如板载 mDNS 应答器)
meow_svcd start  meow_netd      # 启动单个服务
meow_svcd stop   all            # 停止全部服务
meow_svcd reload                # 重读板载 + TF 双源 services.d 配置
meow_svcd pid                   # 打印守护进程 pid
  • socket:控制走 AF_UNIX 单行文本,默认 /tmp/meow_svcd.sock(--sock/MEOW_SVCD_SOCK 可改)。 守护未运行时命令回退打印状态文件 /tmp/meow_svcd.status(或 card_present=0 services=0)并以退出码 1 返回。
  • 守护前台:-f/--foreground —— 守护自身跑前台,供 supervisor fork/exec+waitpid 托管; 默认(无子命令)则为后台常驻。
  • 应答:成功 OK(pid→pid 数字);服务不存在 ERR no-such-service;status 返回对齐表格, 行内含 state/pid/restart(重启计数)/exit(上次退出码)/trigger/来源/backoff_ms/exec。

7. 编译

./build_svcd.sh        # mipsel 静态 → meow_svcd(0 warning)
./build_svcd.sh host   # 宿主编译 → meow_svcd_host(集成测试)

后续(不在本阶段)

  • 接入 supervisor 启动链(已改由 etc/init.d/S89meow_svcd 开机自启;bootmenu/launcher fork+exec + waitpid 托管仍为备选)。
  • cap 真机实装(平台是否支持 capset/pthread caps 待确认;需先探测)。
  • wifi-up 事件细节(是否用 /proc/net/wireless / 重试文件,接口判定收紧)。
  • svcd/服务日志落位到卡 MeowOS/logs/ 的行为(当前 svcd 日志 stderr + 可选 --log)。