更好的进程系统

This commit is contained in:
2026-04-17 17:07:19 +08:00
parent bf41872d8d
commit f93af4a2a6
17 changed files with 1385 additions and 35 deletions

View File

@@ -362,6 +362,7 @@ set(RAMDISK_ROOT_APPS)
set(USER_SHELL_COMMAND_APPS
help args ls cat grep head tail wc cut uniq sort pwd cd exec pid spawn wait sleep yield
bg fg jobs kill ps top
shutdown restart exit clear ansi ansitest wavplay fastfetch memstat fsstat taskstat userstat
shstat stats tty dmesg kbdstat mkdir touch write append cp mv rm
)

96
cleonos/c/apps/bg_main.c Normal file
View File

@@ -0,0 +1,96 @@
#include "cmd_runtime.h"
static int ush_cmd_bg(const ush_state *sh, const char *arg) {
char target[USH_PATH_MAX];
char argv_line[USH_ARG_MAX];
char env_line[USH_PATH_MAX + 32ULL];
const char *rest = "";
char path[USH_PATH_MAX];
u64 pid;
if (sh == (const ush_state *)0 || arg == (const char *)0 || arg[0] == '\0') {
ush_writeln("bg: usage bg <path|name> [args...]");
return 0;
}
if (ush_split_first_and_rest(arg, target, (u64)sizeof(target), &rest) == 0) {
ush_writeln("bg: usage bg <path|name> [args...]");
return 0;
}
argv_line[0] = '\0';
if (rest != (const char *)0 && rest[0] != '\0') {
ush_copy(argv_line, (u64)sizeof(argv_line), rest);
}
if (ush_resolve_exec_path(sh, target, path, (u64)sizeof(path)) == 0) {
ush_writeln("bg: invalid target");
return 0;
}
if (ush_path_is_under_system(path) != 0) {
ush_writeln("bg: /system/*.elf is kernel-mode (KELF), not user-exec");
return 0;
}
env_line[0] = '\0';
ush_copy(env_line, (u64)sizeof(env_line), "PWD=");
ush_copy(env_line + 4, (u64)(sizeof(env_line) - 4ULL), sh->cwd);
pid = cleonos_sys_spawn_pathv(path, argv_line, env_line);
if (pid == (u64)-1) {
ush_writeln("bg: request failed");
return 0;
}
ush_write("[");
ush_write_hex_u64(pid);
ush_write("] ");
ush_writeln(path);
return 1;
}
int cleonos_app_main(void) {
ush_cmd_ctx ctx;
ush_cmd_ret ret;
ush_state sh;
char initial_cwd[USH_PATH_MAX];
int has_context = 0;
int success = 0;
const char *arg = "";
ush_zero(&ctx, (u64)sizeof(ctx));
ush_zero(&ret, (u64)sizeof(ret));
ush_init_state(&sh);
ush_copy(initial_cwd, (u64)sizeof(initial_cwd), sh.cwd);
if (ush_command_ctx_read(&ctx) != 0) {
if (ctx.cmd[0] != '\0' && ush_streq(ctx.cmd, "bg") != 0) {
has_context = 1;
arg = ctx.arg;
if (ctx.cwd[0] == '/') {
ush_copy(sh.cwd, (u64)sizeof(sh.cwd), ctx.cwd);
ush_copy(initial_cwd, (u64)sizeof(initial_cwd), sh.cwd);
}
}
}
success = ush_cmd_bg(&sh, arg);
if (has_context != 0) {
if (ush_streq(sh.cwd, initial_cwd) == 0) {
ret.flags |= USH_CMD_RET_FLAG_CWD;
ush_copy(ret.cwd, (u64)sizeof(ret.cwd), sh.cwd);
}
if (sh.exit_requested != 0) {
ret.flags |= USH_CMD_RET_FLAG_EXIT;
ret.exit_code = sh.exit_code;
}
(void)ush_command_ret_write(&ret);
}
return (success != 0) ? 0 : 1;
}

163
cleonos/c/apps/fg_main.c Normal file
View File

@@ -0,0 +1,163 @@
#include "cmd_runtime.h"
static int ush_fg_is_user_path(const char *path) {
if (path == (const char *)0 || path[0] != '/') {
return 0;
}
if (path[1] == 's' && path[2] == 'y' && path[3] == 's' && path[4] == 't' && path[5] == 'e' && path[6] == 'm' &&
(path[7] == '/' || path[7] == '\0')) {
return 0;
}
if (path[1] == 'd' && path[2] == 'r' && path[3] == 'i' && path[4] == 'v' && path[5] == 'e' && path[6] == 'r' &&
(path[7] == '/' || path[7] == '\0')) {
return 0;
}
return 1;
}
static int ush_fg_pick_latest_job(u64 *out_pid) {
u64 proc_count;
u64 tty_active;
u64 i;
u64 best = 0ULL;
if (out_pid == (u64 *)0) {
return 0;
}
*out_pid = 0ULL;
proc_count = cleonos_sys_proc_count();
tty_active = cleonos_sys_tty_active();
for (i = 0ULL; i < proc_count; i++) {
u64 pid = 0ULL;
cleonos_proc_snapshot snap;
if (cleonos_sys_proc_pid_at(i, &pid) == 0ULL || pid == 0ULL) {
continue;
}
if (cleonos_sys_proc_snapshot(pid, &snap, (u64)sizeof(snap)) == 0ULL) {
continue;
}
if (snap.tty_index != tty_active) {
continue;
}
if (ush_fg_is_user_path(snap.path) == 0) {
continue;
}
if (snap.state != CLEONOS_PROC_STATE_PENDING && snap.state != CLEONOS_PROC_STATE_RUNNING) {
continue;
}
if (best == 0ULL || snap.pid > best) {
best = snap.pid;
}
}
if (best == 0ULL) {
return 0;
}
*out_pid = best;
return 1;
}
static int ush_fg_wait_pid(u64 pid) {
for (;;) {
u64 status = (u64)-1;
u64 wait_ret = cleonos_sys_wait_pid(pid, &status);
if (wait_ret == (u64)-1) {
ush_writeln("fg: pid not found");
return 0;
}
if (wait_ret == 1ULL) {
ush_write("fg: done [");
ush_write_hex_u64(pid);
ush_writeln("]");
if ((status & (1ULL << 63)) != 0ULL) {
ush_print_kv_hex(" SIGNAL", status & 0xFFULL);
ush_print_kv_hex(" VECTOR", (status >> 8) & 0xFFULL);
ush_print_kv_hex(" ERROR", (status >> 16) & 0xFFFFULL);
} else {
ush_print_kv_hex(" STATUS", status);
}
return 1;
}
(void)cleonos_sys_sleep_ticks(1ULL);
}
}
static int ush_cmd_fg(const char *arg) {
u64 pid = 0ULL;
if (arg != (const char *)0 && arg[0] != '\0') {
if (ush_parse_u64_dec(arg, &pid) == 0 || pid == 0ULL) {
ush_writeln("fg: usage fg [pid]");
return 0;
}
} else {
if (ush_fg_pick_latest_job(&pid) == 0) {
ush_writeln("fg: no active background job");
return 0;
}
}
ush_write("fg: waiting [");
ush_write_hex_u64(pid);
ush_writeln("]");
return ush_fg_wait_pid(pid);
}
int cleonos_app_main(void) {
ush_cmd_ctx ctx;
ush_cmd_ret ret;
ush_state sh;
char initial_cwd[USH_PATH_MAX];
int has_context = 0;
int success = 0;
const char *arg = "";
ush_zero(&ctx, (u64)sizeof(ctx));
ush_zero(&ret, (u64)sizeof(ret));
ush_init_state(&sh);
ush_copy(initial_cwd, (u64)sizeof(initial_cwd), sh.cwd);
if (ush_command_ctx_read(&ctx) != 0) {
if (ctx.cmd[0] != '\0' && ush_streq(ctx.cmd, "fg") != 0) {
has_context = 1;
arg = ctx.arg;
if (ctx.cwd[0] == '/') {
ush_copy(sh.cwd, (u64)sizeof(sh.cwd), ctx.cwd);
ush_copy(initial_cwd, (u64)sizeof(initial_cwd), sh.cwd);
}
}
}
success = ush_cmd_fg(arg);
if (has_context != 0) {
if (ush_streq(sh.cwd, initial_cwd) == 0) {
ret.flags |= USH_CMD_RET_FLAG_CWD;
ush_copy(ret.cwd, (u64)sizeof(ret.cwd), sh.cwd);
}
if (sh.exit_requested != 0) {
ret.flags |= USH_CMD_RET_FLAG_EXIT;
ret.exit_code = sh.exit_code;
}
(void)ush_command_ret_write(&ret);
}
return (success != 0) ? 0 : 1;
}

View File

@@ -27,8 +27,10 @@ static int ush_cmd_help(void) {
ush_writeln(" mv <src> <dst> (/temp only)");
ush_writeln(" rm <path> (/temp only)");
ush_writeln(" pid");
ush_writeln(" spawn <path|name> [args...]");
ush_writeln(" wait <pid>");
ush_writeln(" spawn <path|name> [args...] / bg <path|name> [args...]");
ush_writeln(" wait <pid> / fg [pid]");
ush_writeln(" kill <pid> [signal]");
ush_writeln(" jobs [-a] / ps [-a] [-u] / top [--once] [-n loops] [-d ticks]");
ush_writeln(" sleep <ticks>");
ush_writeln(" yield");
ush_writeln(" shutdown / restart");

142
cleonos/c/apps/jobs_main.c Normal file
View File

@@ -0,0 +1,142 @@
#include "cmd_runtime.h"
static int ush_jobs_is_user_path(const char *path) {
if (path == (const char *)0 || path[0] != '/') {
return 0;
}
if (path[1] == 's' && path[2] == 'y' && path[3] == 's' && path[4] == 't' && path[5] == 'e' && path[6] == 'm' &&
(path[7] == '/' || path[7] == '\0')) {
return 0;
}
if (path[1] == 'd' && path[2] == 'r' && path[3] == 'i' && path[4] == 'v' && path[5] == 'e' && path[6] == 'r' &&
(path[7] == '/' || path[7] == '\0')) {
return 0;
}
return 1;
}
static const char *ush_jobs_state_name(u64 state) {
if (state == CLEONOS_PROC_STATE_PENDING) {
return "PENDING";
}
if (state == CLEONOS_PROC_STATE_RUNNING) {
return "RUNNING";
}
if (state == CLEONOS_PROC_STATE_EXITED) {
return "EXITED ";
}
return "UNUSED ";
}
static int ush_cmd_jobs(const char *arg) {
u64 proc_count;
u64 tty_active = cleonos_sys_tty_active();
u64 i;
u64 shown = 0ULL;
int include_exited = 0;
if (arg != (const char *)0 && arg[0] != '\0') {
if (ush_streq(arg, "-a") != 0 || ush_streq(arg, "--all") != 0) {
include_exited = 1;
} else {
ush_writeln("jobs: usage jobs [-a|--all]");
return 0;
}
}
proc_count = cleonos_sys_proc_count();
ush_writeln("jobs:");
for (i = 0ULL; i < proc_count; i++) {
u64 pid = 0ULL;
cleonos_proc_snapshot snap;
const char *state_name;
if (cleonos_sys_proc_pid_at(i, &pid) == 0ULL || pid == 0ULL) {
continue;
}
if (cleonos_sys_proc_snapshot(pid, &snap, (u64)sizeof(snap)) == 0ULL) {
continue;
}
if (ush_jobs_is_user_path(snap.path) == 0) {
continue;
}
if (snap.tty_index != tty_active) {
continue;
}
if (include_exited == 0 && snap.state == CLEONOS_PROC_STATE_EXITED) {
continue;
}
state_name = ush_jobs_state_name(snap.state);
ush_write("[");
ush_write_hex_u64(snap.pid);
ush_write("] ");
ush_write(state_name);
ush_write(" ");
ush_write(snap.path);
if (snap.state == CLEONOS_PROC_STATE_EXITED) {
ush_write(" status=");
ush_write_hex_u64(snap.exit_status);
}
ush_write_char('\n');
shown++;
}
if (shown == 0ULL) {
ush_writeln("(no jobs)");
}
return 1;
}
int cleonos_app_main(void) {
ush_cmd_ctx ctx;
ush_cmd_ret ret;
ush_state sh;
char initial_cwd[USH_PATH_MAX];
int has_context = 0;
int success = 0;
const char *arg = "";
ush_zero(&ctx, (u64)sizeof(ctx));
ush_zero(&ret, (u64)sizeof(ret));
ush_init_state(&sh);
ush_copy(initial_cwd, (u64)sizeof(initial_cwd), sh.cwd);
if (ush_command_ctx_read(&ctx) != 0) {
if (ctx.cmd[0] != '\0' && ush_streq(ctx.cmd, "jobs") != 0) {
has_context = 1;
arg = ctx.arg;
if (ctx.cwd[0] == '/') {
ush_copy(sh.cwd, (u64)sizeof(sh.cwd), ctx.cwd);
ush_copy(initial_cwd, (u64)sizeof(initial_cwd), sh.cwd);
}
}
}
success = ush_cmd_jobs(arg);
if (has_context != 0) {
if (ush_streq(sh.cwd, initial_cwd) == 0) {
ret.flags |= USH_CMD_RET_FLAG_CWD;
ush_copy(ret.cwd, (u64)sizeof(ret.cwd), sh.cwd);
}
if (sh.exit_requested != 0) {
ret.flags |= USH_CMD_RET_FLAG_EXIT;
ret.exit_code = sh.exit_code;
}
(void)ush_command_ret_write(&ret);
}
return (success != 0) ? 0 : 1;
}

View File

@@ -0,0 +1,94 @@
#include "cmd_runtime.h"
static int ush_cmd_kill(const char *arg) {
char pid_text[USH_PATH_MAX];
const char *rest = "";
u64 pid;
u64 signal = 15ULL;
u64 ret;
if (arg == (const char *)0 || arg[0] == '\0') {
ush_writeln("kill: usage kill <pid> [signal]");
return 0;
}
if (ush_split_first_and_rest(arg, pid_text, (u64)sizeof(pid_text), &rest) == 0) {
ush_writeln("kill: usage kill <pid> [signal]");
return 0;
}
if (ush_parse_u64_dec(pid_text, &pid) == 0 || pid == 0ULL) {
ush_writeln("kill: invalid pid");
return 0;
}
if (rest != (const char *)0 && rest[0] != '\0') {
if (ush_parse_u64_dec(rest, &signal) == 0 || signal > 255ULL) {
ush_writeln("kill: invalid signal");
return 0;
}
}
ret = cleonos_sys_proc_kill(pid, signal);
if (ret == (u64)-1) {
ush_writeln("kill: pid not found");
return 0;
}
if (ret == 0ULL) {
ush_writeln("kill: target cannot be terminated right now");
return 0;
}
ush_write("kill: sent signal ");
ush_write_hex_u64(signal);
ush_write(" to ");
ush_write_hex_u64(pid);
ush_write_char('\n');
return 1;
}
int cleonos_app_main(void) {
ush_cmd_ctx ctx;
ush_cmd_ret ret;
ush_state sh;
char initial_cwd[USH_PATH_MAX];
int has_context = 0;
int success = 0;
const char *arg = "";
ush_zero(&ctx, (u64)sizeof(ctx));
ush_zero(&ret, (u64)sizeof(ret));
ush_init_state(&sh);
ush_copy(initial_cwd, (u64)sizeof(initial_cwd), sh.cwd);
if (ush_command_ctx_read(&ctx) != 0) {
if (ctx.cmd[0] != '\0' && ush_streq(ctx.cmd, "kill") != 0) {
has_context = 1;
arg = ctx.arg;
if (ctx.cwd[0] == '/') {
ush_copy(sh.cwd, (u64)sizeof(sh.cwd), ctx.cwd);
ush_copy(initial_cwd, (u64)sizeof(initial_cwd), sh.cwd);
}
}
}
success = ush_cmd_kill(arg);
if (has_context != 0) {
if (ush_streq(sh.cwd, initial_cwd) == 0) {
ret.flags |= USH_CMD_RET_FLAG_CWD;
ush_copy(ret.cwd, (u64)sizeof(ret.cwd), sh.cwd);
}
if (sh.exit_requested != 0) {
ret.flags |= USH_CMD_RET_FLAG_EXIT;
ret.exit_code = sh.exit_code;
}
(void)ush_command_ret_write(&ret);
}
return (success != 0) ? 0 : 1;
}

191
cleonos/c/apps/ps_main.c Normal file
View File

@@ -0,0 +1,191 @@
#include "cmd_runtime.h"
static int ush_ps_is_user_path(const char *path) {
if (path == (const char *)0 || path[0] != '/') {
return 0;
}
if (path[1] == 's' && path[2] == 'y' && path[3] == 's' && path[4] == 't' && path[5] == 'e' && path[6] == 'm' &&
(path[7] == '/' || path[7] == '\0')) {
return 0;
}
if (path[1] == 'd' && path[2] == 'r' && path[3] == 'i' && path[4] == 'v' && path[5] == 'e' && path[6] == 'r' &&
(path[7] == '/' || path[7] == '\0')) {
return 0;
}
return 1;
}
static const char *ush_ps_state_name(u64 state) {
if (state == CLEONOS_PROC_STATE_PENDING) {
return "PEND";
}
if (state == CLEONOS_PROC_STATE_RUNNING) {
return "RUN ";
}
if (state == CLEONOS_PROC_STATE_EXITED) {
return "EXIT";
}
return "UNKN";
}
static int ush_ps_next_token(const char **io_cursor, char *out, u64 out_size) {
const char *p;
u64 n = 0ULL;
if (io_cursor == (const char **)0 || out == (char *)0 || out_size == 0ULL) {
return 0;
}
out[0] = '\0';
p = *io_cursor;
if (p == (const char *)0) {
return 0;
}
while (*p != '\0' && ush_is_space(*p) != 0) {
p++;
}
if (*p == '\0') {
*io_cursor = p;
return 0;
}
while (*p != '\0' && ush_is_space(*p) == 0) {
if (n + 1ULL < out_size) {
out[n++] = *p;
}
p++;
}
out[n] = '\0';
*io_cursor = p;
return 1;
}
static void ush_ps_print_one(const cleonos_proc_snapshot *snap) {
if (snap == (const cleonos_proc_snapshot *)0) {
return;
}
ush_write("PID=");
ush_write_hex_u64(snap->pid);
ush_write(" PPID=");
ush_write_hex_u64(snap->ppid);
ush_write(" ST=");
ush_write(ush_ps_state_name(snap->state));
ush_write(" TTY=");
ush_write_hex_u64(snap->tty_index);
ush_write(" RT=");
ush_write_hex_u64(snap->runtime_ticks);
ush_write(" MEM=");
ush_write_hex_u64(snap->mem_bytes);
if (snap->state == CLEONOS_PROC_STATE_EXITED) {
ush_write(" EXIT=");
ush_write_hex_u64(snap->exit_status);
}
ush_write(" PATH=");
ush_writeln(snap->path);
}
static int ush_cmd_ps(const char *arg) {
u64 proc_count;
u64 i;
u64 shown = 0ULL;
int include_exited = 0;
int only_user = 0;
const char *cursor = arg;
char token[USH_PATH_MAX];
while (ush_ps_next_token(&cursor, token, (u64)sizeof(token)) != 0) {
if (ush_streq(token, "-a") != 0 || ush_streq(token, "--all") != 0) {
include_exited = 1;
} else if (ush_streq(token, "-u") != 0 || ush_streq(token, "--user") != 0) {
only_user = 1;
} else {
ush_writeln("ps: usage ps [-a|--all] [-u|--user]");
return 0;
}
}
proc_count = cleonos_sys_proc_count();
ush_writeln("ps:");
for (i = 0ULL; i < proc_count; i++) {
u64 pid = 0ULL;
cleonos_proc_snapshot snap;
if (cleonos_sys_proc_pid_at(i, &pid) == 0ULL || pid == 0ULL) {
continue;
}
if (cleonos_sys_proc_snapshot(pid, &snap, (u64)sizeof(snap)) == 0ULL) {
continue;
}
if (include_exited == 0 && snap.state == CLEONOS_PROC_STATE_EXITED) {
continue;
}
if (only_user != 0 && ush_ps_is_user_path(snap.path) == 0) {
continue;
}
ush_ps_print_one(&snap);
shown++;
}
if (shown == 0ULL) {
ush_writeln("(no process)");
}
return 1;
}
int cleonos_app_main(void) {
ush_cmd_ctx ctx;
ush_cmd_ret ret;
ush_state sh;
char initial_cwd[USH_PATH_MAX];
int has_context = 0;
int success = 0;
const char *arg = "";
ush_zero(&ctx, (u64)sizeof(ctx));
ush_zero(&ret, (u64)sizeof(ret));
ush_init_state(&sh);
ush_copy(initial_cwd, (u64)sizeof(initial_cwd), sh.cwd);
if (ush_command_ctx_read(&ctx) != 0) {
if (ctx.cmd[0] != '\0' && ush_streq(ctx.cmd, "ps") != 0) {
has_context = 1;
arg = ctx.arg;
if (ctx.cwd[0] == '/') {
ush_copy(sh.cwd, (u64)sizeof(sh.cwd), ctx.cwd);
ush_copy(initial_cwd, (u64)sizeof(initial_cwd), sh.cwd);
}
}
}
success = ush_cmd_ps(arg);
if (has_context != 0) {
if (ush_streq(sh.cwd, initial_cwd) == 0) {
ret.flags |= USH_CMD_RET_FLAG_CWD;
ush_copy(ret.cwd, (u64)sizeof(ret.cwd), sh.cwd);
}
if (sh.exit_requested != 0) {
ret.flags |= USH_CMD_RET_FLAG_EXIT;
ret.exit_code = sh.exit_code;
}
(void)ush_command_ret_write(&ret);
}
return (success != 0) ? 0 : 1;
}

View File

@@ -152,8 +152,10 @@ static int ush_cmd_help(void) {
ush_writeln(" mv <src> <dst> (/temp only)");
ush_writeln(" rm <path> (/temp only)");
ush_writeln(" pid");
ush_writeln(" spawn <path|name> [args...]");
ush_writeln(" wait <pid>");
ush_writeln(" spawn <path|name> [args...] / bg <path|name> [args...]");
ush_writeln(" wait <pid> / fg [pid]");
ush_writeln(" kill <pid> [signal]");
ush_writeln(" jobs [-a] / ps [-a] [-u] / top [--once] [-n loops] [-d ticks]");
ush_writeln(" sleep <ticks>");
ush_writeln(" yield");
ush_writeln(" shutdown / restart");

236
cleonos/c/apps/top_main.c Normal file
View File

@@ -0,0 +1,236 @@
#include "cmd_runtime.h"
static const char *ush_top_state_name(u64 state) {
if (state == CLEONOS_PROC_STATE_PENDING) {
return "PEND";
}
if (state == CLEONOS_PROC_STATE_RUNNING) {
return "RUN ";
}
if (state == CLEONOS_PROC_STATE_EXITED) {
return "EXIT";
}
return "UNKN";
}
static int ush_top_next_token(const char **io_cursor, char *out, u64 out_size) {
const char *p;
u64 n = 0ULL;
if (io_cursor == (const char **)0 || out == (char *)0 || out_size == 0ULL) {
return 0;
}
out[0] = '\0';
p = *io_cursor;
if (p == (const char *)0) {
return 0;
}
while (*p != '\0' && ush_is_space(*p) != 0) {
p++;
}
if (*p == '\0') {
*io_cursor = p;
return 0;
}
while (*p != '\0' && ush_is_space(*p) == 0) {
if (n + 1ULL < out_size) {
out[n++] = *p;
}
p++;
}
out[n] = '\0';
*io_cursor = p;
return 1;
}
static int ush_top_parse(const char *arg, u64 *out_loops, u64 *out_delay) {
const char *cursor = arg;
char token[USH_PATH_MAX];
u64 loops = 0ULL;
u64 delay = 5ULL;
if (out_loops == (u64 *)0 || out_delay == (u64 *)0) {
return 0;
}
while (ush_top_next_token(&cursor, token, (u64)sizeof(token)) != 0) {
if (ush_streq(token, "--once") != 0) {
loops = 1ULL;
continue;
}
if (ush_streq(token, "-n") != 0) {
if (ush_top_next_token(&cursor, token, (u64)sizeof(token)) == 0 || ush_parse_u64_dec(token, &loops) == 0) {
return 0;
}
continue;
}
if (ush_streq(token, "-d") != 0) {
if (ush_top_next_token(&cursor, token, (u64)sizeof(token)) == 0 || ush_parse_u64_dec(token, &delay) == 0) {
return 0;
}
continue;
}
return 0;
}
*out_loops = loops;
*out_delay = delay;
return 1;
}
static void ush_top_render_frame(u64 frame_index, u64 delay_ticks) {
u64 proc_count = cleonos_sys_proc_count();
u64 i;
u64 shown = 0ULL;
ush_write("\x1B[2J\x1B[H");
ush_write("top frame=");
ush_write_hex_u64(frame_index);
ush_write(" ticks=");
ush_write_hex_u64(cleonos_sys_timer_ticks());
ush_write(" delay=");
ush_write_hex_u64(delay_ticks);
ush_write_char('\n');
ush_writeln("PID ST TTY RTICKS MEM PATH");
for (i = 0ULL; i < proc_count; i++) {
u64 pid = 0ULL;
cleonos_proc_snapshot snap;
if (cleonos_sys_proc_pid_at(i, &pid) == 0ULL || pid == 0ULL) {
continue;
}
if (cleonos_sys_proc_snapshot(pid, &snap, (u64)sizeof(snap)) == 0ULL) {
continue;
}
if (snap.state != CLEONOS_PROC_STATE_PENDING && snap.state != CLEONOS_PROC_STATE_RUNNING) {
continue;
}
ush_write_hex_u64(snap.pid);
ush_write(" ");
ush_write(ush_top_state_name(snap.state));
ush_write(" ");
ush_write_hex_u64(snap.tty_index);
ush_write(" ");
ush_write_hex_u64(snap.runtime_ticks);
ush_write(" ");
ush_write_hex_u64(snap.mem_bytes);
ush_write(" ");
ush_writeln(snap.path);
shown++;
}
if (shown == 0ULL) {
ush_writeln("(no active process)");
}
ush_writeln("");
ush_writeln("press q to quit");
}
static int ush_top_sleep_or_quit(u64 delay_ticks) {
u64 i;
if (delay_ticks == 0ULL) {
delay_ticks = 1ULL;
}
for (i = 0ULL; i < delay_ticks; i++) {
u64 ch = cleonos_sys_kbd_get_char();
if (ch != (u64)-1) {
char c = (char)(ch & 0xFFULL);
if (c == 'q' || c == 'Q') {
return 1;
}
}
(void)cleonos_sys_sleep_ticks(1ULL);
}
return 0;
}
static int ush_cmd_top(const char *arg) {
u64 loops;
u64 delay_ticks;
u64 frame = 0ULL;
if (ush_top_parse(arg, &loops, &delay_ticks) == 0) {
ush_writeln("top: usage top [--once] [-n loops] [-d ticks]");
return 0;
}
for (;;) {
frame++;
ush_top_render_frame(frame, delay_ticks);
if (loops != 0ULL && frame >= loops) {
break;
}
if (ush_top_sleep_or_quit(delay_ticks) != 0) {
break;
}
}
ush_write("\x1B[0m");
return 1;
}
int cleonos_app_main(void) {
ush_cmd_ctx ctx;
ush_cmd_ret ret;
ush_state sh;
char initial_cwd[USH_PATH_MAX];
int has_context = 0;
int success = 0;
const char *arg = "";
ush_zero(&ctx, (u64)sizeof(ctx));
ush_zero(&ret, (u64)sizeof(ret));
ush_init_state(&sh);
ush_copy(initial_cwd, (u64)sizeof(initial_cwd), sh.cwd);
if (ush_command_ctx_read(&ctx) != 0) {
if (ctx.cmd[0] != '\0' && ush_streq(ctx.cmd, "top") != 0) {
has_context = 1;
arg = ctx.arg;
if (ctx.cwd[0] == '/') {
ush_copy(sh.cwd, (u64)sizeof(sh.cwd), ctx.cwd);
ush_copy(initial_cwd, (u64)sizeof(initial_cwd), sh.cwd);
}
}
}
success = ush_cmd_top(arg);
if (has_context != 0) {
if (ush_streq(sh.cwd, initial_cwd) == 0) {
ret.flags |= USH_CMD_RET_FLAG_CWD;
ush_copy(ret.cwd, (u64)sizeof(ret.cwd), sh.cwd);
}
if (sh.exit_requested != 0) {
ret.flags |= USH_CMD_RET_FLAG_EXIT;
ret.exit_code = sh.exit_code;
}
(void)ush_command_ret_write(&ret);
}
return (success != 0) ? 0 : 1;
}

View File

@@ -5,6 +5,29 @@ typedef unsigned long long u64;
typedef unsigned long long usize;
#define CLEONOS_FS_NAME_MAX 96ULL
#define CLEONOS_PROC_PATH_MAX 192ULL
#define CLEONOS_PROC_STATE_UNUSED 0ULL
#define CLEONOS_PROC_STATE_PENDING 1ULL
#define CLEONOS_PROC_STATE_RUNNING 2ULL
#define CLEONOS_PROC_STATE_EXITED 3ULL
typedef struct cleonos_proc_snapshot {
u64 pid;
u64 ppid;
u64 state;
u64 started_tick;
u64 exited_tick;
u64 exit_status;
u64 runtime_ticks;
u64 mem_bytes;
u64 tty_index;
u64 last_signal;
u64 last_fault_vector;
u64 last_fault_error;
u64 last_fault_rip;
char path[CLEONOS_PROC_PATH_MAX];
} cleonos_proc_snapshot;
#define CLEONOS_SYSCALL_LOG_WRITE 0ULL
#define CLEONOS_SYSCALL_TIMER_TICKS 1ULL
@@ -67,6 +90,10 @@ typedef unsigned long long usize;
#define CLEONOS_SYSCALL_PROC_FAULT_VECTOR 58ULL
#define CLEONOS_SYSCALL_PROC_FAULT_ERROR 59ULL
#define CLEONOS_SYSCALL_PROC_FAULT_RIP 60ULL
#define CLEONOS_SYSCALL_PROC_COUNT 61ULL
#define CLEONOS_SYSCALL_PROC_PID_AT 62ULL
#define CLEONOS_SYSCALL_PROC_SNAPSHOT 63ULL
#define CLEONOS_SYSCALL_PROC_KILL 64ULL
u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
u64 cleonos_sys_log_write(const char *message, u64 length);
@@ -129,5 +156,9 @@ u64 cleonos_sys_proc_last_signal(void);
u64 cleonos_sys_proc_fault_vector(void);
u64 cleonos_sys_proc_fault_error(void);
u64 cleonos_sys_proc_fault_rip(void);
u64 cleonos_sys_proc_count(void);
u64 cleonos_sys_proc_pid_at(u64 index, u64 *out_pid);
u64 cleonos_sys_proc_snapshot(u64 pid, cleonos_proc_snapshot *out_snapshot, u64 out_size);
u64 cleonos_sys_proc_kill(u64 pid, u64 signal);
#endif

View File

@@ -252,3 +252,19 @@ u64 cleonos_sys_proc_fault_error(void) {
u64 cleonos_sys_proc_fault_rip(void) {
return cleonos_syscall(CLEONOS_SYSCALL_PROC_FAULT_RIP, 0ULL, 0ULL, 0ULL);
}
u64 cleonos_sys_proc_count(void) {
return cleonos_syscall(CLEONOS_SYSCALL_PROC_COUNT, 0ULL, 0ULL, 0ULL);
}
u64 cleonos_sys_proc_pid_at(u64 index, u64 *out_pid) {
return cleonos_syscall(CLEONOS_SYSCALL_PROC_PID_AT, index, (u64)out_pid, 0ULL);
}
u64 cleonos_sys_proc_snapshot(u64 pid, cleonos_proc_snapshot *out_snapshot, u64 out_size) {
return cleonos_syscall(CLEONOS_SYSCALL_PROC_SNAPSHOT, pid, (u64)out_snapshot, out_size);
}
u64 cleonos_sys_proc_kill(u64 pid, u64 signal) {
return cleonos_syscall(CLEONOS_SYSCALL_PROC_KILL, pid, signal, 0ULL);
}

View File

@@ -3,6 +3,30 @@
#include <clks/types.h>
#define CLKS_EXEC_PROC_PATH_MAX 192U
#define CLKS_EXEC_PROC_STATE_UNUSED 0ULL
#define CLKS_EXEC_PROC_STATE_PENDING 1ULL
#define CLKS_EXEC_PROC_STATE_RUNNING 2ULL
#define CLKS_EXEC_PROC_STATE_EXITED 3ULL
struct clks_exec_proc_snapshot {
u64 pid;
u64 ppid;
u64 state;
u64 started_tick;
u64 exited_tick;
u64 exit_status;
u64 runtime_ticks;
u64 mem_bytes;
u64 tty_index;
u64 last_signal;
u64 last_fault_vector;
u64 last_fault_error;
u64 last_fault_rip;
char path[CLKS_EXEC_PROC_PATH_MAX];
};
void clks_exec_init(void);
clks_bool clks_exec_run_path(const char *path, u64 *out_status);
clks_bool clks_exec_run_pathv(const char *path, const char *argv_line, const char *env_line, u64 *out_status);
@@ -20,6 +44,10 @@ u64 clks_exec_current_signal(void);
u64 clks_exec_current_fault_vector(void);
u64 clks_exec_current_fault_error(void);
u64 clks_exec_current_fault_rip(void);
u64 clks_exec_proc_count(void);
clks_bool clks_exec_proc_pid_at(u64 index, u64 *out_pid);
clks_bool clks_exec_proc_snapshot(u64 pid, struct clks_exec_proc_snapshot *out_snapshot);
u64 clks_exec_proc_kill(u64 pid, u64 signal);
clks_bool clks_exec_handle_exception(u64 vector,
u64 error_code,
u64 rip,

View File

@@ -64,6 +64,10 @@
#define CLKS_SYSCALL_PROC_FAULT_VECTOR 58ULL
#define CLKS_SYSCALL_PROC_FAULT_ERROR 59ULL
#define CLKS_SYSCALL_PROC_FAULT_RIP 60ULL
#define CLKS_SYSCALL_PROC_COUNT 61ULL
#define CLKS_SYSCALL_PROC_PID_AT 62ULL
#define CLKS_SYSCALL_PROC_SNAPSHOT 63ULL
#define CLKS_SYSCALL_PROC_KILL 64ULL
void clks_syscall_init(void);
u64 clks_syscall_dispatch(void *frame_ptr);

View File

@@ -22,6 +22,7 @@ typedef u64 (*clks_exec_entry_fn)(void);
#define CLKS_EXEC_MAX_ENVS 24U
#define CLKS_EXEC_ITEM_MAX 128U
#define CLKS_EXEC_STATUS_SIGNAL_FLAG (1ULL << 63)
#define CLKS_EXEC_DEFAULT_KILL_SIGNAL 15ULL
enum clks_exec_proc_state {
CLKS_EXEC_PROC_UNUSED = 0,
@@ -39,6 +40,7 @@ struct clks_exec_proc_record {
u64 exited_tick;
u64 exit_status;
u32 tty_index;
u64 image_mem_bytes;
char path[CLKS_EXEC_PATH_MAX];
char argv_line[CLKS_EXEC_ARG_LINE_MAX];
char env_line[CLKS_EXEC_ENV_LINE_MAX];
@@ -413,6 +415,7 @@ static struct clks_exec_proc_record *clks_exec_prepare_proc_record(i32 slot,
proc->exited_tick = 0ULL;
proc->exit_status = (u64)-1;
proc->tty_index = clks_tty_active();
proc->image_mem_bytes = 0ULL;
clks_exec_copy_path(proc->path, sizeof(proc->path), path);
clks_exec_copy_line(proc->argv_line, sizeof(proc->argv_line), argv_line);
clks_exec_copy_line(proc->env_line, sizeof(proc->env_line), env_line);
@@ -544,6 +547,8 @@ static clks_bool clks_exec_run_proc_slot(i32 slot, u64 *out_status) {
goto fail;
}
proc->image_mem_bytes = info.total_load_memsz;
if (clks_elf64_load(image, image_size, &loaded) == CLKS_FALSE) {
clks_log(CLKS_LOG_WARN, "EXEC", "EXEC ELF LOAD FAILED");
clks_log(CLKS_LOG_WARN, "EXEC", proc->path);
@@ -958,6 +963,190 @@ u64 clks_exec_current_fault_rip(void) {
return (proc != CLKS_NULL) ? proc->last_fault_rip : 0ULL;
}
static u64 clks_exec_proc_runtime_ticks(const struct clks_exec_proc_record *proc, u64 now_tick) {
if (proc == CLKS_NULL || proc->started_tick == 0ULL) {
return 0ULL;
}
if (proc->state == CLKS_EXEC_PROC_RUNNING) {
if (now_tick <= proc->started_tick) {
return 0ULL;
}
return now_tick - proc->started_tick;
}
if (proc->state == CLKS_EXEC_PROC_EXITED) {
if (proc->exited_tick <= proc->started_tick) {
return 0ULL;
}
return proc->exited_tick - proc->started_tick;
}
return 0ULL;
}
static u64 clks_exec_proc_memory_bytes(const struct clks_exec_proc_record *proc) {
u64 mem = 0ULL;
if (proc == CLKS_NULL) {
return 0ULL;
}
mem += proc->image_mem_bytes;
if (proc->state == CLKS_EXEC_PROC_RUNNING) {
mem += CLKS_EXEC_RUN_STACK_BYTES;
}
return mem;
}
u64 clks_exec_proc_count(void) {
u64 count = 0ULL;
u32 i;
for (i = 0U; i < CLKS_EXEC_MAX_PROCS; i++) {
if (clks_exec_proc_table[i].used == CLKS_TRUE) {
count++;
}
}
return count;
}
clks_bool clks_exec_proc_pid_at(u64 index, u64 *out_pid) {
u64 pos = 0ULL;
u32 i;
if (out_pid != CLKS_NULL) {
*out_pid = 0ULL;
}
if (out_pid == CLKS_NULL) {
return CLKS_FALSE;
}
for (i = 0U; i < CLKS_EXEC_MAX_PROCS; i++) {
if (clks_exec_proc_table[i].used != CLKS_TRUE) {
continue;
}
if (pos == index) {
*out_pid = clks_exec_proc_table[i].pid;
return CLKS_TRUE;
}
pos++;
}
return CLKS_FALSE;
}
clks_bool clks_exec_proc_snapshot(u64 pid, struct clks_exec_proc_snapshot *out_snapshot) {
i32 slot;
const struct clks_exec_proc_record *proc;
u64 now_tick;
if (out_snapshot == CLKS_NULL) {
return CLKS_FALSE;
}
slot = clks_exec_proc_find_slot_by_pid(pid);
if (slot < 0) {
return CLKS_FALSE;
}
proc = &clks_exec_proc_table[(u32)slot];
if (proc->used != CLKS_TRUE) {
return CLKS_FALSE;
}
now_tick = clks_interrupts_timer_ticks();
clks_memset(out_snapshot, 0, sizeof(*out_snapshot));
out_snapshot->pid = proc->pid;
out_snapshot->ppid = proc->ppid;
out_snapshot->state = (u64)proc->state;
out_snapshot->started_tick = proc->started_tick;
out_snapshot->exited_tick = proc->exited_tick;
out_snapshot->exit_status = proc->exit_status;
out_snapshot->runtime_ticks = clks_exec_proc_runtime_ticks(proc, now_tick);
out_snapshot->mem_bytes = clks_exec_proc_memory_bytes(proc);
out_snapshot->tty_index = (u64)proc->tty_index;
out_snapshot->last_signal = proc->last_signal;
out_snapshot->last_fault_vector = proc->last_fault_vector;
out_snapshot->last_fault_error = proc->last_fault_error;
out_snapshot->last_fault_rip = proc->last_fault_rip;
clks_exec_copy_path(out_snapshot->path, sizeof(out_snapshot->path), proc->path);
return CLKS_TRUE;
}
u64 clks_exec_proc_kill(u64 pid, u64 signal) {
i32 slot;
struct clks_exec_proc_record *proc;
u64 effective_signal;
u64 status;
u64 now_tick;
if (pid == 0ULL) {
return (u64)-1;
}
slot = clks_exec_proc_find_slot_by_pid(pid);
if (slot < 0) {
return (u64)-1;
}
proc = &clks_exec_proc_table[(u32)slot];
if (proc->used != CLKS_TRUE) {
return (u64)-1;
}
effective_signal = (signal == 0ULL) ? CLKS_EXEC_DEFAULT_KILL_SIGNAL : (signal & 0xFFULL);
status = clks_exec_encode_signal_status(effective_signal, 0ULL, 0ULL);
now_tick = clks_interrupts_timer_ticks();
if (proc->state == CLKS_EXEC_PROC_EXITED) {
return 1ULL;
}
if (proc->state == CLKS_EXEC_PROC_PENDING) {
proc->state = CLKS_EXEC_PROC_EXITED;
proc->exit_status = status;
proc->exited_tick = now_tick;
proc->last_signal = effective_signal;
proc->last_fault_vector = 0ULL;
proc->last_fault_error = 0ULL;
proc->last_fault_rip = 0ULL;
return 1ULL;
}
if (proc->state == CLKS_EXEC_PROC_RUNNING) {
i32 depth_index = clks_exec_current_depth_index();
if (depth_index < 0 || clks_exec_current_pid() != pid) {
return 0ULL;
}
proc->last_signal = effective_signal;
proc->last_fault_vector = 0ULL;
proc->last_fault_error = 0ULL;
proc->last_fault_rip = 0ULL;
clks_exec_exit_requested_stack[(u32)depth_index] = CLKS_TRUE;
clks_exec_exit_status_stack[(u32)depth_index] = status;
return 1ULL;
}
return 0ULL;
}
clks_bool clks_exec_handle_exception(u64 vector,
u64 error_code,
u64 rip,

View File

@@ -6,6 +6,8 @@
#define CLKS_LOG_LINE_MAX 256
#define CLKS_LOG_JOURNAL_CAP 256
#define CLKS_LOG_ANSI_RESET "\x1B[0m"
static char clks_log_journal[CLKS_LOG_JOURNAL_CAP][CLKS_LOG_LINE_MAX];
static u32 clks_log_journal_head = 0U;
static u32 clks_log_journal_count_live = 0U;
@@ -37,6 +39,10 @@ static void clks_log_append_char(char *buffer, usize *cursor, char ch) {
static void clks_log_append_text(char *buffer, usize *cursor, const char *text) {
usize i = 0;
if (text == CLKS_NULL) {
return;
}
while (text[i] != '\0') {
clks_log_append_char(buffer, cursor, text[i]);
i++;
@@ -83,51 +89,121 @@ static void clks_log_journal_push(const char *line) {
}
}
static void clks_log_emit_line(const char *line) {
static const char *clks_log_level_ansi(enum clks_log_level level) {
switch (level) {
case CLKS_LOG_DEBUG:
return "\x1B[38;5;110m";
case CLKS_LOG_INFO:
return "\x1B[38;5;120m";
case CLKS_LOG_WARN:
return "\x1B[1;38;5;220m";
case CLKS_LOG_ERROR:
return "\x1B[1;38;5;203m";
default:
return "\x1B[38;5;250m";
}
}
static const char *clks_log_tag_ansi(const char *tag) {
static const char *palette[] = {
"\x1B[38;5;81m",
"\x1B[38;5;117m",
"\x1B[38;5;159m",
"\x1B[38;5;45m",
"\x1B[38;5;75m",
"\x1B[38;5;141m",
"\x1B[38;5;214m",
"\x1B[38;5;168m",
};
u32 hash = 5381U;
usize i = 0U;
usize palette_count = sizeof(palette) / sizeof(palette[0]);
if (tag == CLKS_NULL || tag[0] == '\0') {
return palette[0];
}
while (tag[i] != '\0') {
hash = ((hash << 5U) + hash) ^ (u32)(u8)tag[i];
i++;
}
return palette[hash % (u32)palette_count];
}
static void clks_log_emit_tty_colored(enum clks_log_level level, const char *tag, const char *message) {
const char *safe_tag = (tag == CLKS_NULL) ? "LOG" : tag;
const char *safe_message = (message == CLKS_NULL) ? "" : message;
clks_tty_write(clks_log_level_ansi(level));
clks_tty_write("[");
clks_tty_write(clks_log_level_name(level));
clks_tty_write("]");
clks_tty_write(clks_log_tag_ansi(safe_tag));
clks_tty_write("[");
clks_tty_write(safe_tag);
clks_tty_write("]");
clks_tty_write(CLKS_LOG_ANSI_RESET);
clks_tty_write(" ");
clks_tty_write(safe_message);
clks_tty_write("\n");
}
static void clks_log_build_line(enum clks_log_level level, const char *tag, const char *message, char *line) {
const char *safe_tag = (tag == CLKS_NULL) ? "LOG" : tag;
const char *safe_message = (message == CLKS_NULL) ? "" : message;
usize cursor = 0U;
if (line == CLKS_NULL) {
return;
}
clks_log_append_char(line, &cursor, '[');
clks_log_append_text(line, &cursor, clks_log_level_name(level));
clks_log_append_char(line, &cursor, ']');
clks_log_append_char(line, &cursor, '[');
clks_log_append_text(line, &cursor, safe_tag);
clks_log_append_char(line, &cursor, ']');
clks_log_append_char(line, &cursor, ' ');
clks_log_append_text(line, &cursor, safe_message);
line[cursor] = '\0';
}
static void clks_log_emit_line(enum clks_log_level level, const char *tag, const char *message, const char *line) {
if (line == CLKS_NULL) {
return;
}
clks_log_journal_push(line);
clks_serial_write(line);
clks_serial_write("\n");
clks_tty_write(line);
clks_tty_write("\n");
clks_log_emit_tty_colored(level, tag, message);
}
void clks_log(enum clks_log_level level, const char *tag, const char *message) {
char line[CLKS_LOG_LINE_MAX];
usize cursor = 0;
clks_log_append_char(line, &cursor, '[');
clks_log_append_text(line, &cursor, clks_log_level_name(level));
clks_log_append_char(line, &cursor, ']');
clks_log_append_char(line, &cursor, '[');
clks_log_append_text(line, &cursor, tag);
clks_log_append_char(line, &cursor, ']');
clks_log_append_char(line, &cursor, ' ');
clks_log_append_text(line, &cursor, message);
line[cursor] = '\0';
clks_log_emit_line(line);
clks_log_build_line(level, tag, message, line);
clks_log_emit_line(level, tag, message, line);
}
void clks_log_hex(enum clks_log_level level, const char *tag, const char *label, u64 value) {
char message[CLKS_LOG_LINE_MAX];
char line[CLKS_LOG_LINE_MAX];
usize cursor = 0;
usize cursor = 0U;
clks_log_append_char(line, &cursor, '[');
clks_log_append_text(line, &cursor, clks_log_level_name(level));
clks_log_append_char(line, &cursor, ']');
clks_log_append_char(line, &cursor, '[');
clks_log_append_text(line, &cursor, tag);
clks_log_append_char(line, &cursor, ']');
clks_log_append_char(line, &cursor, ' ');
clks_log_append_text(line, &cursor, label);
clks_log_append_char(line, &cursor, ':');
clks_log_append_char(line, &cursor, ' ');
clks_log_append_hex_u64(line, &cursor, value);
line[cursor] = '\0';
clks_log_append_text(message, &cursor, (label == CLKS_NULL) ? "VALUE" : label);
clks_log_append_char(message, &cursor, ':');
clks_log_append_char(message, &cursor, ' ');
clks_log_append_hex_u64(message, &cursor, value);
message[cursor] = '\0';
clks_log_emit_line(line);
clks_log_build_line(level, tag, message, line);
clks_log_emit_line(level, tag, message, line);
}
u64 clks_log_journal_count(void) {
@@ -153,4 +229,4 @@ clks_bool clks_log_journal_read(u64 index_from_oldest, char *out_line, usize out
clks_log_journal_copy_line(out_line, out_line_size, clks_log_journal[slot]);
return CLKS_TRUE;
}
}

View File

@@ -362,6 +362,44 @@ static u64 clks_syscall_proc_fault_rip(void) {
return clks_exec_current_fault_rip();
}
static u64 clks_syscall_proc_count(void) {
return clks_exec_proc_count();
}
static u64 clks_syscall_proc_pid_at(u64 arg0, u64 arg1) {
u64 pid = 0ULL;
if (arg1 == 0ULL) {
return 0ULL;
}
if (clks_exec_proc_pid_at(arg0, &pid) == CLKS_FALSE) {
return 0ULL;
}
clks_memcpy((void *)arg1, &pid, sizeof(pid));
return 1ULL;
}
static u64 clks_syscall_proc_snapshot(u64 arg0, u64 arg1, u64 arg2) {
struct clks_exec_proc_snapshot snap;
if (arg1 == 0ULL || arg2 < (u64)sizeof(snap)) {
return 0ULL;
}
if (clks_exec_proc_snapshot(arg0, &snap) == CLKS_FALSE) {
return 0ULL;
}
clks_memcpy((void *)arg1, &snap, sizeof(snap));
return 1ULL;
}
static u64 clks_syscall_proc_kill(u64 arg0, u64 arg1) {
return clks_exec_proc_kill(arg0, arg1);
}
static u64 clks_syscall_exit(u64 arg0) {
return (clks_exec_request_exit(arg0) == CLKS_TRUE) ? 1ULL : 0ULL;
}
@@ -723,6 +761,14 @@ u64 clks_syscall_dispatch(void *frame_ptr) {
return clks_syscall_proc_fault_error();
case CLKS_SYSCALL_PROC_FAULT_RIP:
return clks_syscall_proc_fault_rip();
case CLKS_SYSCALL_PROC_COUNT:
return clks_syscall_proc_count();
case CLKS_SYSCALL_PROC_PID_AT:
return clks_syscall_proc_pid_at(frame->rbx, frame->rcx);
case CLKS_SYSCALL_PROC_SNAPSHOT:
return clks_syscall_proc_snapshot(frame->rbx, frame->rcx, frame->rdx);
case CLKS_SYSCALL_PROC_KILL:
return clks_syscall_proc_kill(frame->rbx, frame->rcx);
case CLKS_SYSCALL_EXIT:
return clks_syscall_exit(frame->rbx);
case CLKS_SYSCALL_SLEEP_TICKS:

View File

@@ -60,7 +60,7 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
- `FS_MKDIR` / `FS_WRITE` / `FS_APPEND` / `FS_REMOVE` 仅允许 `/temp` 树下路径。
## 4. Syscall 列表0~60
## 4. Syscall 列表0~64
### 0 `CLEONOS_SYSCALL_LOG_WRITE`
@@ -446,6 +446,38 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
- 参数:无
- 返回:当前进程最近一次 CPU 异常 RIP无则 `0`
### 61 `CLEONOS_SYSCALL_PROC_COUNT`
- 参数:无
- 返回:当前进程表中已使用槽位数量
### 62 `CLEONOS_SYSCALL_PROC_PID_AT`
- 参数:
- `arg0`: `u64 index`
- `arg1`: `u64 *out_pid`
- 返回:成功 `1`,失败 `0`
- 说明:用于枚举进程;`index` 超出范围返回 `0`
### 63 `CLEONOS_SYSCALL_PROC_SNAPSHOT`
- 参数:
- `arg0`: `u64 pid`
- `arg1`: `struct cleonos_proc_snapshot *out_snapshot`
- `arg2`: `u64 out_size`(需 `>= sizeof(cleonos_proc_snapshot)`
- 返回:成功 `1`,失败 `0`
- 说明:返回 PID/PPID/状态/运行 tick/内存估算/TTY/路径等快照信息。
### 64 `CLEONOS_SYSCALL_PROC_KILL`
- 参数:
- `arg0`: `u64 pid`
- `arg1`: `u64 signal``0` 时按 `SIGTERM(15)` 处理)
- 返回:
- `1`:请求成功
- `0`:当前不可终止(例如非当前上下文中的 running 进程)
- `-1`PID 不存在
## 5. 用户态封装函数
用户态封装位于:
@@ -467,6 +499,7 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
- `cleonos_sys_audio_available()` / `cleonos_sys_audio_play_tone()` / `cleonos_sys_audio_stop()`
- `cleonos_sys_proc_argc()` / `cleonos_sys_proc_argv()` / `cleonos_sys_proc_envc()` / `cleonos_sys_proc_env()`
- `cleonos_sys_proc_last_signal()` / `cleonos_sys_proc_fault_vector()` / `cleonos_sys_proc_fault_error()` / `cleonos_sys_proc_fault_rip()`
- `cleonos_sys_proc_count()` / `cleonos_sys_proc_pid_at()` / `cleonos_sys_proc_snapshot()` / `cleonos_sys_proc_kill()`
## 6. 开发注意事项