M2.54: 字体归MeowOS/fonts+SDK跟随+多字体+全屏?(等)+boot板载+状态栏28+亮度/音量修复+mDNS固化(meow_svcd双源+meow_mdns)+hostname=meowos+文档
This commit is contained in:
1 parent
064635b3c4
commit
9b8a1e5c8b
13 files changed
+807
-35
No files matched your search
@@ -8,9 +8,13 @@
|
||||
* - svcd 本身极简:无 dlopen、无外部依赖,仅依赖 POSIX + Linux 基础接口,
|
||||
* 交叉编译为 mipsel 静态(zig-mipsel-cc),打进固件(不入卡)。
|
||||
*
|
||||
* 配置来源(TF 卡,目录式):
|
||||
* `$CARD/MeowOS/services.d/<name>.conf`(默认 `CARD=/usr/data/mnt/sd_0`)。
|
||||
* 卡拔出 → svcd 优雅停止所托管服务并保留运行状态;插卡 → 自动重建服务。
|
||||
* 配置来源(双源,目录式;板载优先):
|
||||
* - 板载 `/usr/data/meow/services.d/<name>.conf`(Data 区,恒定存在,权威源);
|
||||
* - TF 卡 `$CARD/MeowOS/services.d/<name>.conf`(默认 `CARD=/usr/data/mnt/sd_0`)。
|
||||
* 扫描**两处都读**;同名服务**板载优先**(扫 TF 时若 name 已在板载 → 跳过 + WARN
|
||||
* 「<name> 板载与 TF 都存在,采用板载」)。无双源冲突时行为不变。
|
||||
* 卡拔出 → svcd 优雅停止所托管**卡上**服务并保留运行状态(板载服务视 trigger 保留);
|
||||
* 插卡 → 自动重建。
|
||||
*
|
||||
* .conf 字段(极简 key = value,'#'/';' 注释,见 meow_svcd.md 文档):
|
||||
* name / exec / args / env / enabled / restart / backoff_ms / max_restart /
|
||||
@@ -60,7 +64,9 @@
|
||||
|
||||
/* ---- 默认路径 / 常量 ---- */
|
||||
#define SVCD_CARD_DEFAULT "/usr/data/mnt/sd_0" /* TF 卡挂载点(SPEC §1.2) */
|
||||
#define SVCD_SERVICES_REL "MeowOS/services.d" /* 配置目录(用户定案目录式) */
|
||||
#define SVCD_SERVICES_REL "MeowOS/services.d" /* TF 配置目录(用户定案目录式) */
|
||||
#define SVCD_SERVICES_BOARD "/usr/data/meow/services.d" /* 板载配置目录(首启预置/Data 区) */
|
||||
#define SVCD_PATH_MAX 256 /* 服务源目录路径缓冲上限 */
|
||||
#define SVCD_SOCK_DEFAULT "/tmp/meow_svcd.sock"
|
||||
#define SVCD_STATUS_DEFAULT "/tmp/meow_svcd.status"
|
||||
#define SVCD_PIDFILE_DEFAULT "/tmp/meow_svcd.pid"
|
||||
@@ -111,6 +117,7 @@ typedef struct {
|
||||
int max_restart; /* <0=无限 */
|
||||
char cap[SVCD_CAP_MAX]; /* 解析保留;实装为后续任务 */
|
||||
char trigger[SVCD_TRIG_STR_MAX]; /* boot|card-mount|wifi-up */
|
||||
int src; /* 0=TF 卡, 1=板载(同名优先源) */
|
||||
|
||||
/* 运行状态 */
|
||||
pid_t pid;
|
||||
@@ -131,12 +138,14 @@ static int g_nsvc = 0;
|
||||
|
||||
/* 全局环境(可被 --card/--sock/--status 覆盖,亦读 env) */
|
||||
static char g_card[256] = SVCD_CARD_DEFAULT;
|
||||
static char g_board_dir[256] = SVCD_SERVICES_BOARD; /* 板载服务目录(--board/MEOW_SVCD_BOARD 可覆写) */
|
||||
static char g_sock[SVCD_SOCK_PATH_MAX] = SVCD_SOCK_DEFAULT;
|
||||
static char g_status[256] = SVCD_STATUS_DEFAULT;
|
||||
static char g_pidfile[256] = SVCD_PIDFILE_DEFAULT;
|
||||
static char g_log[256] = ""; /* 可选日志文件 */
|
||||
|
||||
static int g_card_present = 0;
|
||||
static int g_board_online = 0; /* 板载服务目录本帧可读 */
|
||||
static int g_wifi_up = 0;
|
||||
static int g_shutdown = 0;
|
||||
static int g_fg = 0; /* -f:前台(supervisor 托管) */
|
||||
@@ -513,9 +522,9 @@ static int trigger_satisfied(const svc_t *s)
|
||||
return g_card_present;
|
||||
case 'w': /* wifi-up */
|
||||
return g_card_present && g_wifi_up;
|
||||
case 'b': /* boot:配置在卡 → 随卡存在 */
|
||||
case 'b': /* boot:板载服务恒定存在,触发不依赖卡;TF 服务仍需卡 */
|
||||
default:
|
||||
return g_card_present;
|
||||
return (s->src == 1) ? 1 : g_card_present;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -570,11 +579,23 @@ static int card_present(void)
|
||||
return 0; /* 同文件系统空目录 = 未挂载/未用 */
|
||||
}
|
||||
|
||||
static int scan_directory(char out[][SVCD_NAME_MAX], int max)
|
||||
static int board_services_exist(void)
|
||||
{
|
||||
struct stat st;
|
||||
if (stat(g_board_dir, &st) != 0 || !S_ISDIR(st.st_mode)) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int name_in_list(const char *name, char list[][SVCD_NAME_MAX], int n)
|
||||
{
|
||||
for (int i = 0; i < n; i++)
|
||||
if (strcmp(list[i], name) == 0) return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 枚举某目录下的 *.conf,去除 .conf 得服务名。返回个数。 */
|
||||
static int scan_conf_names(const char *dir, char out[][SVCD_NAME_MAX], int max)
|
||||
{
|
||||
char dir[512];
|
||||
if (snprintf(dir, sizeof dir, "%s/%s", g_card, SVCD_SERVICES_REL)
|
||||
>= (int)sizeof dir) return 0;
|
||||
DIR *d = opendir(dir);
|
||||
if (!d) return 0;
|
||||
int n = 0;
|
||||
@@ -593,18 +614,48 @@ static int scan_directory(char out[][SVCD_NAME_MAX], int max)
|
||||
return n;
|
||||
}
|
||||
|
||||
/* 卡存在时(初始/插入/reload)重新读配置并调和服务表。 */
|
||||
/* 双源目录调和:板载(恒定存在、权威优先)先扫,卡上有则叠加扫 TF,
|
||||
* 同名服务 TF 被板载屏蔽(WARN 记录)。无双源冲突时行为不变。 */
|
||||
static void scan_and_reconcile(void)
|
||||
{
|
||||
char names[SVCD_MAX_SERVICES][SVCD_NAME_MAX];
|
||||
int n = scan_directory(names, SVCD_MAX_SERVICES);
|
||||
char srcdir[SVCD_MAX_SERVICES][SVCD_PATH_MAX]; /* 每服务实际 .conf 所在目录 */
|
||||
int n = 0;
|
||||
|
||||
if (board_services_exist()) {
|
||||
int nb = scan_conf_names(g_board_dir, names, SVCD_MAX_SERVICES);
|
||||
for (int i = 0; i < nb; i++)
|
||||
safe_strcpy(srcdir[i], sizeof srcdir[0], g_board_dir);
|
||||
n = nb;
|
||||
}
|
||||
|
||||
if (g_card_present) {
|
||||
char tfdir[SVCD_PATH_MAX];
|
||||
if (snprintf(tfdir, sizeof tfdir, "%s/%s", g_card, SVCD_SERVICES_REL)
|
||||
< (int)sizeof tfdir) {
|
||||
char tfnames[SVCD_MAX_SERVICES][SVCD_NAME_MAX];
|
||||
int nt = scan_conf_names(tfdir, tfnames, SVCD_MAX_SERVICES);
|
||||
for (int t = 0; t < nt; t++) {
|
||||
if (name_in_list(tfnames[t], names, n) >= 0) {
|
||||
svcd_log("%s 板载与 TF 都存在,采用板载", tfnames[t]);
|
||||
continue;
|
||||
}
|
||||
if (n >= SVCD_MAX_SERVICES) {
|
||||
svcd_log("service table full, drop %s", tfnames[t]); continue;
|
||||
}
|
||||
safe_strcpy(names[n], sizeof names[0], tfnames[t]);
|
||||
safe_strcpy(srcdir[n], sizeof srcdir[0], tfdir);
|
||||
n++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < g_nsvc; i++) g_svcs[i].in_config = 0;
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
char path[512];
|
||||
if (snprintf(path, sizeof path, "%s/%s/%s.conf", g_card, SVCD_SERVICES_REL,
|
||||
names[i]) >= (int)sizeof path) continue;
|
||||
if (snprintf(path, sizeof path, "%s/%s.conf", srcdir[i], names[i])
|
||||
>= (int)sizeof path) continue;
|
||||
int idx = find_svc(names[i]);
|
||||
if (idx < 0) {
|
||||
if (g_nsvc >= SVCD_MAX_SERVICES) { svcd_log("service table full, drop %s", names[i]); continue; }
|
||||
@@ -612,6 +663,7 @@ static void scan_and_reconcile(void)
|
||||
}
|
||||
svc_t tmp;
|
||||
if (load_conf(path, names[i], &tmp) != 0) { continue; }
|
||||
tmp.src = (strcmp(srcdir[i], g_board_dir) == 0) ? 1 : 0;
|
||||
svc_t *s = &g_svcs[idx];
|
||||
|
||||
/* 判定是否需重启(结构字段变化) */
|
||||
@@ -692,6 +744,8 @@ static void on_card_out(void)
|
||||
for (int i = 0; i < g_nsvc; i++) {
|
||||
svc_t *s = &g_svcs[i];
|
||||
s->restart_at_ms = 0;
|
||||
/* 拔卡后 trigger 仍满足的服务(板载-boot)不随卡停止(板载服务保留,MDNS 等常驻) */
|
||||
if (s->pid > 0 && trigger_satisfied(s)) continue;
|
||||
if (s->pid > 0) { stop_service(s, 0, 0); }
|
||||
else if (s->state == SV_RUNNING || s->state == SV_STOPPING) s->state = SV_STOPPED;
|
||||
}
|
||||
@@ -822,7 +876,7 @@ static void handle_connection(int fd)
|
||||
} else if (strcmp(line, "status") == 0) {
|
||||
cmd_status(fd);
|
||||
} else if (strcmp(line, "reload") == 0) {
|
||||
if (g_card_present) scan_and_reconcile();
|
||||
scan_and_reconcile();
|
||||
send_resp(fd, "OK\n");
|
||||
} else if (sp && strcmp(line, "start") == 0) {
|
||||
send_resp(fd, cmd_start(sp) == 0 ? "OK\n" : "ERR no-such-service\n");
|
||||
@@ -942,12 +996,13 @@ static int start_daemon(void)
|
||||
if (g_status_fd < 0) svcd_log("status file open fail: %s", strerror(errno));
|
||||
else set_cloexec(g_status_fd);
|
||||
|
||||
/* 初始卡探测 */
|
||||
/* 初始卡探测 + 板载服务目录状态 */
|
||||
g_card_present = card_present();
|
||||
if (g_card_present) scan_and_reconcile();
|
||||
g_board_online = board_services_exist();
|
||||
scan_and_reconcile(); /* 板载服务恒在,无卡也扫;卡上有则叠加扫 TF */
|
||||
|
||||
svcd_log("meow_svcd up: card=%s present=%d sock=%s pid=%d",
|
||||
g_card, g_card_present, g_sock, (int)getpid());
|
||||
svcd_log("meow_svcd up: card=%s present=%d board=%s sock=%s pid=%d",
|
||||
g_card, g_card_present, g_board_dir, g_sock, (int)getpid());
|
||||
|
||||
struct pollfd pfds[2];
|
||||
nfds_t nfds = 2;
|
||||
@@ -997,6 +1052,12 @@ static int start_daemon(void)
|
||||
if (present) { g_card_present = 1; svcd_log("card mounted, rebuild"); scan_and_reconcile(); }
|
||||
else { g_card_present = 0; on_card_out(); }
|
||||
}
|
||||
int bonline = board_services_exist();
|
||||
if (bonline != g_board_online) {
|
||||
g_board_online = bonline;
|
||||
svcd_log("board services dir %s %s, rebuild", g_board_dir, bonline ? "online" : "offline");
|
||||
scan_and_reconcile();
|
||||
}
|
||||
}
|
||||
tick_evaluate();
|
||||
build_status_file();
|
||||
@@ -1048,6 +1109,7 @@ static void usage(const char *argv0)
|
||||
" options:\n"
|
||||
" -f, --foreground stay in foreground (supervisor fork/exec 托管)\n"
|
||||
" --card <path> TF card mount point (default /usr/data/mnt/sd_0)\n"
|
||||
" --board <path> board services dir (default /usr/data/meow/services.d)\n"
|
||||
" --sock <path> control socket (default /tmp/meow_svcd.sock)\n"
|
||||
" --status <path> status file (default /tmp/meow_svcd.status)\n"
|
||||
" --pidfile <path> pid file (default /tmp/meow_svcd.pid)\n"
|
||||
@@ -1065,6 +1127,7 @@ int main(int argc, char **argv)
|
||||
const char *a = argv[i];
|
||||
if (strcmp(a, "-f") == 0 || strcmp(a, "--foreground") == 0) g_fg = 1;
|
||||
else if (strcmp(a, "--card") == 0 && i + 1 < argc) safe_strcpy(g_card, sizeof g_card, argv[++i]);
|
||||
else if (strcmp(a, "--board") == 0 && i + 1 < argc) safe_strcpy(g_board_dir, sizeof g_board_dir, argv[++i]);
|
||||
else if (strcmp(a, "--sock") == 0 && i + 1 < argc) safe_strcpy(g_sock, sizeof g_sock, argv[++i]);
|
||||
else if (strcmp(a, "--status") == 0 && i + 1 < argc) safe_strcpy(g_status, sizeof g_status, argv[++i]);
|
||||
else if (strcmp(a, "--pidfile") == 0 && i + 1 < argc) safe_strcpy(g_pidfile, sizeof g_pidfile, argv[++i]);
|
||||
@@ -1076,6 +1139,7 @@ int main(int argc, char **argv)
|
||||
/* env 覆盖 */
|
||||
const char *e;
|
||||
if ((e = getenv("MEOW_SVCD_CARD")) && e[0]) safe_strcpy(g_card, sizeof g_card, e);
|
||||
if ((e = getenv("MEOW_SVCD_BOARD")) && e[0]) safe_strcpy(g_board_dir, sizeof g_board_dir, e);
|
||||
if ((e = getenv("MEOW_SVCD_SOCK")) && e[0]) safe_strcpy(g_sock, sizeof g_sock, e);
|
||||
if ((e = getenv("MEOW_SVCD_STATUS")) && e[0]) safe_strcpy(g_status, sizeof g_status, e);
|
||||
if ((e = getenv("MEOW_SVCD_LOG")) && e[0]) safe_strcpy(g_log, sizeof g_log, e);
|
||||
|
||||
Reference in new issue
Block a user