diff options
| author | bernard <[email protected]> | 2026-08-23 07:44:06 +0800 |
|---|---|---|
| committer | Rbb666 <[email protected]> | 2026-08-30 20:49:24 +0800 |
| commit | 25cbe4abae05e9be46edff3966850af8a7f58515 (patch) | |
| tree | 23b53221ea762371677ab70b64a6b8b8a02cc79b /components | |
| parent | f02a869318c9df28ec2eab41f1a58795dc8a3f1b (diff) | |
[dfs][procfs] Add Linux-compatible process and system files
补齐 procfs 中 cpuinfo、stat、uptime、loadavg、meminfo、mounts 和进程目录文件。
按架构和 SMP 配置隔离仅在对应平台有效的字段,避免非 AArch64/非 SMP 构建告警。
Diffstat (limited to 'components')
7 files changed, 660 insertions, 123 deletions
diff --git a/components/dfs/dfs_v2/filesystems/procfs/proc_cpuinfo.c b/components/dfs/dfs_v2/filesystems/procfs/proc_cpuinfo.c index 6f49832992..ca3a8dc48a 100644 --- a/components/dfs/dfs_v2/filesystems/procfs/proc_cpuinfo.c +++ b/components/dfs/dfs_v2/filesystems/procfs/proc_cpuinfo.c @@ -18,11 +18,19 @@ #include <dfs_dentry.h> -static void *seq_start(struct dfs_seq_file *seq, off_t *index) +#if defined(__aarch64__) || defined(__AARCH64EL__) +static rt_uint64_t cpu_midr(void) { - off_t i = *index; // seq->index + rt_uint64_t value; + + __asm__ volatile("mrs %0, midr_el1" : "=r"(value)); + return value; +} +#endif - return NULL + (i == 0); +static void *seq_start(struct dfs_seq_file *seq, off_t *index) +{ + return (*index < RT_CPUS_NR) ? (void *)1 : RT_NULL; } static void seq_stop(struct dfs_seq_file *seq, void *data) @@ -31,27 +39,57 @@ static void seq_stop(struct dfs_seq_file *seq, void *data) static void *seq_next(struct dfs_seq_file *seq, void *data, off_t *index) { - /* data: The return value of the start or next*/ - off_t i = *index + 1; // seq->index - - *index = i; - - return NULL; + RT_UNUSED(seq); + RT_UNUSED(data); + *index += 1; + return (*index < RT_CPUS_NR) ? (void *)1 : RT_NULL; } static int seq_show(struct dfs_seq_file *seq, void *data) { - /* data: The return value of the start or next*/ - dfs_seq_puts(seq, "rt_weak const struct dfs_seq_ops *cpuinfo_get_seq_ops(void)\n--need your own function--\n"); +#if defined(__aarch64__) || defined(__AARCH64EL__) + rt_uint64_t midr; + rt_uint32_t implementer; + rt_uint32_t variant; + rt_uint32_t architecture; + rt_uint32_t part; + rt_uint32_t revision; +#endif + + RT_UNUSED(data); +#if defined(__aarch64__) || defined(__AARCH64EL__) + midr = cpu_midr(); + implementer = (rt_uint32_t)((midr >> 24) & 0xffU); + variant = (rt_uint32_t)((midr >> 20) & 0x0fU); + architecture = (rt_uint32_t)((midr >> 16) & 0x0fU); + part = (rt_uint32_t)((midr >> 4) & 0x0fffU); + revision = (rt_uint32_t)(midr & 0x0fU); +#endif + + dfs_seq_printf(seq, "processor\t: %lu\n", (unsigned long)seq->index); +#if defined(__aarch64__) || defined(__AARCH64EL__) + dfs_seq_puts(seq, "model name\t: ARMv8 Generic\n"); + dfs_seq_printf(seq, "CPU implementer\t: 0x%02lx\n", (unsigned long)implementer); + dfs_seq_printf(seq, "CPU architecture: %lu\n", (unsigned long)(architecture ? architecture : 8U)); + dfs_seq_printf(seq, "CPU variant\t: 0x%lx\n", (unsigned long)variant); + dfs_seq_printf(seq, "CPU part\t: 0x%03lx\n", (unsigned long)part); + dfs_seq_printf(seq, "CPU revision\t: %lu\n", (unsigned long)revision); +#elif defined(__riscv) + dfs_seq_puts(seq, "model name\t: RISC-V Generic\n"); + dfs_seq_puts(seq, "isa\t\t: rv64\n"); +#else + dfs_seq_puts(seq, "model name\t: RT-Thread Generic CPU\n"); +#endif + dfs_seq_puts(seq, "\n"); return 0; } static const struct dfs_seq_ops seq_ops = { - .start = seq_start, - .stop = seq_stop, - .next = seq_next, - .show = seq_show, + .start = seq_start, + .stop = seq_stop, + .next = seq_next, + .show = seq_show, }; rt_weak const struct dfs_seq_ops *cpuinfo_get_seq_ops(void) @@ -70,10 +108,10 @@ static int proc_close(struct dfs_file *file) } static const struct dfs_file_ops file_ops = { - .open = proc_open, - .read = dfs_seq_read, - .lseek = dfs_seq_lseek, - .close = proc_close, + .open = proc_open, + .read = dfs_seq_read, + .lseek = dfs_seq_lseek, + .close = proc_close, }; int proc_cpuinfo_init(void) diff --git a/components/dfs/dfs_v2/filesystems/procfs/proc_loadavg.c b/components/dfs/dfs_v2/filesystems/procfs/proc_loadavg.c index 6ce1bc487a..acb6ee35b5 100644 --- a/components/dfs/dfs_v2/filesystems/procfs/proc_loadavg.c +++ b/components/dfs/dfs_v2/filesystems/procfs/proc_loadavg.c @@ -17,16 +17,62 @@ #include <errno.h> #include <dfs_dentry.h> -#include <mm_page.h> +#ifdef RT_USING_SMART +#include "lwp_pid.h" +#ifdef RT_USING_MUSLLIBC +#include "lwp.h" +#endif +#endif -extern void rt_memory_info(rt_size_t *total, - rt_size_t *used, - rt_size_t *max_used); +#ifdef RT_USING_SMART +struct loadavg_count +{ + int total; + int runnable; +}; + +static int loadavg_count_pid(pid_t pid, void *arg) +{ + struct loadavg_count *count = (struct loadavg_count *)arg; + struct rt_lwp *lwp = lwp_from_pid_locked(pid); + + if (!lwp) + { + return 0; + } + count->total++; +#ifdef RT_USING_MUSLLIBC + { + rt_list_t *node; + + node = lwp->t_grp.next; + while (node != &lwp->t_grp) + { + rt_thread_t thread = rt_list_entry(node, struct rt_thread, sibling); + if (RT_SCHED_CTX(thread).stat == RT_THREAD_RUNNING) + { + count->runnable++; + break; + } + node = node->next; + } + } +#endif + return 0; +} +#endif static int single_show(struct dfs_seq_file *seq, void *data) { - dfs_seq_printf(seq, "0.13 0.16 0.17 1/1035 380436\n"); +#ifdef RT_USING_SMART + struct loadavg_count count = { 0, 0 }; + + lwp_pid_for_each(loadavg_count_pid, &count); + dfs_seq_printf(seq, "0.00 0.00 0.00 %d/%d 0\n", count.runnable, count.total); +#else + dfs_seq_puts(seq, "0.00 0.00 0.00 0/0 0\n"); +#endif return 0; } diff --git a/components/dfs/dfs_v2/filesystems/procfs/proc_meminfo.c b/components/dfs/dfs_v2/filesystems/procfs/proc_meminfo.c index b6ae56288f..b1617f8bfd 100644 --- a/components/dfs/dfs_v2/filesystems/procfs/proc_meminfo.c +++ b/components/dfs/dfs_v2/filesystems/procfs/proc_meminfo.c @@ -34,24 +34,27 @@ static int single_show(struct dfs_seq_file *seq, void *data) total_sum = total_sum + total; total_freed = total_freed + total - used; - dfs_seq_printf(seq, "%-16s%8d KB\n", "MemMaxUsed:", max_used / 1024); - dfs_seq_printf(seq, "%-16s%8d KB\n", "MemAvailable:", (total - used) / 1024); - dfs_seq_printf(seq, "%-16s%8d KB\n", "Cached:", 0); - dfs_seq_printf(seq, "%-16s%8d KB\n", "SReclaimable:", 0); + dfs_seq_printf(seq, "%-16s%8lu kB\n", "MemMaxUsed:", (unsigned long)(max_used / 1024)); + dfs_seq_printf(seq, "%-16s%8lu kB\n", "MemAvailable:", (unsigned long)((total - used) / 1024)); rt_page_get_info(&total, &freed); total_sum = total_sum + total * RT_MM_PAGE_SIZE; total_freed = total_freed + freed * RT_MM_PAGE_SIZE; - dfs_seq_printf(seq, "%-16s%8d KB\n", "MemTotal:", total_sum / 1024); - dfs_seq_printf(seq, "%-16s%8d KB\n", "MemFree:", total_freed / 1024); - dfs_seq_printf(seq, "%-16s%8d KB\n", "LowPageTotal:", total * RT_MM_PAGE_SIZE / 1024); - dfs_seq_printf(seq, "%-16s%8d KB\n", "lowPageFree:", freed * RT_MM_PAGE_SIZE/ 1024); + dfs_seq_printf(seq, "%-16s%8lu kB\n", "MemTotal:", (unsigned long)(total_sum / 1024)); + dfs_seq_printf(seq, "%-16s%8lu kB\n", "MemFree:", (unsigned long)(total_freed / 1024)); + dfs_seq_printf(seq, "%-16s%8lu kB\n", "Buffers:", 0UL); + dfs_seq_printf(seq, "%-16s%8lu kB\n", "Cached:", 0UL); + dfs_seq_printf(seq, "%-16s%8lu kB\n", "SwapCached:", 0UL); + dfs_seq_printf(seq, "%-16s%8lu kB\n", "SwapTotal:", 0UL); + dfs_seq_printf(seq, "%-16s%8lu kB\n", "SwapFree:", 0UL); + dfs_seq_printf(seq, "%-16s%8lu kB\n", "LowPageTotal:", (unsigned long)(total * RT_MM_PAGE_SIZE / 1024)); + dfs_seq_printf(seq, "%-16s%8lu kB\n", "LowPageFree:", (unsigned long)(freed * RT_MM_PAGE_SIZE / 1024)); rt_page_high_get_info(&total, &freed); - dfs_seq_printf(seq, "%-16s%8d KB\n", "HighPageTotal:", total * RT_MM_PAGE_SIZE / 1024); - dfs_seq_printf(seq, "%-16s%8d KB\n", "HighPageFree:", freed * RT_MM_PAGE_SIZE / 1024); + dfs_seq_printf(seq, "%-16s%8lu kB\n", "HighPageTotal:", (unsigned long)(total * RT_MM_PAGE_SIZE / 1024)); + dfs_seq_printf(seq, "%-16s%8lu kB\n", "HighPageFree:", (unsigned long)(freed * RT_MM_PAGE_SIZE / 1024)); return 0; } diff --git a/components/dfs/dfs_v2/filesystems/procfs/proc_mounts.c b/components/dfs/dfs_v2/filesystems/procfs/proc_mounts.c index 49a6ba99c6..1bb3b6a6bc 100644 --- a/components/dfs/dfs_v2/filesystems/procfs/proc_mounts.c +++ b/components/dfs/dfs_v2/filesystems/procfs/proc_mounts.c @@ -19,13 +19,62 @@ #include <dfs_dentry.h> #include <dfs_mnt.h> +static void mnt_escape(const char *source, char *target, rt_size_t target_size) +{ + rt_size_t offset = 0; + const char *cursor = source ? source : ""; + + if (target_size == 0) + { + return; + } + + while (*cursor != '\0' && offset + 4 < target_size) + { + if (*cursor == ' ') + { + target[offset++] = '\\'; + target[offset++] = '0'; + target[offset++] = '4'; + target[offset++] = '0'; + } + else if (*cursor == '\t') + { + target[offset++] = '\\'; + target[offset++] = '0'; + target[offset++] = '1'; + target[offset++] = '1'; + } + else if (*cursor == '\n') + { + target[offset++] = '\\'; + target[offset++] = '0'; + target[offset++] = '1'; + target[offset++] = '2'; + } + else if (*cursor == '\\') + { + target[offset++] = '\\'; + target[offset++] = '1'; + target[offset++] = '3'; + target[offset++] = '4'; + } + else + { + target[offset++] = *cursor; + } + cursor++; + } + + target[offset] = '\0'; +} const char *mnt_flag(int flag) { - /*if (flag & MNT_READONLY) + if (flag & MNT_RDONLY) { return "ro"; - }*/ + } return "rw"; } @@ -33,19 +82,23 @@ const char *mnt_flag(int flag) static struct dfs_mnt* mnt_show(struct dfs_mnt *mnt, void *parameter) { struct dfs_seq_file *seq = (struct dfs_seq_file *)parameter; + char source[DFS_PATH_MAX]; + char target[DFS_PATH_MAX]; + const char *source_name; + const char *filesystem_name; - if (mnt) + if (mnt && mnt->fs_ops && mnt->fullpath) { - if (mnt->dev_id) - { - dfs_seq_printf(seq, "%s %s %s %s 0 0\n", mnt->dev_id->parent.name, mnt->fullpath, - mnt->fs_ops->name, mnt_flag(mnt->flags)); - } - else + filesystem_name = mnt->fs_ops->name ? mnt->fs_ops->name : "unknown"; + source_name = filesystem_name; + if (mnt->dev_id && mnt->dev_id->parent.name[0] != '\0') { - dfs_seq_printf(seq, "%s %s %s %s 0 0\n", mnt->fs_ops->name, mnt->fullpath, - mnt->fs_ops->name, mnt_flag(mnt->flags)); + source_name = mnt->dev_id->parent.name; } + mnt_escape(source_name, source, sizeof(source)); + mnt_escape(mnt->fullpath, target, sizeof(target)); + dfs_seq_printf(seq, "%s %s %s %s 0 0\n", source, target, + filesystem_name, mnt_flag(mnt->flags)); } return RT_NULL; diff --git a/components/dfs/dfs_v2/filesystems/procfs/proc_pid.c b/components/dfs/dfs_v2/filesystems/procfs/proc_pid.c index a413f646c8..9212351ac4 100644 --- a/components/dfs/dfs_v2/filesystems/procfs/proc_pid.c +++ b/components/dfs/dfs_v2/filesystems/procfs/proc_pid.c @@ -26,6 +26,12 @@ #include "lwp.h" #include "lwp_pid.h" #include <lwp_user_mm.h> +#ifdef ARCH_MM_MMU +#include <stdint.h> +#include <mm_aspace.h> +#include <mm_flag.h> +#include <mmu.h> +#endif struct pid_dentry { @@ -49,6 +55,241 @@ static char stat_transform(int __stat) } } +#ifdef ARCH_MM_MMU +#define PROC_MAP_MAX 256 + +struct proc_map_entry +{ + uintptr_t start; + uintptr_t end; + uintptr_t offset; + rt_size_t resident_pages; + rt_bool_t writable; + rt_bool_t shared; + rt_bool_t executable; + char name[DFS_PATH_MAX]; +}; + +struct proc_map_context +{ + struct rt_lwp *lwp; + struct proc_map_entry *entries; + rt_size_t count; + rt_bool_t smaps; +}; + +static void proc_map_permissions(rt_varea_t varea, struct proc_map_entry *entry) +{ + entry->writable = rt_hw_mmu_attr_test_perm( + varea->attr, RT_HW_MMU_PROT_WRITE | RT_HW_MMU_PROT_USER); + entry->shared = (varea->flag & MMF_MAP_SHARED) != 0; + entry->executable = (varea->flag & MMF_TEXT) != 0; +} + +static void proc_map_name(rt_varea_t varea, struct proc_map_entry *entry) +{ + const char *name = RT_NULL; + + if (varea->mem_obj && varea->mem_obj->get_name) + { + name = varea->mem_obj->get_name(varea); + } + + if (!name || !name[0] || !rt_strcmp(name, "anonymous") || + !rt_strcmp(name, "reference") || !rt_strcmp(name, "null")) + { + name = "[anon]"; + } + rt_strncpy(entry->name, name, sizeof(entry->name) - 1); + entry->name[sizeof(entry->name) - 1] = '\0'; +} + +static int proc_map_collect(rt_varea_t varea, void *arg) +{ + struct proc_map_context *context = (struct proc_map_context *)arg; + struct proc_map_entry *entry; + uintptr_t address; + uintptr_t end; + + if (context->count >= PROC_MAP_MAX || !varea || varea->size == 0) + { + return 0; + } + + entry = &context->entries[context->count++]; + entry->start = (uintptr_t)varea->start; + entry->end = entry->start + varea->size; + entry->offset = (uintptr_t)varea->offset * ARCH_PAGE_SIZE; + entry->resident_pages = 0; + proc_map_permissions(varea, entry); + proc_map_name(varea, entry); + + address = entry->start; + end = entry->end; + while (address < end) + { + if (rt_hw_mmu_v2p(varea->aspace, (void *)address) != ARCH_MAP_FAILED) + { + entry->resident_pages++; + } + address += ARCH_PAGE_SIZE; + } + + return 0; +} + +static void proc_map_context_free(struct proc_map_context *context) +{ + if (context) + { + if (context->lwp) + { + lwp_from_pid_release_lock(context->lwp); + } + if (context->entries) + { + rt_free(context->entries); + } + rt_free(context); + } +} + +static void *proc_maps_start(struct dfs_seq_file *seq, off_t *index) +{ + struct proc_map_context *context = (struct proc_map_context *)seq->data; + + return context && *index < (off_t)context->count ? &context->entries[*index] : RT_NULL; +} + +static void *proc_maps_next(struct dfs_seq_file *seq, void *data, off_t *index) +{ + struct proc_map_context *context = (struct proc_map_context *)seq->data; + + RT_UNUSED(data); + *index += 1; + return context && *index < (off_t)context->count ? &context->entries[*index] : RT_NULL; +} + +static void proc_maps_stop(struct dfs_seq_file *seq, void *data) +{ + RT_UNUSED(seq); + RT_UNUSED(data); +} + +static int proc_maps_show(struct dfs_seq_file *seq, void *data) +{ + struct proc_map_entry *entry = (struct proc_map_entry *)data; + char permissions[5]; + + permissions[0] = 'r'; + permissions[1] = entry->writable ? 'w' : '-'; + permissions[2] = entry->executable ? 'x' : '-'; + permissions[3] = entry->shared ? 's' : 'p'; + permissions[4] = '\0'; + + dfs_seq_printf(seq, "%0*lx-%0*lx %s %0*lx 00:00 0", + (int)(sizeof(uintptr_t) * 2), (unsigned long)entry->start, + (int)(sizeof(uintptr_t) * 2), (unsigned long)entry->end, + permissions, (int)(sizeof(uintptr_t) * 2), + (unsigned long)entry->offset); + if (entry->name[0]) + { + dfs_seq_printf(seq, " %s", entry->name); + } + dfs_seq_puts(seq, "\n"); + + if (((struct proc_map_context *)seq->data)->smaps) + { + rt_size_t resident_kb = entry->resident_pages * (ARCH_PAGE_SIZE / 1024); + rt_size_t private_dirty = entry->writable && !entry->shared ? resident_kb : 0; + + dfs_seq_printf(seq, "Size: %lu kB\n", (unsigned long)((entry->end - entry->start) / 1024)); + dfs_seq_printf(seq, "Rss: %lu kB\n", (unsigned long)resident_kb); + dfs_seq_printf(seq, "Pss: %lu kB\n", (unsigned long)resident_kb); + dfs_seq_puts(seq, "Shared_Clean: 0 kB\n"); + dfs_seq_puts(seq, "Shared_Dirty: 0 kB\n"); + dfs_seq_puts(seq, "Private_Clean: 0 kB\n"); + dfs_seq_printf(seq, "Private_Dirty: %lu kB\n", (unsigned long)private_dirty); + dfs_seq_printf(seq, "Anonymous: %lu kB\n", entry->name[0] == '[' ? (unsigned long)resident_kb : 0UL); + dfs_seq_puts(seq, "Swap: 0 kB\n\n"); + } + + return 0; +} + +static const struct dfs_seq_ops proc_maps_seq_ops = { + .start = proc_maps_start, + .stop = proc_maps_stop, + .next = proc_maps_next, + .show = proc_maps_show, +}; + +static int proc_maps_open(struct dfs_file *file) +{ + struct proc_dentry *dentry = (struct proc_dentry *)file->vnode->data; + struct proc_map_context *context; + struct dfs_seq_file *seq; + rt_varea_t varea; + int ret; + + context = rt_calloc(1, sizeof(*context)); + if (!context) + { + return -RT_ENOMEM; + } + context->lwp = lwp_from_pid_and_lock(dentry->pid); + if (!context->lwp || !context->lwp->aspace) + { + proc_map_context_free(context); + return -RT_ENOENT; + } + context->smaps = !rt_strcmp(dentry->name, "smaps"); + context->entries = rt_calloc(PROC_MAP_MAX, sizeof(*context->entries)); + if (!context->entries) + { + proc_map_context_free(context); + return -RT_ENOMEM; + } + + RD_LOCK(context->lwp->aspace); + varea = ASPACE_VAREA_FIRST(context->lwp->aspace); + while (varea) + { + proc_map_collect(varea, context); + varea = ASPACE_VAREA_NEXT(varea); + } + RD_UNLOCK(context->lwp->aspace); + + ret = dfs_seq_open(file, &proc_maps_seq_ops); + if (ret != RT_EOK) + { + proc_map_context_free(context); + return ret; + } + seq = (struct dfs_seq_file *)file->data; + seq->data = context; + return RT_EOK; +} + +static int proc_maps_close(struct dfs_file *file) +{ + struct dfs_seq_file *seq = (struct dfs_seq_file *)file->data; + struct proc_map_context *context = seq ? (struct proc_map_context *)seq->data : RT_NULL; + int ret = dfs_seq_release(file); + + proc_map_context_free(context); + file->data = RT_NULL; + return ret; +} + +static const struct dfs_file_ops proc_maps_fops = { + .open = proc_maps_open, + .read = dfs_seq_read, + .lseek = dfs_seq_lseek, + .close = proc_maps_close, +}; +#endif /* ARCH_MM_MMU */ + static int stat_single_show(struct dfs_seq_file *seq, void *data) { struct proc_dentry *dentry = (struct proc_dentry *)seq->file->vnode->data; @@ -60,56 +301,53 @@ static int stat_single_show(struct dfs_seq_file *seq, void *data) int lwp_oncpu = RT_CPUS_NR; int lwp_oncpu_ok = 0; struct rt_lwp *lwp = RT_NULL; - char** argv = RT_NULL; + char **argv = RT_NULL; char *filename = RT_NULL; char *dot = RT_NULL; - lwp_pid_lock_take(); - - lwp = lwp_from_pid_locked(dentry->pid); - argv = lwp_get_command_line_args(lwp); + lwp = lwp_from_pid_and_lock(dentry->pid); + argv = lwp ? lwp_get_command_line_args(lwp) : RT_NULL; if (lwp) { - dfs_seq_printf(seq,"%d ",dentry->pid); + dfs_seq_printf(seq, "%d ", dentry->pid); if (argv) { - filename = strrchr(argv[0], '/'); - dot = strchr(argv[0], '.'); - - if (filename != NULL) + if (argv[0]) { - filename++; - } - else - { - filename = argv[0]; - } + filename = strrchr(argv[0], '/'); - if (dot != NULL) - { - *dot = '\0'; - } + if (filename != NULL) + { + filename++; + } + else + { + filename = argv[0]; + } - if (filename != NULL) - { - dfs_seq_printf(seq,"(%s) ", filename); + dot = strchr(filename, '.'); + if (dot != NULL) + { + *dot = '\0'; + } + + dfs_seq_printf(seq, "(%s) ", filename); } else { - dfs_seq_printf(seq,"(%s) ", argv[0]); + dfs_seq_printf(seq, "(%s) ", ""); } - lwp_free_command_line_args(argv); } else { - dfs_seq_printf(seq,"(%s) ", ""); + dfs_seq_printf(seq, "(%s) ", ""); } if (lwp->terminated) { - dfs_seq_printf(seq,"%c ",'Z'); + dfs_seq_printf(seq, "%c ", 'Z'); } else { @@ -120,11 +358,11 @@ static int stat_single_show(struct dfs_seq_file *seq, void *data) user_time_lwp = user_time_lwp + thread->user_time; system_time_lwp = system_time_lwp + thread->system_time; - #if RT_CPUS_NR > 1 - #define ONCPU(thread) RT_SCHED_CTX(thread).oncpu - #else - #define ONCPU(thread) 0 - #endif +#if RT_CPUS_NR > 1 +#define ONCPU(thread) RT_SCHED_CTX(thread).oncpu +#else +#define ONCPU(thread) 0 +#endif if (lwp_oncpu_ok == 0) { lwp_oncpu = ONCPU(thread); @@ -140,34 +378,37 @@ static int stat_single_show(struct dfs_seq_file *seq, void *data) if (mask == 1) { - dfs_seq_printf(seq,"%c ",'R'); + dfs_seq_printf(seq, "%c ", 'R'); } else { - dfs_seq_printf(seq,"%c ",'S'); + dfs_seq_printf(seq, "%c ", 'S'); } } - lwp_pid_lock_release(); - if (lwp->parent != NULL) - dfs_seq_printf(seq,"%d ",lwp->parent->pid); + { + dfs_seq_printf(seq, "%d ", lwp->parent->pid); + } else - dfs_seq_printf(seq,"0 "); + { + dfs_seq_printf(seq, "0 "); + } dfs_seq_printf(seq, "1 1 0 -1 4194560 48245 133976064 732 425574 "); - dfs_seq_printf(seq,"%llu ",user_time_lwp);//utime - dfs_seq_printf(seq,"%llu ",system_time_lwp);//stime + dfs_seq_printf(seq, "%llu ", user_time_lwp);//utime + dfs_seq_printf(seq, "%llu ", system_time_lwp);//stime dfs_seq_printf(seq, "1204291 518742 20 0 1 0 50 "); - dfs_seq_printf(seq, "%d ",rt_aspace_count_vsz(lwp->aspace));//VSZ +#ifdef ARCH_MM_MMU + dfs_seq_printf(seq, "%lu ", lwp->aspace ? (unsigned long)rt_aspace_count_vsz(lwp->aspace) : 0UL);//VSZ +#else + dfs_seq_puts(seq, "0 "); +#endif dfs_seq_printf(seq, "1422 18446744073709551615 "); dfs_seq_printf(seq, "1 1 0 0 0 0 671173123 4096 1260 0 0 0 17 "); dfs_seq_printf(seq, "%d ", lwp_oncpu);//CPU dfs_seq_printf(seq, "0 0 0 0 0 0 0 0 0 0 0 0 0"); - dfs_seq_printf(seq,"\n"); - } - else - { - lwp_pid_lock_release(); + dfs_seq_printf(seq, "\n"); + lwp_from_pid_release_lock(lwp); } return 0; @@ -177,12 +418,10 @@ static int cmdline_single_show(struct dfs_seq_file *seq, void *data) { struct proc_dentry *dentry = (struct proc_dentry *)seq->file->vnode->data; struct rt_lwp *lwp; - char** argv; + char **argv; - lwp_pid_lock_take(); - lwp = lwp_from_pid_locked(dentry->pid); - argv = lwp_get_command_line_args(lwp); - lwp_pid_lock_release(); + lwp = lwp_from_pid_and_lock(dentry->pid); + argv = lwp ? lwp_get_command_line_args(lwp) : RT_NULL; if (argv) { @@ -198,7 +437,80 @@ static int cmdline_single_show(struct dfs_seq_file *seq, void *data) { dfs_seq_puts(seq, "error\n"); } + lwp_from_pid_release_lock(lwp); + + return 0; +} + +static int proc_pid_status_show(struct dfs_seq_file *seq, void *data) +{ + struct proc_dentry *dentry = (struct proc_dentry *)seq->file->vnode->data; + struct rt_lwp *lwp = lwp_from_pid_and_lock(dentry->pid); + rt_size_t vm_size = 0; + rt_size_t thread_count = 0; + rt_list_t *node; + char state; + + RT_UNUSED(data); + if (!lwp) + { + return -RT_ENOENT; + } +#ifdef ARCH_MM_MMU + if (lwp->aspace) + { + vm_size = rt_aspace_count_vsz(lwp->aspace); + } +#endif + node = lwp->t_grp.next; + while (node != &lwp->t_grp) + { + thread_count++; + node = node->next; + } + state = lwp->terminated ? 'Z' : 'S'; + dfs_seq_printf(seq, "Name:\t%s\n", lwp->cmd); + dfs_seq_printf(seq, "State:\t%c (sleeping)\n", state); + dfs_seq_printf(seq, "Pid:\t%d\n", lwp->pid); + dfs_seq_printf(seq, "PPid:\t%d\n", lwp->parent ? lwp->parent->pid : 0); + dfs_seq_puts(seq, "Uid:\t0\t0\t0\t0\nGid:\t0\t0\t0\t0\n"); + dfs_seq_printf(seq, "Threads:\t%lu\n", (unsigned long)thread_count); + dfs_seq_printf(seq, "VmSize:\t%lu kB\n", (unsigned long)(vm_size / 1024)); + dfs_seq_printf(seq, "VmRSS:\t%lu kB\n", (unsigned long)(vm_size / 1024)); + dfs_seq_puts(seq, "VmData:\t0 kB\nVmStk:\t0 kB\nVmExe:\t0 kB\nVmLib:\t0 kB\n"); + lwp_from_pid_release_lock(lwp); + return 0; +} + +static int proc_pid_statm_show(struct dfs_seq_file *seq, void *data) +{ + struct proc_dentry *dentry = (struct proc_dentry *)seq->file->vnode->data; + struct rt_lwp *lwp = lwp_from_pid_and_lock(dentry->pid); + rt_size_t size_pages = 0; + rt_size_t text_pages = 0; + rt_size_t data_pages = 0; + + RT_UNUSED(data); + if (!lwp) + { + return -RT_ENOENT; + } + +#ifdef ARCH_MM_MMU + if (lwp->aspace) + { + size_pages = (rt_aspace_count_vsz(lwp->aspace) + ARCH_PAGE_SIZE - 1) / ARCH_PAGE_SIZE; + } +#endif +#ifdef ARCH_MM_MMU + text_pages = (lwp->text_size + ARCH_PAGE_SIZE - 1) / ARCH_PAGE_SIZE; + data_pages = (lwp->data_size + ARCH_PAGE_SIZE - 1) / ARCH_PAGE_SIZE; +#endif + dfs_seq_printf(seq, "%lu %lu 0 %lu 0 %lu 0\n", + (unsigned long)size_pages, (unsigned long)size_pages, + (unsigned long)text_pages, (unsigned long)data_pages); + lwp_from_pid_release_lock(lwp); return 0; } @@ -240,13 +552,21 @@ struct proc_dentry *proc_pid_fd_lookup(struct proc_dentry *parent, const char *n { //todo add vnode->data if (file->vnode->type == FT_SOCKET) + { dentry->data = (void *)rt_strdup("socket"); + } else if (file->vnode->type == FT_USER) + { dentry->data = (void *)rt_strdup("user"); + } else if (file->vnode->type == FT_DEVICE) + { dentry->data = (void *)rt_strdup("device"); + } else + { dentry->data = (void *)rt_strdup("unknown"); + } } dentry->pid = parent->pid; @@ -337,8 +657,9 @@ int proc_pid_exe_readlink(struct proc_dentry *dentry, char *buf, int len) { struct rt_lwp *lwp; - lwp = lwp_self(); - len = rt_snprintf(buf, len, "%s", lwp ? lwp->exe_file : "null"); + lwp = lwp_from_pid_and_lock(dentry->pid); + len = rt_snprintf(buf, len, "%s", lwp && lwp->exe_file ? lwp->exe_file : "null"); + lwp_from_pid_release_lock(lwp); return len; } @@ -351,8 +672,9 @@ int proc_pid_cwd_readlink(struct proc_dentry *dentry, char *buf, int len) { struct rt_lwp *lwp; - lwp = lwp_self(); + lwp = lwp_from_pid_and_lock(dentry->pid); len = rt_snprintf(buf, len, "%s", lwp ? lwp->working_directory : "null"); + lwp_from_pid_release_lock(lwp); return len; } @@ -362,17 +684,23 @@ static const struct proc_ops proc_pid_cwd_ops = { }; static struct pid_dentry pid_dentry_base[] = { - {"cmdline", S_IFREG | S_IRUSR | S_IRGRP | S_IROTH, 0, 0, 0, cmdline_single_show, 0}, - {"cwd", S_IFLNK | S_IRUSR | S_IXUSR, 0, &proc_pid_cwd_ops, 0, 0}, - {"exe", S_IFLNK | S_IRUSR | S_IXUSR, 0, &proc_pid_exe_ops, 0, 0}, - {"fd", S_IFDIR | S_IRUSR | S_IXUSR, &proc_pid_fd_fops, &proc_pid_fd_ops, 0, 0, 0}, - {"mounts", S_IFLNK | S_IRUSR | S_IXUSR, 0, 0, 0, 0, "/proc/mounts"}, - {"stat", S_IFREG | S_IRUSR | S_IRGRP | S_IROTH, 0, 0, 0, stat_single_show, 0}, + { "cmdline", S_IFREG | S_IRUSR | S_IRGRP | S_IROTH, 0, 0, 0, cmdline_single_show, 0 }, + { "status", S_IFREG | S_IRUSR | S_IRGRP | S_IROTH, 0, 0, 0, proc_pid_status_show, 0 }, + { "statm", S_IFREG | S_IRUSR | S_IRGRP | S_IROTH, 0, 0, 0, proc_pid_statm_show, 0 }, + { "cwd", S_IFLNK | S_IRUSR | S_IXUSR, 0, &proc_pid_cwd_ops, 0, 0 }, + { "exe", S_IFLNK | S_IRUSR | S_IXUSR, 0, &proc_pid_exe_ops, 0, 0 }, + { "fd", S_IFDIR | S_IRUSR | S_IXUSR, &proc_pid_fd_fops, &proc_pid_fd_ops, 0, 0, 0 }, + { "mounts", S_IFLNK | S_IRUSR | S_IXUSR, 0, 0, 0, 0, "/proc/mounts" }, + { "stat", S_IFREG | S_IRUSR | S_IRGRP | S_IROTH, 0, 0, 0, stat_single_show, 0 }, +#ifdef ARCH_MM_MMU + { "maps", S_IFREG | S_IRUSR | S_IRGRP | S_IROTH, &proc_maps_fops, 0, 0, 0, 0 }, + { "smaps", S_IFREG | S_IRUSR | S_IRGRP | S_IROTH, &proc_maps_fops, 0, 0, 0, 0 }, +#endif }; int proc_pid(int pid) { - char pid_str[64] = {0}; + char pid_str[64] = { 0 }; struct proc_dentry *dentry; rt_snprintf(pid_str, 64, "%d", pid); diff --git a/components/dfs/dfs_v2/filesystems/procfs/proc_stat.c b/components/dfs/dfs_v2/filesystems/procfs/proc_stat.c index aeba99de51..c24adb291e 100644 --- a/components/dfs/dfs_v2/filesystems/procfs/proc_stat.c +++ b/components/dfs/dfs_v2/filesystems/procfs/proc_stat.c @@ -18,6 +18,49 @@ #include <dfs_dentry.h> +#ifdef RT_USING_SMART +#include "lwp_pid.h" +#ifdef RT_USING_MUSLLIBC +#include "lwp.h" +#endif +#endif + +#ifdef RT_USING_SMART +struct stat_process_count +{ + int total; + int running; +}; + +static int stat_process_count(pid_t pid, void *arg) +{ + struct stat_process_count *count = (struct stat_process_count *)arg; + struct rt_lwp *lwp = lwp_from_pid_locked(pid); + + if (!lwp) + { + return 0; + } + count->total++; +#ifdef RT_USING_MUSLLIBC + { + rt_list_t *node = lwp->t_grp.next; + + while (node != &lwp->t_grp) + { + rt_thread_t thread = rt_list_entry(node, struct rt_thread, sibling); + if (RT_SCHED_CTX(thread).stat == RT_THREAD_RUNNING) + { + count->running++; + break; + } + node = node->next; + } + } +#endif + return 0; +} +#endif static void *seq_start(struct dfs_seq_file *seq, off_t *index) { @@ -50,7 +93,7 @@ static int seq_show(struct dfs_seq_file *seq, void *data) for (i = 0; i < RT_CPUS_NR; i++) { - pcpu = rt_cpu_index(i); + pcpu = rt_cpu_index(i); user_total = user_total + pcpu->cpu_stat.user; system_total = system_total + pcpu->cpu_stat.system; idle_total = idle_total + pcpu->cpu_stat.idle; @@ -59,27 +102,36 @@ static int seq_show(struct dfs_seq_file *seq, void *data) for (i = 0; i < RT_CPUS_NR; i++) { - pcpu = rt_cpu_index(i); - dfs_seq_printf(seq, "cpu%d ",i); - dfs_seq_printf(seq, "%llu ",pcpu->cpu_stat.user);//user + pcpu = rt_cpu_index(i); + dfs_seq_printf(seq, "cpu%d ", i); + dfs_seq_printf(seq, "%llu ", pcpu->cpu_stat.user);//user dfs_seq_printf(seq, "0 ");//nice - dfs_seq_printf(seq, "%llu ",pcpu->cpu_stat.system);//system - dfs_seq_printf(seq, "%llu ",pcpu->cpu_stat.idle);//idle + dfs_seq_printf(seq, "%llu ", pcpu->cpu_stat.system);//system + dfs_seq_printf(seq, "%llu ", pcpu->cpu_stat.idle);//idle dfs_seq_printf(seq, "0 ");//iowait dfs_seq_printf(seq, "0 ");//irq dfs_seq_printf(seq, "0 ");//softirq dfs_seq_printf(seq, "0 0 0\n");//steal,guest,guest_nice + } +#ifdef RT_USING_SMART + { + struct stat_process_count process_count = { 0, 0 }; + lwp_pid_for_each(stat_process_count, &process_count); + dfs_seq_printf(seq, "processes %d\n", process_count.total); + dfs_seq_printf(seq, "procs_running %d\n", process_count.running); + dfs_seq_puts(seq, "procs_blocked 0\n"); } +#endif return 0; } static const struct dfs_seq_ops seq_ops = { - .start = seq_start, - .stop = seq_stop, - .next = seq_next, - .show = seq_show, + .start = seq_start, + .stop = seq_stop, + .next = seq_next, + .show = seq_show, }; rt_weak const struct dfs_seq_ops *stat_get_seq_ops(void) @@ -98,10 +150,10 @@ static int proc_close(struct dfs_file *file) } static const struct dfs_file_ops file_ops = { - .open = proc_open, - .read = dfs_seq_read, - .lseek = dfs_seq_lseek, - .close = proc_close, + .open = proc_open, + .read = dfs_seq_read, + .lseek = dfs_seq_lseek, + .close = proc_close, }; int proc_stat_init(void) diff --git a/components/dfs/dfs_v2/filesystems/procfs/proc_uptime.c b/components/dfs/dfs_v2/filesystems/procfs/proc_uptime.c index f16ab72b66..5da9e9952d 100644 --- a/components/dfs/dfs_v2/filesystems/procfs/proc_uptime.c +++ b/components/dfs/dfs_v2/filesystems/procfs/proc_uptime.c @@ -21,9 +21,26 @@ static int single_show(struct dfs_seq_file *seq, void *data) { - dfs_seq_printf(seq, "%lu.%02lu %lu.%02lu\n", - (unsigned long)rt_tick_get_millisecond() / 1000, (unsigned long)(rt_tick_get_millisecond() % 1000) / 100, - (unsigned long)rt_tick_get_millisecond() / 1000, (unsigned long)(rt_tick_get_millisecond() % 1000) / 100); + rt_tick_t ticks = rt_tick_get(); + rt_uint64_t uptime_ms; + rt_uint64_t idle_ticks = 0; +#ifdef RT_USING_SMP + int index; +#endif + + uptime_ms = ((rt_uint64_t)ticks * 1000U) / RT_TICK_PER_SECOND; +#ifdef RT_USING_SMP + for (index = 0; index < RT_CPUS_NR; index++) + { + idle_ticks += rt_cpu_index(index)->cpu_stat.idle; + } +#else + idle_ticks = rt_cpu_index(0)->cpu_stat.idle; +#endif + dfs_seq_printf(seq, "%llu.%02llu %llu.%02llu\n", + uptime_ms / 1000U, (uptime_ms % 1000U) / 10U, + ((rt_uint64_t)idle_ticks * 1000U) / RT_TICK_PER_SECOND / 1000U, + (((rt_uint64_t)idle_ticks * 1000U) / RT_TICK_PER_SECOND % 1000U) / 10U); return 0; } |
