外网通讯+TTY优化

This commit is contained in:
2026-04-25 10:08:05 +08:00
parent fee891b413
commit 5cf65a757b
10 changed files with 552 additions and 47 deletions

View File

@@ -25,7 +25,17 @@ set(OBJCOPY_FOR_TARGET "llvm-objcopy" CACHE STRING "objcopy tool for limine conf
set(OBJDUMP_FOR_TARGET "llvm-objdump" CACHE STRING "objdump tool for limine configure")
set(READELF_FOR_TARGET "llvm-readelf" CACHE STRING "readelf tool for limine configure")
set(QEMU_X86_64 "qemu-system-x86_64" CACHE STRING "QEMU executable")
set(QEMU_X86_64 "qemu-system-x86_64" CACHE STRING "QEMU executable")
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
set(_cleonos_qemu_kvm_default ON)
else()
set(_cleonos_qemu_kvm_default OFF)
endif()
set(CLEONOS_QEMU_ENABLE_KVM ${_cleonos_qemu_kvm_default} CACHE BOOL "Enable QEMU KVM acceleration for run/debug targets")
set(CLEONOS_QEMU_ACCEL_ARGS "")
if(CLEONOS_QEMU_ENABLE_KVM)
list(APPEND CLEONOS_QEMU_ACCEL_ARGS -enable-kvm -cpu host)
endif()
set(CLEONOS_SOURCE_DIR "${CMAKE_SOURCE_DIR}/cleonos")
if(EXISTS "${CLEONOS_SOURCE_DIR}/CMakeLists.txt")
@@ -348,27 +358,27 @@ if(CLEONOS_ENABLE)
add_custom_target(iso ALL DEPENDS "${ISO_IMAGE}")
add_dependencies(iso setup-tools setup-limine kernel ramdisk)
add_custom_target(run
COMMAND ${CMAKE_COMMAND}
"-DNO_COLOR=${NO_COLOR}"
"-DLOG_LEVEL=STEP"
"-DLOG_TEXT=launching qemu run"
-P "${CL_LOG_EMIT_SCRIPT}"
COMMAND ${QEMU_X86_64} -M pc -m 1024M -boot order=d -cdrom "${ISO_IMAGE}" -drive "file=${DISK_IMAGE},format=raw,if=none,id=clksdisk,media=disk" -device "ide-hd,drive=clksdisk,bus=ide.0" -netdev "user,id=clksnet0" -device "e1000,netdev=clksnet0" -serial stdio
DEPENDS iso disk-image
USES_TERMINAL
)
add_custom_target(run
COMMAND ${CMAKE_COMMAND}
"-DNO_COLOR=${NO_COLOR}"
"-DLOG_LEVEL=STEP"
"-DLOG_TEXT=launching qemu run"
-P "${CL_LOG_EMIT_SCRIPT}"
COMMAND ${QEMU_X86_64} ${CLEONOS_QEMU_ACCEL_ARGS} -M pc -m 1024M -boot order=d -cdrom "${ISO_IMAGE}" -drive "file=${DISK_IMAGE},format=raw,if=none,id=clksdisk,media=disk" -device "ide-hd,drive=clksdisk,bus=ide.0" -netdev "user,id=clksnet0" -device "e1000,netdev=clksnet0" -serial stdio
DEPENDS iso disk-image
USES_TERMINAL
)
add_custom_target(debug
COMMAND ${CMAKE_COMMAND}
"-DNO_COLOR=${NO_COLOR}"
"-DLOG_LEVEL=STEP"
"-DLOG_TEXT=launching qemu debug (-s -S)"
-P "${CL_LOG_EMIT_SCRIPT}"
COMMAND ${QEMU_X86_64} -M pc -m 1024M -boot order=d -cdrom "${ISO_IMAGE}" -drive "file=${DISK_IMAGE},format=raw,if=none,id=clksdisk,media=disk" -device "ide-hd,drive=clksdisk,bus=ide.0" -netdev "user,id=clksnet0" -device "e1000,netdev=clksnet0" -serial stdio -s -S
DEPENDS iso disk-image
USES_TERMINAL
)
add_custom_target(debug
COMMAND ${CMAKE_COMMAND}
"-DNO_COLOR=${NO_COLOR}"
"-DLOG_LEVEL=STEP"
"-DLOG_TEXT=launching qemu debug (-s -S)"
-P "${CL_LOG_EMIT_SCRIPT}"
COMMAND ${QEMU_X86_64} ${CLEONOS_QEMU_ACCEL_ARGS} -M pc -m 1024M -boot order=d -cdrom "${ISO_IMAGE}" -drive "file=${DISK_IMAGE},format=raw,if=none,id=clksdisk,media=disk" -device "ide-hd,drive=clksdisk,bus=ide.0" -netdev "user,id=clksnet0" -device "e1000,netdev=clksnet0" -serial stdio -s -S
DEPENDS iso disk-image
USES_TERMINAL
)
else()
add_custom_target(clks-default ALL DEPENDS kernel)
endif()

View File

@@ -236,6 +236,9 @@ help:
> $(Q)echo " make run V=1"
> $(Q)echo " make run SHOW_COMMANDS=1"
> $(Q)echo " (includes CMake build internals: compiler/linker command lines)"
> $(Q)echo "QEMU KVM toggle:"
> $(Q)echo " make run CMAKE_EXTRA_ARGS='-DCLEONOS_QEMU_ENABLE_KVM=ON' # force on"
> $(Q)echo " make run CMAKE_EXTRA_ARGS='-DCLEONOS_QEMU_ENABLE_KVM=OFF' # force off"
> $(Q)echo ""
> $(Q)echo "Pass custom CMake cache args via:"
> $(Q)echo " make configure CMAKE_EXTRA_ARGS='-DLIMINE_SKIP_CONFIGURE=1 -DOBJCOPY_FOR_TARGET=objcopy'"

View File

@@ -128,7 +128,7 @@ list(SORT DOOMGENERIC_DEP_SOURCES_ABS)
set(USER_SHELL_COMMAND_APPS
help args ls cat grep head tail wc cut uniq sort pwd cd exec pid spawn wait sleep yield
ping
ping ifconfig nslookup
bg fg jobs kill ps top
procstat sysstat
diskinfo mkfsfat32 mount partctl

View File

@@ -32,9 +32,11 @@ static int ush_cmd_help(void) {
ush_writeln(" diskinfo");
ush_writeln(" mkfsfat32 [label]");
ush_writeln(" mount [path] (default suggested: /temp/disk)");
ush_writeln(" partctl <subcommand> (mbr partition control: list/init-mbr/create/delete/set-boot)");
ush_writeln(" ping <a.b.c.d> [count]");
ush_writeln(" pid");
ush_writeln(" partctl <subcommand> (mbr partition control: list/init-mbr/create/delete/set-boot)");
ush_writeln(" ping <a.b.c.d> [count]");
ush_writeln(" ifconfig");
ush_writeln(" nslookup <domain>");
ush_writeln(" pid");
ush_writeln(" spawn <path|name> [args...] / bg <path|name> [args...]");
ush_writeln(" wait <pid> / fg [pid]");
ush_writeln(" kill <pid> [signal]");

View File

@@ -0,0 +1,101 @@
#include "cmd_runtime.h"
#include <stdio.h>
static void ush_ifconfig_print_ipv4(u64 ipv4_be) {
unsigned int a = (unsigned int)((ipv4_be >> 24ULL) & 0xFFULL);
unsigned int b = (unsigned int)((ipv4_be >> 16ULL) & 0xFFULL);
unsigned int c = (unsigned int)((ipv4_be >> 8ULL) & 0xFFULL);
unsigned int d = (unsigned int)(ipv4_be & 0xFFULL);
(void)printf("%u.%u.%u.%u", a, b, c, d);
}
static int ush_cmd_ifconfig(const char *arg) {
u64 available;
u64 ip;
u64 netmask;
u64 gateway;
u64 dns;
if (arg != (const char *)0 && arg[0] != '\0') {
if (ush_streq(arg, "--help") != 0 || ush_streq(arg, "-h") != 0) {
(void)puts("usage: ifconfig");
return 1;
}
(void)puts("ifconfig: usage ifconfig");
return 0;
}
available = cleonos_sys_net_available();
if (available == 0ULL) {
(void)puts("ifconfig: network unavailable");
return 0;
}
ip = cleonos_sys_net_ipv4_addr();
netmask = cleonos_sys_net_netmask();
gateway = cleonos_sys_net_gateway();
dns = cleonos_sys_net_dns_server();
(void)fputs("inet: ", 1);
ush_ifconfig_print_ipv4(ip);
(void)putchar('\n');
(void)fputs("netmask: ", 1);
ush_ifconfig_print_ipv4(netmask);
(void)putchar('\n');
(void)fputs("gateway: ", 1);
ush_ifconfig_print_ipv4(gateway);
(void)putchar('\n');
(void)fputs("dns: ", 1);
ush_ifconfig_print_ipv4(dns);
(void)putchar('\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, "ifconfig") != 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_ifconfig(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,353 @@
#include "cmd_runtime.h"
#include <stdio.h>
#define USH_DNS_QUERY_MAX 512U
typedef unsigned char u8;
typedef unsigned short u16;
static u16 ush_dns_read_be16(const u8 *ptr) {
return (u16)(((u16)ptr[0] << 8U) | (u16)ptr[1]);
}
static void ush_dns_write_be16(u8 *ptr, u16 value) {
ptr[0] = (u8)((value >> 8U) & 0xFFU);
ptr[1] = (u8)(value & 0xFFU);
}
static void ush_dns_print_ipv4_be(u64 ipv4_be) {
unsigned int a = (unsigned int)((ipv4_be >> 24ULL) & 0xFFULL);
unsigned int b = (unsigned int)((ipv4_be >> 16ULL) & 0xFFULL);
unsigned int c = (unsigned int)((ipv4_be >> 8ULL) & 0xFFULL);
unsigned int d = (unsigned int)(ipv4_be & 0xFFULL);
(void)printf("%u.%u.%u.%u", a, b, c, d);
}
static int ush_dns_encode_qname(const char *host, u8 *out, u64 out_cap, u64 *out_len) {
const char *p;
u64 at = 0ULL;
if (host == (const char *)0 || out == (u8 *)0 || out_len == (u64 *)0 || out_cap < 2ULL || host[0] == '\0') {
return 0;
}
p = host;
while (*p != '\0') {
const char *dot = p;
u64 label_len;
u64 i;
while (*dot != '\0' && *dot != '.') {
dot++;
}
label_len = (u64)(dot - p);
if (label_len == 0ULL || label_len > 63ULL) {
return 0;
}
if (at + 1ULL + label_len + 1ULL > out_cap) {
return 0;
}
out[at++] = (u8)label_len;
for (i = 0ULL; i < label_len; i++) {
out[at++] = (u8)p[i];
}
if (*dot == '.') {
p = dot + 1;
} else {
p = dot;
}
}
out[at++] = 0U;
*out_len = at;
return 1;
}
static int ush_dns_skip_name(const u8 *msg, u64 msg_len, u64 *io_off) {
u64 pos;
u64 depth = 0ULL;
int jumped = 0;
if (msg == (const u8 *)0 || io_off == (u64 *)0 || *io_off >= msg_len) {
return 0;
}
pos = *io_off;
while (depth < 32ULL) {
u8 len;
if (pos >= msg_len) {
return 0;
}
len = msg[pos];
if (len == 0U) {
if (jumped == 0) {
*io_off = pos + 1ULL;
}
return 1;
}
if ((len & 0xC0U) == 0xC0U) {
u16 ptr;
if (pos + 1ULL >= msg_len) {
return 0;
}
ptr = (u16)(((u16)(len & 0x3FU) << 8U) | (u16)msg[pos + 1ULL]);
if ((u64)ptr >= msg_len) {
return 0;
}
if (jumped == 0) {
*io_off = pos + 2ULL;
jumped = 1;
}
pos = (u64)ptr;
depth++;
continue;
}
if ((len & 0xC0U) != 0U) {
return 0;
}
if (pos + 1ULL + (u64)len > msg_len) {
return 0;
}
pos += 1ULL + (u64)len;
if (jumped == 0) {
*io_off = pos;
}
depth++;
}
return 0;
}
static int ush_dns_parse_response(const u8 *resp, u64 resp_len, u16 expected_id) {
u16 id;
u16 flags;
u16 qdcount;
u16 ancount;
u16 i;
u64 off = 12ULL;
int found = 0;
if (resp == (const u8 *)0 || resp_len < 12ULL) {
return 0;
}
id = ush_dns_read_be16(&resp[0]);
if (id != expected_id) {
return 0;
}
flags = ush_dns_read_be16(&resp[2]);
qdcount = ush_dns_read_be16(&resp[4]);
ancount = ush_dns_read_be16(&resp[6]);
if ((flags & 0x8000U) == 0U) {
return 0;
}
if ((flags & 0x000FU) != 0U) {
(void)printf("nslookup: server error rcode=%u\n", (unsigned int)(flags & 0x000FU));
return 0;
}
for (i = 0U; i < qdcount; i++) {
if (ush_dns_skip_name(resp, resp_len, &off) == 0) {
return 0;
}
if (off + 4ULL > resp_len) {
return 0;
}
off += 4ULL;
}
for (i = 0U; i < ancount; i++) {
u16 type;
u16 klass;
u16 rdlen;
if (ush_dns_skip_name(resp, resp_len, &off) == 0) {
return found;
}
if (off + 10ULL > resp_len) {
return found;
}
type = ush_dns_read_be16(&resp[off + 0ULL]);
klass = ush_dns_read_be16(&resp[off + 2ULL]);
rdlen = ush_dns_read_be16(&resp[off + 8ULL]);
off += 10ULL;
if (off + (u64)rdlen > resp_len) {
return found;
}
if (type == 1U && klass == 1U && rdlen == 4U) {
u64 ip = ((u64)resp[off] << 24ULL) | ((u64)resp[off + 1ULL] << 16ULL) |
((u64)resp[off + 2ULL] << 8ULL) | (u64)resp[off + 3ULL];
ush_dns_print_ipv4_be(ip);
(void)putchar('\n');
found++;
}
off += (u64)rdlen;
}
return found;
}
static int ush_cmd_nslookup(const char *arg) {
u64 dns_server;
u8 query[USH_DNS_QUERY_MAX];
u8 answer[USH_DNS_QUERY_MAX];
u64 qname_len = 0ULL;
u64 query_len;
u16 txid;
u16 src_port;
cleonos_net_udp_send_req send_req;
int loops;
if (arg == (const char *)0 || arg[0] == '\0') {
(void)puts("nslookup: usage nslookup <domain>");
return 0;
}
if (cleonos_sys_net_available() == 0ULL) {
(void)puts("nslookup: network unavailable");
return 0;
}
dns_server = cleonos_sys_net_dns_server();
if (dns_server == 0ULL) {
(void)puts("nslookup: dns server unavailable");
return 0;
}
txid = (u16)((cleonos_sys_timer_ticks() ^ 0xA5C3ULL) & 0xFFFFULL);
src_port = (u16)(40000U + (txid % 20000U));
(void)memset(query, 0, sizeof(query));
if (ush_dns_encode_qname(arg, query + 12ULL, (u64)sizeof(query) - 12ULL, &qname_len) == 0) {
(void)puts("nslookup: invalid domain");
return 0;
}
ush_dns_write_be16(&query[0], txid);
ush_dns_write_be16(&query[2], 0x0100U);
ush_dns_write_be16(&query[4], 1U);
ush_dns_write_be16(&query[6], 0U);
ush_dns_write_be16(&query[8], 0U);
ush_dns_write_be16(&query[10], 0U);
query_len = 12ULL + qname_len;
if (query_len + 4ULL > (u64)sizeof(query)) {
(void)puts("nslookup: query too large");
return 0;
}
ush_dns_write_be16(&query[query_len], 1U);
ush_dns_write_be16(&query[query_len + 2ULL], 1U);
query_len += 4ULL;
send_req.dst_ipv4_be = dns_server;
send_req.dst_port = 53ULL;
send_req.src_port = (u64)src_port;
send_req.payload_ptr = (u64)(usize)query;
send_req.payload_len = query_len;
if (cleonos_sys_net_udp_send(&send_req) != query_len) {
(void)puts("nslookup: send failed");
return 0;
}
(void)fputs("Server: ", 1);
ush_dns_print_ipv4_be(dns_server);
(void)putchar('\n');
(void)fputs("Query: ", 1);
(void)puts(arg);
(void)puts("Answer:");
for (loops = 0; loops < 600; loops++) {
cleonos_net_udp_recv_req recv_req;
u64 got;
u64 src_ip = 0ULL;
u64 src_p = 0ULL;
u64 dst_p = 0ULL;
recv_req.out_payload_ptr = (u64)(usize)answer;
recv_req.payload_capacity = (u64)sizeof(answer);
recv_req.out_src_ipv4_ptr = (u64)(usize)&src_ip;
recv_req.out_src_port_ptr = (u64)(usize)&src_p;
recv_req.out_dst_port_ptr = (u64)(usize)&dst_p;
got = cleonos_sys_net_udp_recv(&recv_req);
if (got == 0ULL) {
(void)cleonos_sys_sleep_ticks(2ULL);
continue;
}
if (src_p != 53ULL || src_ip != dns_server) {
continue;
}
if (ush_dns_parse_response(answer, got, txid) > 0) {
return 1;
}
}
(void)puts("nslookup: timeout");
return 0;
}
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, "nslookup") != 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_nslookup(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

@@ -172,10 +172,13 @@ typedef struct cleonos_net_udp_recv_req {
#define CLEONOS_SYSCALL_DISK_READ_SECTOR 93ULL
#define CLEONOS_SYSCALL_DISK_WRITE_SECTOR 94ULL
#define CLEONOS_SYSCALL_NET_AVAILABLE 95ULL
#define CLEONOS_SYSCALL_NET_IPV4_ADDR 96ULL
#define CLEONOS_SYSCALL_NET_PING 97ULL
#define CLEONOS_SYSCALL_NET_UDP_SEND 98ULL
#define CLEONOS_SYSCALL_NET_UDP_RECV 99ULL
#define CLEONOS_SYSCALL_NET_IPV4_ADDR 96ULL
#define CLEONOS_SYSCALL_NET_PING 97ULL
#define CLEONOS_SYSCALL_NET_UDP_SEND 98ULL
#define CLEONOS_SYSCALL_NET_UDP_RECV 99ULL
#define CLEONOS_SYSCALL_NET_NETMASK 100ULL
#define CLEONOS_SYSCALL_NET_GATEWAY 101ULL
#define CLEONOS_SYSCALL_NET_DNS_SERVER 102ULL
u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
u64 cleonos_sys_log_write(const char *message, u64 length);
@@ -273,10 +276,13 @@ u64 cleonos_sys_disk_mounted(void);
u64 cleonos_sys_disk_mount_path(char *out_path, u64 out_size);
u64 cleonos_sys_disk_read_sector(u64 lba, void *out_sector);
u64 cleonos_sys_disk_write_sector(u64 lba, const void *sector_data);
u64 cleonos_sys_net_available(void);
u64 cleonos_sys_net_ipv4_addr(void);
u64 cleonos_sys_net_ping(u64 dst_ipv4_be, u64 poll_budget);
u64 cleonos_sys_net_udp_send(const cleonos_net_udp_send_req *req);
u64 cleonos_sys_net_udp_recv(cleonos_net_udp_recv_req *req);
u64 cleonos_sys_net_available(void);
u64 cleonos_sys_net_ipv4_addr(void);
u64 cleonos_sys_net_netmask(void);
u64 cleonos_sys_net_gateway(void);
u64 cleonos_sys_net_dns_server(void);
u64 cleonos_sys_net_ping(u64 dst_ipv4_be, u64 poll_budget);
u64 cleonos_sys_net_udp_send(const cleonos_net_udp_send_req *req);
u64 cleonos_sys_net_udp_recv(cleonos_net_udp_recv_req *req);
#endif

View File

@@ -416,13 +416,25 @@ u64 cleonos_sys_net_available(void) {
return cleonos_syscall(CLEONOS_SYSCALL_NET_AVAILABLE, 0ULL, 0ULL, 0ULL);
}
u64 cleonos_sys_net_ipv4_addr(void) {
return cleonos_syscall(CLEONOS_SYSCALL_NET_IPV4_ADDR, 0ULL, 0ULL, 0ULL);
}
u64 cleonos_sys_net_ping(u64 dst_ipv4_be, u64 poll_budget) {
return cleonos_syscall(CLEONOS_SYSCALL_NET_PING, dst_ipv4_be, poll_budget, 0ULL);
}
u64 cleonos_sys_net_ipv4_addr(void) {
return cleonos_syscall(CLEONOS_SYSCALL_NET_IPV4_ADDR, 0ULL, 0ULL, 0ULL);
}
u64 cleonos_sys_net_netmask(void) {
return cleonos_syscall(CLEONOS_SYSCALL_NET_NETMASK, 0ULL, 0ULL, 0ULL);
}
u64 cleonos_sys_net_gateway(void) {
return cleonos_syscall(CLEONOS_SYSCALL_NET_GATEWAY, 0ULL, 0ULL, 0ULL);
}
u64 cleonos_sys_net_dns_server(void) {
return cleonos_syscall(CLEONOS_SYSCALL_NET_DNS_SERVER, 0ULL, 0ULL, 0ULL);
}
u64 cleonos_sys_net_ping(u64 dst_ipv4_be, u64 poll_budget) {
return cleonos_syscall(CLEONOS_SYSCALL_NET_PING, dst_ipv4_be, poll_budget, 0ULL);
}
u64 cleonos_sys_net_udp_send(const cleonos_net_udp_send_req *req) {
return cleonos_syscall(CLEONOS_SYSCALL_NET_UDP_SEND, (u64)req, 0ULL, 0ULL);

2
clks

Submodule clks updated: f7c89a3420...9c23c272d0

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~99
## 4. Syscall 列表0~102
### 0 `CLEONOS_SYSCALL_LOG_WRITE`
@@ -740,7 +740,7 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
- 参数:无
- 返回:当前 IPv4 地址(`u32`,以网络字节序放在返回值低 32 位)。
- 说明:当前默认静态地址为 `10.0.2.15`QEMU usernet 常见配置)。
- 说明:优先使用 DHCP 自动获取地址;若 DHCP 失败回退到 `10.0.2.15`QEMU usernet 常见默认值)。
### 97 `CLEONOS_SYSCALL_NET_PING`
@@ -762,6 +762,24 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
- `arg0`: `struct { u64 out_payload_ptr; u64 payload_capacity; u64 out_src_ipv4_ptr; u64 out_src_port_ptr; u64 out_dst_port_ptr; } *req`
- 返回:实际拷贝到 `out_payload_ptr` 的字节数;无数据/失败返回 `0`
- 说明:`out_src_*`/`out_dst_*` 指针可为 `0`(表示不关心该字段)。
### 100 `CLEONOS_SYSCALL_NET_NETMASK`
- 参数:无
- 返回:当前 IPv4 子网掩码(`u32`,网络字节序,位于返回值低 32 位)。
- 说明:优先使用 DHCP 下发值;若 DHCP 未提供则按回退策略填充。
### 101 `CLEONOS_SYSCALL_NET_GATEWAY`
- 参数:无
- 返回:当前 IPv4 默认网关(`u32`,网络字节序,位于返回值低 32 位)。
- 说明:优先使用 DHCP 下发值;若 DHCP 未提供则按回退策略填充。
### 102 `CLEONOS_SYSCALL_NET_DNS_SERVER`
- 参数:无
- 返回:当前 DNS 服务器 IPv4`u32`,网络字节序,位于返回值低 32 位)。
- 说明:优先使用 DHCP 下发值;若 DHCP 未提供则按回退策略填充。
## 5. 用户态封装函数
@@ -795,7 +813,7 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
- `cleonos_sys_disk_present()` / `cleonos_sys_disk_size_bytes()` / `cleonos_sys_disk_sector_count()`
- `cleonos_sys_disk_formatted()` / `cleonos_sys_disk_format_fat32()` / `cleonos_sys_disk_mount()` / `cleonos_sys_disk_mounted()` / `cleonos_sys_disk_mount_path()`
- `cleonos_sys_disk_read_sector()` / `cleonos_sys_disk_write_sector()`
- `cleonos_sys_net_available()` / `cleonos_sys_net_ipv4_addr()` / `cleonos_sys_net_ping()`
- `cleonos_sys_net_available()` / `cleonos_sys_net_ipv4_addr()` / `cleonos_sys_net_netmask()` / `cleonos_sys_net_gateway()` / `cleonos_sys_net_dns_server()` / `cleonos_sys_net_ping()`
- `cleonos_sys_net_udp_send()` / `cleonos_sys_net_udp_recv()`
## 6. 开发注意事项
@@ -807,7 +825,7 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
## 7. Wine 兼容说明
- `wine/cleonos_wine_lib/runner.py` 当前已覆盖到 `0..99`(含 `DL_*``FB_*``KERNEL_VERSION``DISK_*``NET_*`)。
- `wine/cleonos_wine_lib/runner.py` 当前已覆盖到 `0..102`(含 `DL_*``FB_*``KERNEL_VERSION``DISK_*``NET_*`)。
- `DL_*``77..79`)在 Wine 中为“可运行兼容”实现:
- `DL_OPEN`:加载 guest ELF 到当前 Unicorn 地址空间,返回稳定 `handle`,并做引用计数。
- `DL_SYM`:解析 ELF `SYMTAB/DYNSYM` 并返回 guest 可调用地址。
@@ -824,7 +842,7 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
- `DISK_FORMAT_FAT32` 会初始化/重置 Wine rootfs 下的虚拟磁盘目录。
- `DISK_MOUNT`/`DISK_MOUNT_PATH` 支持挂载点管理,并与 `FS_MKDIR/WRITE/APPEND/REMOVE` 的路径规则联动。
- `DISK_READ_SECTOR`/`DISK_WRITE_SECTOR``93..94`)在 Wine 中已实现为 512B 原始扇区读写host 文件后端)。
- 网络 syscall`95..99`)在 Wine 当前为兼容占位实现(统一返回 `0`);即 Wine 运行模式下不会提供真实网络收发。
- 网络 syscall`95..102`)在 Wine 当前为兼容占位实现(统一返回 `0`);即 Wine 运行模式下不会提供真实网络收发。
- Wine 在运行时崩溃场景下会生成与内核一致格式的“信号编码退出状态”,可通过 `WAITPID` 读取。
- Wine 当前音频 syscall 为占位实现:`AUDIO_AVAILABLE=0``AUDIO_PLAY_TONE=0``AUDIO_STOP=1`
- Wine 版本号策略固定为 `85.0.0-wine`(历史兼容号;不会随 syscall 扩展继续增长)。