fd子系统

This commit is contained in:
2026-04-17 22:23:14 +08:00
parent 56bfa58e56
commit 59b1b05e0d
7 changed files with 561 additions and 3 deletions

View File

@@ -18,6 +18,13 @@ typedef unsigned long long usize;
#define CLEONOS_SIGCONT 18ULL
#define CLEONOS_SIGSTOP 19ULL
#define CLEONOS_O_RDONLY 0x0000ULL
#define CLEONOS_O_WRONLY 0x0001ULL
#define CLEONOS_O_RDWR 0x0002ULL
#define CLEONOS_O_CREAT 0x0040ULL
#define CLEONOS_O_TRUNC 0x0200ULL
#define CLEONOS_O_APPEND 0x0400ULL
typedef struct cleonos_proc_snapshot {
u64 pid;
u64 ppid;
@@ -107,6 +114,11 @@ typedef struct cleonos_proc_snapshot {
#define CLEONOS_SYSCALL_STATS_ID_COUNT 69ULL
#define CLEONOS_SYSCALL_STATS_RECENT_WINDOW 70ULL
#define CLEONOS_SYSCALL_STATS_RECENT_ID 71ULL
#define CLEONOS_SYSCALL_FD_OPEN 72ULL
#define CLEONOS_SYSCALL_FD_READ 73ULL
#define CLEONOS_SYSCALL_FD_WRITE 74ULL
#define CLEONOS_SYSCALL_FD_CLOSE 75ULL
#define CLEONOS_SYSCALL_FD_DUP 76ULL
u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
u64 cleonos_sys_log_write(const char *message, u64 length);
@@ -180,5 +192,10 @@ u64 cleonos_sys_stats_total(void);
u64 cleonos_sys_stats_id_count(u64 id);
u64 cleonos_sys_stats_recent_window(void);
u64 cleonos_sys_stats_recent_id(u64 id);
u64 cleonos_sys_fd_open(const char *path, u64 flags, u64 mode);
u64 cleonos_sys_fd_read(u64 fd, void *out_buffer, u64 size);
u64 cleonos_sys_fd_write(u64 fd, const void *buffer, u64 size);
u64 cleonos_sys_fd_close(u64 fd);
u64 cleonos_sys_fd_dup(u64 fd);
#endif

View File

@@ -310,3 +310,23 @@ u64 cleonos_sys_stats_recent_window(void) {
u64 cleonos_sys_stats_recent_id(u64 id) {
return cleonos_syscall(CLEONOS_SYSCALL_STATS_RECENT_ID, id, 0ULL, 0ULL);
}
u64 cleonos_sys_fd_open(const char *path, u64 flags, u64 mode) {
return cleonos_syscall(CLEONOS_SYSCALL_FD_OPEN, (u64)path, flags, mode);
}
u64 cleonos_sys_fd_read(u64 fd, void *out_buffer, u64 size) {
return cleonos_syscall(CLEONOS_SYSCALL_FD_READ, fd, (u64)out_buffer, size);
}
u64 cleonos_sys_fd_write(u64 fd, const void *buffer, u64 size) {
return cleonos_syscall(CLEONOS_SYSCALL_FD_WRITE, fd, (u64)buffer, size);
}
u64 cleonos_sys_fd_close(u64 fd) {
return cleonos_syscall(CLEONOS_SYSCALL_FD_CLOSE, fd, 0ULL, 0ULL);
}
u64 cleonos_sys_fd_dup(u64 fd) {
return cleonos_syscall(CLEONOS_SYSCALL_FD_DUP, fd, 0ULL, 0ULL);
}

View File

@@ -40,6 +40,11 @@ clks_bool clks_exec_spawn_path(const char *path, u64 *out_pid);
clks_bool clks_exec_spawn_pathv(const char *path, const char *argv_line, const char *env_line, u64 *out_pid);
u64 clks_exec_wait_pid(u64 pid, u64 *out_status);
clks_bool clks_exec_request_exit(u64 status);
u64 clks_exec_fd_open(const char *path, u64 flags, u64 mode);
u64 clks_exec_fd_read(u64 fd, void *out_buffer, u64 size);
u64 clks_exec_fd_write(u64 fd, const void *buffer, u64 size);
u64 clks_exec_fd_close(u64 fd);
u64 clks_exec_fd_dup(u64 fd);
u64 clks_exec_current_pid(void);
u32 clks_exec_current_tty(void);
u64 clks_exec_current_argc(void);

View File

@@ -75,6 +75,11 @@
#define CLKS_SYSCALL_STATS_ID_COUNT 69ULL
#define CLKS_SYSCALL_STATS_RECENT_WINDOW 70ULL
#define CLKS_SYSCALL_STATS_RECENT_ID 71ULL
#define CLKS_SYSCALL_FD_OPEN 72ULL
#define CLKS_SYSCALL_FD_READ 73ULL
#define CLKS_SYSCALL_FD_WRITE 74ULL
#define CLKS_SYSCALL_FD_CLOSE 75ULL
#define CLKS_SYSCALL_FD_DUP 76ULL
void clks_syscall_init(void);
u64 clks_syscall_dispatch(void *frame_ptr);

View File

@@ -4,6 +4,7 @@
#include <clks/fs.h>
#include <clks/heap.h>
#include <clks/interrupts.h>
#include <clks/keyboard.h>
#include <clks/log.h>
#include <clks/serial.h>
#include <clks/string.h>
@@ -18,6 +19,7 @@ typedef u64 (*clks_exec_entry_fn)(void);
#define CLKS_EXEC_PATH_MAX 192U
#define CLKS_EXEC_ARG_LINE_MAX 256U
#define CLKS_EXEC_ENV_LINE_MAX 512U
#define CLKS_EXEC_FD_MAX 32U
#define CLKS_EXEC_MAX_ARGS 24U
#define CLKS_EXEC_MAX_ENVS 24U
#define CLKS_EXEC_ITEM_MAX 128U
@@ -25,6 +27,19 @@ typedef u64 (*clks_exec_entry_fn)(void);
#define CLKS_EXEC_DEFAULT_KILL_SIGNAL CLKS_EXEC_SIGNAL_TERM
#define CLKS_EXEC_KERNEL_ADDR_BASE 0xFFFF800000000000ULL
#define CLKS_EXEC_UNWIND_CTX_BYTES 56ULL
#define CLKS_EXEC_FD_ACCESS_MASK 0x3ULL
#define CLKS_EXEC_O_RDONLY 0x0000ULL
#define CLKS_EXEC_O_WRONLY 0x0001ULL
#define CLKS_EXEC_O_RDWR 0x0002ULL
#define CLKS_EXEC_O_CREAT 0x0040ULL
#define CLKS_EXEC_O_TRUNC 0x0200ULL
#define CLKS_EXEC_O_APPEND 0x0400ULL
enum clks_exec_fd_kind {
CLKS_EXEC_FD_KIND_NONE = 0,
CLKS_EXEC_FD_KIND_TTY = 1,
CLKS_EXEC_FD_KIND_FILE = 2,
};
enum clks_exec_proc_state {
CLKS_EXEC_PROC_UNUSED = 0,
@@ -34,6 +49,15 @@ enum clks_exec_proc_state {
CLKS_EXEC_PROC_STOPPED = 4,
};
struct clks_exec_fd_entry {
clks_bool used;
enum clks_exec_fd_kind kind;
u64 flags;
u64 offset;
u32 tty_index;
char path[CLKS_EXEC_PATH_MAX];
};
struct clks_exec_proc_record {
clks_bool used;
enum clks_exec_proc_state state;
@@ -57,6 +81,7 @@ struct clks_exec_proc_record {
u64 last_fault_vector;
u64 last_fault_error;
u64 last_fault_rip;
struct clks_exec_fd_entry fds[CLKS_EXEC_FD_MAX];
};
#if defined(CLKS_ARCH_X86_64)
@@ -81,6 +106,8 @@ static u64 clks_exec_image_begin_stack[CLKS_EXEC_MAX_DEPTH];
static u64 clks_exec_image_end_stack[CLKS_EXEC_MAX_DEPTH];
static u32 clks_exec_pid_stack_depth = 0U;
static struct clks_exec_proc_record *clks_exec_current_proc(void);
static void clks_exec_serial_write_hex64(u64 value) {
int nibble;
@@ -424,6 +451,188 @@ static u64 clks_exec_alloc_pid(void) {
return pid;
}
static clks_bool clks_exec_fd_access_mode_valid(u64 flags) {
u64 mode = flags & CLKS_EXEC_FD_ACCESS_MASK;
return (mode == CLKS_EXEC_O_RDONLY || mode == CLKS_EXEC_O_WRONLY || mode == CLKS_EXEC_O_RDWR) ? CLKS_TRUE
: CLKS_FALSE;
}
static clks_bool clks_exec_fd_can_read(u64 flags) {
u64 mode = flags & CLKS_EXEC_FD_ACCESS_MASK;
return (mode == CLKS_EXEC_O_RDONLY || mode == CLKS_EXEC_O_RDWR) ? CLKS_TRUE : CLKS_FALSE;
}
static clks_bool clks_exec_fd_can_write(u64 flags) {
u64 mode = flags & CLKS_EXEC_FD_ACCESS_MASK;
return (mode == CLKS_EXEC_O_WRONLY || mode == CLKS_EXEC_O_RDWR) ? CLKS_TRUE : CLKS_FALSE;
}
static clks_bool clks_exec_path_is_dev_tty(const char *path) {
return (path != CLKS_NULL && clks_strcmp(path, "/dev/tty") == 0) ? CLKS_TRUE : CLKS_FALSE;
}
static void clks_exec_fd_init_defaults(struct clks_exec_proc_record *proc) {
if (proc == CLKS_NULL) {
return;
}
clks_memset(proc->fds, 0, sizeof(proc->fds));
proc->fds[0].used = CLKS_TRUE;
proc->fds[0].kind = CLKS_EXEC_FD_KIND_TTY;
proc->fds[0].flags = CLKS_EXEC_O_RDONLY;
proc->fds[0].offset = 0ULL;
proc->fds[0].tty_index = proc->tty_index;
proc->fds[0].path[0] = '\0';
proc->fds[1].used = CLKS_TRUE;
proc->fds[1].kind = CLKS_EXEC_FD_KIND_TTY;
proc->fds[1].flags = CLKS_EXEC_O_WRONLY;
proc->fds[1].offset = 0ULL;
proc->fds[1].tty_index = proc->tty_index;
proc->fds[1].path[0] = '\0';
proc->fds[2].used = CLKS_TRUE;
proc->fds[2].kind = CLKS_EXEC_FD_KIND_TTY;
proc->fds[2].flags = CLKS_EXEC_O_WRONLY;
proc->fds[2].offset = 0ULL;
proc->fds[2].tty_index = proc->tty_index;
proc->fds[2].path[0] = '\0';
}
static i32 clks_exec_fd_find_free(struct clks_exec_proc_record *proc) {
u32 i;
if (proc == CLKS_NULL) {
return -1;
}
for (i = 0U; i < CLKS_EXEC_FD_MAX; i++) {
if (proc->fds[i].used == CLKS_FALSE) {
return (i32)i;
}
}
return -1;
}
static struct clks_exec_fd_entry *clks_exec_fd_lookup(struct clks_exec_proc_record *proc, u64 fd) {
if (proc == CLKS_NULL || fd >= CLKS_EXEC_FD_MAX) {
return CLKS_NULL;
}
if (proc->fds[(u32)fd].used == CLKS_FALSE) {
return CLKS_NULL;
}
return &proc->fds[(u32)fd];
}
static u64 clks_exec_fd_file_read(struct clks_exec_fd_entry *entry, void *out_buffer, u64 size) {
const void *file_data;
u64 file_size = 0ULL;
u64 read_len;
if (entry == CLKS_NULL || out_buffer == CLKS_NULL || size == 0ULL) {
return 0ULL;
}
file_data = clks_fs_read_all(entry->path, &file_size);
if (file_data == CLKS_NULL) {
return (u64)-1;
}
if (entry->offset >= file_size) {
return 0ULL;
}
read_len = file_size - entry->offset;
if (read_len > size) {
read_len = size;
}
clks_memcpy(out_buffer, (const u8 *)file_data + (usize)entry->offset, (usize)read_len);
entry->offset += read_len;
return read_len;
}
static u64 clks_exec_fd_file_write(struct clks_exec_fd_entry *entry, const void *buffer, u64 size) {
const void *old_data = CLKS_NULL;
u64 old_size = 0ULL;
u64 write_pos;
u64 new_size;
void *merged = CLKS_NULL;
clks_bool ok;
if (entry == CLKS_NULL) {
return (u64)-1;
}
if (size == 0ULL) {
return 0ULL;
}
if (buffer == CLKS_NULL) {
return (u64)-1;
}
if ((entry->flags & CLKS_EXEC_O_APPEND) != 0ULL) {
if (clks_fs_append(entry->path, buffer, size) == CLKS_FALSE) {
return (u64)-1;
}
entry->offset += size;
return size;
}
old_data = clks_fs_read_all(entry->path, &old_size);
if (old_data == CLKS_NULL) {
return (u64)-1;
}
write_pos = entry->offset;
if (write_pos > (0xFFFFFFFFFFFFFFFFULL - size)) {
return (u64)-1;
}
new_size = write_pos + size;
if (new_size < old_size) {
new_size = old_size;
}
if (new_size == 0ULL) {
return 0ULL;
}
merged = clks_kmalloc((usize)new_size);
if (merged == CLKS_NULL) {
return (u64)-1;
}
clks_memset(merged, 0, (usize)new_size);
if (old_size > 0ULL) {
clks_memcpy(merged, old_data, (usize)old_size);
}
clks_memcpy((u8 *)merged + (usize)write_pos, buffer, (usize)size);
ok = clks_fs_write_all(entry->path, merged, new_size);
clks_kfree(merged);
if (ok == CLKS_FALSE) {
return (u64)-1;
}
entry->offset = write_pos + size;
return size;
}
static struct clks_exec_proc_record *clks_exec_prepare_proc_record(i32 slot,
u64 pid,
const char *path,
@@ -461,6 +670,7 @@ static struct clks_exec_proc_record *clks_exec_prepare_proc_record(i32 slot,
proc->last_fault_vector = 0ULL;
proc->last_fault_error = 0ULL;
proc->last_fault_rip = 0ULL;
clks_exec_fd_init_defaults(proc);
if (proc->argc < CLKS_EXEC_MAX_ARGS) {
clks_exec_copy_path(proc->argv_items[proc->argc], CLKS_EXEC_ITEM_MAX, path);
@@ -965,6 +1175,215 @@ clks_bool clks_exec_request_exit(u64 status) {
return CLKS_TRUE;
}
u64 clks_exec_fd_open(const char *path, u64 flags, u64 mode) {
struct clks_exec_proc_record *proc = clks_exec_current_proc();
struct clks_fs_node_info info;
i32 fd_slot;
u8 empty_payload = 0U;
(void)mode;
if (proc == CLKS_NULL || path == CLKS_NULL || path[0] != '/') {
return (u64)-1;
}
if (clks_strlen(path) >= CLKS_EXEC_PATH_MAX) {
return (u64)-1;
}
if (clks_exec_fd_access_mode_valid(flags) == CLKS_FALSE) {
return (u64)-1;
}
if (((flags & CLKS_EXEC_O_TRUNC) != 0ULL || (flags & CLKS_EXEC_O_APPEND) != 0ULL) &&
clks_exec_fd_can_write(flags) == CLKS_FALSE) {
return (u64)-1;
}
fd_slot = clks_exec_fd_find_free(proc);
if (fd_slot < 0) {
return (u64)-1;
}
if (clks_exec_path_is_dev_tty(path) == CLKS_TRUE) {
struct clks_exec_fd_entry *entry = &proc->fds[(u32)fd_slot];
clks_memset(entry, 0, sizeof(*entry));
entry->used = CLKS_TRUE;
entry->kind = CLKS_EXEC_FD_KIND_TTY;
entry->flags = flags;
entry->offset = 0ULL;
entry->tty_index = proc->tty_index;
entry->path[0] = '\0';
return (u64)fd_slot;
}
if (clks_fs_stat(path, &info) == CLKS_FALSE) {
if ((flags & CLKS_EXEC_O_CREAT) == 0ULL || clks_exec_fd_can_write(flags) == CLKS_FALSE) {
return (u64)-1;
}
if (clks_fs_write_all(path, &empty_payload, 0ULL) == CLKS_FALSE || clks_fs_stat(path, &info) == CLKS_FALSE) {
return (u64)-1;
}
}
if (info.type != CLKS_FS_NODE_FILE) {
return (u64)-1;
}
if ((flags & CLKS_EXEC_O_TRUNC) != 0ULL) {
if (clks_fs_write_all(path, &empty_payload, 0ULL) == CLKS_FALSE || clks_fs_stat(path, &info) == CLKS_FALSE) {
return (u64)-1;
}
}
{
struct clks_exec_fd_entry *entry = &proc->fds[(u32)fd_slot];
clks_memset(entry, 0, sizeof(*entry));
entry->used = CLKS_TRUE;
entry->kind = CLKS_EXEC_FD_KIND_FILE;
entry->flags = flags;
entry->offset = ((flags & CLKS_EXEC_O_APPEND) != 0ULL) ? info.size : 0ULL;
entry->tty_index = proc->tty_index;
clks_exec_copy_path(entry->path, sizeof(entry->path), path);
}
return (u64)fd_slot;
}
u64 clks_exec_fd_read(u64 fd, void *out_buffer, u64 size) {
struct clks_exec_proc_record *proc = clks_exec_current_proc();
struct clks_exec_fd_entry *entry;
if (proc == CLKS_NULL) {
return (u64)-1;
}
if (size == 0ULL) {
return 0ULL;
}
if (out_buffer == CLKS_NULL) {
return (u64)-1;
}
entry = clks_exec_fd_lookup(proc, fd);
if (entry == CLKS_NULL || clks_exec_fd_can_read(entry->flags) == CLKS_FALSE) {
return (u64)-1;
}
if (entry->kind == CLKS_EXEC_FD_KIND_TTY) {
u64 count = 0ULL;
char *dst = (char *)out_buffer;
while (count < size) {
char ch;
if (clks_keyboard_pop_char_for_tty(entry->tty_index, &ch) == CLKS_FALSE) {
break;
}
dst[count] = ch;
count++;
}
return count;
}
if (entry->kind == CLKS_EXEC_FD_KIND_FILE) {
return clks_exec_fd_file_read(entry, out_buffer, size);
}
return (u64)-1;
}
u64 clks_exec_fd_write(u64 fd, const void *buffer, u64 size) {
struct clks_exec_proc_record *proc = clks_exec_current_proc();
struct clks_exec_fd_entry *entry;
if (proc == CLKS_NULL) {
return (u64)-1;
}
if (size == 0ULL) {
return 0ULL;
}
if (buffer == CLKS_NULL) {
return (u64)-1;
}
entry = clks_exec_fd_lookup(proc, fd);
if (entry == CLKS_NULL || clks_exec_fd_can_write(entry->flags) == CLKS_FALSE) {
return (u64)-1;
}
if (entry->kind == CLKS_EXEC_FD_KIND_TTY) {
u64 i;
const char *src = (const char *)buffer;
for (i = 0ULL; i < size; i++) {
clks_tty_write_char(src[i]);
}
return size;
}
if (entry->kind == CLKS_EXEC_FD_KIND_FILE) {
return clks_exec_fd_file_write(entry, buffer, size);
}
return (u64)-1;
}
u64 clks_exec_fd_close(u64 fd) {
struct clks_exec_proc_record *proc = clks_exec_current_proc();
struct clks_exec_fd_entry *entry;
if (proc == CLKS_NULL) {
return (u64)-1;
}
entry = clks_exec_fd_lookup(proc, fd);
if (entry == CLKS_NULL) {
return (u64)-1;
}
clks_memset(entry, 0, sizeof(*entry));
return 0ULL;
}
u64 clks_exec_fd_dup(u64 fd) {
struct clks_exec_proc_record *proc = clks_exec_current_proc();
struct clks_exec_fd_entry *entry;
i32 fd_slot;
if (proc == CLKS_NULL) {
return (u64)-1;
}
entry = clks_exec_fd_lookup(proc, fd);
if (entry == CLKS_NULL) {
return (u64)-1;
}
fd_slot = clks_exec_fd_find_free(proc);
if (fd_slot < 0) {
return (u64)-1;
}
proc->fds[(u32)fd_slot] = *entry;
return (u64)fd_slot;
}
u64 clks_exec_current_pid(void) {
i32 depth_index = clks_exec_current_depth_index();

View File

@@ -32,7 +32,7 @@
#define CLKS_SYSCALL_KDBG_STACK_WINDOW_BYTES (128ULL * 1024ULL)
#define CLKS_SYSCALL_KERNEL_SYMBOL_FILE "/system/kernel.sym"
#define CLKS_SYSCALL_KERNEL_ADDR_BASE 0xFFFF800000000000ULL
#define CLKS_SYSCALL_STATS_MAX_ID CLKS_SYSCALL_STATS_RECENT_ID
#define CLKS_SYSCALL_STATS_MAX_ID CLKS_SYSCALL_FD_DUP
#define CLKS_SYSCALL_STATS_RING_SIZE 256U
struct clks_syscall_frame {
@@ -210,6 +210,40 @@ static u64 clks_syscall_kbd_get_char(void) {
return (u64)(u8)ch;
}
static u64 clks_syscall_fd_open(u64 arg0, u64 arg1, u64 arg2) {
char path[CLKS_SYSCALL_PATH_MAX];
if (clks_syscall_copy_user_string(arg0, path, sizeof(path)) == CLKS_FALSE) {
return (u64)-1;
}
return clks_exec_fd_open(path, arg1, arg2);
}
static u64 clks_syscall_fd_read(u64 arg0, u64 arg1, u64 arg2) {
if (arg2 > 0ULL && arg1 == 0ULL) {
return (u64)-1;
}
return clks_exec_fd_read(arg0, (void *)arg1, arg2);
}
static u64 clks_syscall_fd_write(u64 arg0, u64 arg1, u64 arg2) {
if (arg2 > 0ULL && arg1 == 0ULL) {
return (u64)-1;
}
return clks_exec_fd_write(arg0, (const void *)arg1, arg2);
}
static u64 clks_syscall_fd_close(u64 arg0) {
return clks_exec_fd_close(arg0);
}
static u64 clks_syscall_fd_dup(u64 arg0) {
return clks_exec_fd_dup(arg0);
}
static clks_bool clks_syscall_procfs_is_root(const char *path) {
return (path != CLKS_NULL && clks_strcmp(path, "/proc") == 0) ? CLKS_TRUE : CLKS_FALSE;
}
@@ -1786,6 +1820,16 @@ u64 clks_syscall_dispatch(void *frame_ptr) {
return clks_syscall_stats_recent_window();
case CLKS_SYSCALL_STATS_RECENT_ID:
return clks_syscall_stats_recent_id(frame->rbx);
case CLKS_SYSCALL_FD_OPEN:
return clks_syscall_fd_open(frame->rbx, frame->rcx, frame->rdx);
case CLKS_SYSCALL_FD_READ:
return clks_syscall_fd_read(frame->rbx, frame->rcx, frame->rdx);
case CLKS_SYSCALL_FD_WRITE:
return clks_syscall_fd_write(frame->rbx, frame->rcx, frame->rdx);
case CLKS_SYSCALL_FD_CLOSE:
return clks_syscall_fd_close(frame->rbx);
case CLKS_SYSCALL_FD_DUP:
return clks_syscall_fd_dup(frame->rbx);
default:
return (u64)-1;
}

View File

@@ -83,7 +83,7 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
- `/proc/<pid>`:指定 PID 快照文本
- `/proc` 为只读;写入类 syscall 不支持。
## 4. Syscall 列表0~71
## 4. Syscall 列表0~76
### 0 `CLEONOS_SYSCALL_LOG_WRITE`
@@ -557,6 +557,53 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
- `arg0`: `u64 id`
- 返回:指定 syscall ID 在“最近窗口”中的出现次数ID 越界返回 `0`
### 72 `CLEONOS_SYSCALL_FD_OPEN`
- 参数:
- `arg0`: `const char *path`
- `arg1`: `u64 flags`
- `arg2`: `u64 mode`(当前保留)
- 返回:成功返回 `fd`,失败返回 `-1`
- 说明:
- 当前支持普通文件与 `/dev/tty`
- 默认进程会预置 `fd 0/1/2`stdin/stdout/stderr
- 标志位兼容子集:`O_RDONLY/O_WRONLY/O_RDWR/O_CREAT/O_TRUNC/O_APPEND`
### 73 `CLEONOS_SYSCALL_FD_READ`
- 参数:
- `arg0`: `u64 fd`
- `arg1`: `void *out_buffer`
- `arg2`: `u64 size`
- 返回:读取字节数;错误返回 `-1`
- 说明:
-`tty fd`(如 stdin为非阻塞读取无输入时返回 `0`
- 对文件 fd 为顺序读取,内部维护偏移。
### 74 `CLEONOS_SYSCALL_FD_WRITE`
- 参数:
- `arg0`: `u64 fd`
- `arg1`: `const void *buffer`
- `arg2`: `u64 size`
- 返回:写入字节数;错误返回 `-1`
- 说明:
- `tty fd` 输出到终端。
- 文件 fd 支持顺序写;`O_APPEND` 下始终追加。
### 75 `CLEONOS_SYSCALL_FD_CLOSE`
- 参数:
- `arg0`: `u64 fd`
- 返回:成功 `0`,失败 `-1`
### 76 `CLEONOS_SYSCALL_FD_DUP`
- 参数:
- `arg0`: `u64 oldfd`
- 返回:新 fd失败 `-1`
- 说明:当前为“按值复制”语义(复制 flags/offset/目标对象)。
## 5. 用户态封装函数
用户态封装位于:
@@ -581,6 +628,7 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
- `cleonos_sys_proc_count()` / `cleonos_sys_proc_pid_at()` / `cleonos_sys_proc_snapshot()` / `cleonos_sys_proc_kill()`
- `cleonos_sys_kdbg_sym()` / `cleonos_sys_kdbg_bt()` / `cleonos_sys_kdbg_regs()`
- `cleonos_sys_stats_total()` / `cleonos_sys_stats_id_count()` / `cleonos_sys_stats_recent_window()` / `cleonos_sys_stats_recent_id()`
- `cleonos_sys_fd_open()` / `cleonos_sys_fd_read()` / `cleonos_sys_fd_write()` / `cleonos_sys_fd_close()` / `cleonos_sys_fd_dup()`
## 6. 开发注意事项
@@ -591,6 +639,6 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
## 7. Wine 兼容说明
- `wine/cleonos_wine_lib/runner.py` 目前以 syscall `0..67` 为主,新增 ID 需同步适配后才能完整观测统计类接口
- `wine/cleonos_wine_lib/runner.py` 目前以 syscall `0..67` 为主`68..76`stats/fd需同步适配后才能完整覆盖
- Wine 在运行时崩溃场景下会生成与内核一致格式的“信号编码退出状态”,可通过 `WAITPID` 读取。
- Wine 当前音频 syscall 为占位实现:`AUDIO_AVAILABLE=0``AUDIO_PLAY_TONE=0``AUDIO_STOP=1`