static fs_node_t g_proc_uptime;
static fs_node_t g_proc_meminfo;
+#define PID_NODE_POOL 8
+static fs_node_t g_pid_dir[PID_NODE_POOL];
+static fs_node_t g_pid_status[PID_NODE_POOL];
+static fs_node_t g_pid_maps[PID_NODE_POOL];
+static uint32_t g_pid_pool_idx = 0;
+
extern struct process* ready_queue_head;
+static struct process* proc_find_pid(uint32_t pid) {
+ if (!ready_queue_head) return NULL;
+ struct process* it = ready_queue_head;
+ const struct process* start = it;
+ do {
+ if (it->pid == pid) return it;
+ it = it->next;
+ } while (it && it != start);
+ return NULL;
+}
+
static int proc_snprintf(char* buf, uint32_t sz, const char* key, uint32_t val) {
if (sz < 2) return 0;
uint32_t w = 0;
return size;
}
+/* --- per-PID status read (inode == target pid) --- */
+
+static uint32_t proc_pid_status_read(fs_node_t* node, uint32_t offset, uint32_t size, uint8_t* buffer) {
+ uint32_t pid = node->inode;
+ struct process* p = proc_find_pid(pid);
+ if (!p) return 0;
+
+ char tmp[512];
+ uint32_t len = 0;
+
+ len += (uint32_t)proc_snprintf(tmp + len, sizeof(tmp) - len, "Pid:\t", p->pid);
+ len += (uint32_t)proc_snprintf(tmp + len, sizeof(tmp) - len, "PPid:\t", p->parent_pid);
+ len += (uint32_t)proc_snprintf(tmp + len, sizeof(tmp) - len, "Pgrp:\t", p->pgrp_id);
+ len += (uint32_t)proc_snprintf(tmp + len, sizeof(tmp) - len, "Session:\t", p->session_id);
+
+ const char* state_str = "unknown\n";
+ switch (p->state) {
+ case PROCESS_READY: state_str = "R (ready)\n"; break;
+ case PROCESS_RUNNING: state_str = "R (running)\n"; break;
+ case PROCESS_BLOCKED: state_str = "S (blocked)\n"; break;
+ case PROCESS_SLEEPING: state_str = "S (sleeping)\n"; break;
+ case PROCESS_ZOMBIE: state_str = "Z (zombie)\n"; break;
+ }
+ const char* s = "State:\t";
+ while (*s && len + 1 < sizeof(tmp)) tmp[len++] = *s++;
+ s = state_str;
+ while (*s && len + 1 < sizeof(tmp)) tmp[len++] = *s++;
+
+ len += (uint32_t)proc_snprintf(tmp + len, sizeof(tmp) - len, "SigPnd:\t", p->sig_pending_mask);
+ len += (uint32_t)proc_snprintf(tmp + len, sizeof(tmp) - len, "SigBlk:\t", p->sig_blocked_mask);
+ len += (uint32_t)proc_snprintf(tmp + len, sizeof(tmp) - len, "HeapStart:\t", (uint32_t)p->heap_start);
+ len += (uint32_t)proc_snprintf(tmp + len, sizeof(tmp) - len, "HeapBreak:\t", (uint32_t)p->heap_break);
+
+ if (offset >= len) return 0;
+ uint32_t avail = len - offset;
+ if (size > avail) size = avail;
+ memcpy(buffer, tmp + offset, size);
+ return size;
+}
+
+/* --- per-PID maps read (inode == target pid) --- */
+
+static uint32_t proc_pid_maps_read(fs_node_t* node, uint32_t offset, uint32_t size, uint8_t* buffer) {
+ uint32_t pid = node->inode;
+ struct process* p = proc_find_pid(pid);
+ if (!p) return 0;
+
+ char tmp[1024];
+ uint32_t len = 0;
+
+ if (p->heap_start && p->heap_break > p->heap_start) {
+ len += (uint32_t)proc_snprintf(tmp + len, sizeof(tmp) - len, "heap:\t", (uint32_t)p->heap_start);
+ len += (uint32_t)proc_snprintf(tmp + len, sizeof(tmp) - len, "brk:\t", (uint32_t)p->heap_break);
+ }
+
+ for (int i = 0; i < PROCESS_MAX_MMAPS; i++) {
+ if (p->mmaps[i].length == 0) continue;
+ len += (uint32_t)proc_snprintf(tmp + len, sizeof(tmp) - len, "mmap:\t", (uint32_t)p->mmaps[i].base);
+ len += (uint32_t)proc_snprintf(tmp + len, sizeof(tmp) - len, "len:\t", p->mmaps[i].length);
+ }
+
+ if (len == 0) {
+ const char* msg = "(empty)\n";
+ while (*msg && len + 1 < sizeof(tmp)) tmp[len++] = *msg++;
+ }
+
+ if (offset >= len) return 0;
+ uint32_t avail = len - offset;
+ if (size > avail) size = avail;
+ memcpy(buffer, tmp + offset, size);
+ return size;
+}
+
+/* --- per-PID directory --- */
+
+static fs_node_t* proc_pid_finddir(fs_node_t* node, const char* name) {
+ uint32_t pid = node->inode;
+ uint32_t slot = g_pid_pool_idx;
+
+ if (strcmp(name, "status") == 0) {
+ g_pid_pool_idx = (slot + 1) % PID_NODE_POOL;
+ memset(&g_pid_status[slot], 0, sizeof(fs_node_t));
+ strcpy(g_pid_status[slot].name, "status");
+ g_pid_status[slot].flags = FS_FILE;
+ g_pid_status[slot].inode = pid;
+ g_pid_status[slot].read = proc_pid_status_read;
+ return &g_pid_status[slot];
+ }
+ if (strcmp(name, "maps") == 0) {
+ g_pid_pool_idx = (slot + 1) % PID_NODE_POOL;
+ memset(&g_pid_maps[slot], 0, sizeof(fs_node_t));
+ strcpy(g_pid_maps[slot].name, "maps");
+ g_pid_maps[slot].flags = FS_FILE;
+ g_pid_maps[slot].inode = pid;
+ g_pid_maps[slot].read = proc_pid_maps_read;
+ return &g_pid_maps[slot];
+ }
+ return NULL;
+}
+
+static int proc_pid_readdir(fs_node_t* node, uint32_t* inout_index, void* buf, uint32_t buf_len) {
+ (void)node;
+ if (!inout_index || !buf) return -1;
+ if (buf_len < sizeof(struct vfs_dirent)) return -1;
+
+ static const char* entries[] = { "status", "maps" };
+ uint32_t idx = *inout_index;
+ if (idx >= 2) return 0;
+
+ struct vfs_dirent* d = (struct vfs_dirent*)buf;
+ d->d_ino = 300 + idx;
+ d->d_type = FS_FILE;
+ d->d_reclen = sizeof(struct vfs_dirent);
+ {
+ const char* s = entries[idx];
+ uint32_t j = 0;
+ while (s[j] && j + 1 < sizeof(d->d_name)) { d->d_name[j] = s[j]; j++; }
+ d->d_name[j] = 0;
+ }
+ *inout_index = idx + 1;
+ return (int)sizeof(struct vfs_dirent);
+}
+
+static fs_node_t* proc_get_pid_dir(uint32_t pid) {
+ if (!proc_find_pid(pid)) return NULL;
+ uint32_t slot = g_pid_pool_idx;
+ g_pid_pool_idx = (slot + 1) % PID_NODE_POOL;
+ memset(&g_pid_dir[slot], 0, sizeof(fs_node_t));
+ char num[16];
+ itoa(pid, num, 10);
+ strcpy(g_pid_dir[slot].name, num);
+ g_pid_dir[slot].flags = FS_DIRECTORY;
+ g_pid_dir[slot].inode = pid;
+ g_pid_dir[slot].finddir = proc_pid_finddir;
+ g_pid_dir[slot].readdir = proc_pid_readdir;
+ return &g_pid_dir[slot];
+}
+
+/* --- /proc/self --- */
+
static fs_node_t* proc_self_finddir(fs_node_t* node, const char* name) {
(void)node;
if (strcmp(name, "status") == 0) return &g_proc_self_status;
return (int)sizeof(struct vfs_dirent);
}
+static int is_numeric(const char* s) {
+ if (!s || !*s) return 0;
+ while (*s) { if (*s < '0' || *s > '9') return 0; s++; }
+ return 1;
+}
+
+static uint32_t parse_uint(const char* s) {
+ uint32_t v = 0;
+ while (*s >= '0' && *s <= '9') { v = v * 10 + (uint32_t)(*s - '0'); s++; }
+ return v;
+}
+
static fs_node_t* proc_root_finddir(fs_node_t* node, const char* name) {
(void)node;
if (strcmp(name, "self") == 0) return &g_proc_self;
if (strcmp(name, "uptime") == 0) return &g_proc_uptime;
if (strcmp(name, "meminfo") == 0) return &g_proc_meminfo;
+ if (is_numeric(name)) return proc_get_pid_dir(parse_uint(name));
return NULL;
}
if (!inout_index || !buf) return -1;
if (buf_len < sizeof(struct vfs_dirent)) return -1;
- static const char* entries[] = { "self", "uptime", "meminfo" };
uint32_t idx = *inout_index;
- if (idx >= 3) return 0;
-
struct vfs_dirent* d = (struct vfs_dirent*)buf;
- d->d_ino = 200 + idx;
- d->d_type = (idx == 0) ? 2 : 0;
- d->d_reclen = sizeof(struct vfs_dirent);
- {
- const char* s = entries[idx];
+
+ static const char* fixed[] = { "self", "uptime", "meminfo" };
+ if (idx < 3) {
+ d->d_ino = 200 + idx;
+ d->d_type = (idx == 0) ? FS_DIRECTORY : FS_FILE;
+ d->d_reclen = sizeof(struct vfs_dirent);
+ const char* s = fixed[idx];
uint32_t j = 0;
while (s[j] && j + 1 < sizeof(d->d_name)) { d->d_name[j] = s[j]; j++; }
d->d_name[j] = 0;
+ *inout_index = idx + 1;
+ return (int)sizeof(struct vfs_dirent);
}
- *inout_index = idx + 1;
- return (int)sizeof(struct vfs_dirent);
+
+ /* After fixed entries, list numeric PIDs */
+ uint32_t pi = idx - 3;
+ uint32_t count = 0;
+ if (ready_queue_head) {
+ struct process* it = ready_queue_head;
+ const struct process* start = it;
+ do {
+ if (count == pi) {
+ char num[16];
+ itoa(it->pid, num, 10);
+ d->d_ino = 400 + it->pid;
+ d->d_type = FS_DIRECTORY;
+ d->d_reclen = sizeof(struct vfs_dirent);
+ uint32_t j = 0;
+ while (num[j] && j + 1 < sizeof(d->d_name) && j < sizeof(num) - 1) { d->d_name[j] = num[j]; j++; }
+ d->d_name[j] = 0;
+ *inout_index = idx + 1;
+ return (int)sizeof(struct vfs_dirent);
+ }
+ count++;
+ it = it->next;
+ } while (it && it != start);
+ }
+
+ return 0;
}
fs_node_t* procfs_create_root(void) {