diff --git a/.vscode/launch.json b/.vscode/launch.json index 6ab8b0076..8ae29d750 100755 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -71,8 +71,8 @@ // "miDebuggerPath": "/home/zhangzheng/gcc-arm-10.3-2021.07-aarch64-aarch64-none-elf/bin/aarch64-none-elf-gdb", // "miDebuggerPath": "/home/mkrtos-smart/toolchains/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf/bin/aarch64-none-elf-gdb", // "miDebuggerPath": "/home/toolchains/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf/bin/aarch64-none-elf-gdb", - "miDebuggerPath": "/Users/zhangzheng/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-gdb", - // "miDebuggerPath": "/home/zhangzheng/toolchain/gcc-arm-10.3-2021.07-x86_64-arm-none-eabi/bin/arm-none-eabi-gdb", + // "miDebuggerPath": "/Users/zhangzheng/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-gdb", + "miDebuggerPath": "/home/zhangzheng/toolchain/gcc-arm-10.3-2021.07-x86_64-arm-none-eabi/bin/arm-none-eabi-gdb", "miDebuggerServerAddress": "127.0.0.1:33333", "MIMode": "gdb", "setupCommands": [ diff --git a/.vscode/settings.json b/.vscode/settings.json index d9db80a45..c624fa9fd 100755 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -223,7 +223,8 @@ "stdarg.h": "c", "ipcstat.h": "c", "fs_cli.h": "c", - "fs_backend.h": "c" + "fs_backend.h": "c", + "ns_types.h": "c" }, "cortex-debug.showRTOS": false, "cortex-debug.variableUseNaturalFormat": true, diff --git a/mkrtos_knl/knl/ipc.c b/mkrtos_knl/knl/ipc.c index b0ca86a9b..8c727e6ac 100755 --- a/mkrtos_knl/knl/ipc.c +++ b/mkrtos_knl/knl/ipc.c @@ -146,11 +146,11 @@ static void ipc_syscall(kobject_t *kobj, syscall_prot_t sys_p, msg_tag_t in_tag, case IPC_DO: { //!< 如果是ipc协议,则当成一个ipc处理 - if (ipc->svr_tk == cur_task) - { - tag = msg_tag_init4(0, 0, 0, -ECANCELED); - break; - } + // if (ipc->svr_tk == cur_task) + // { + // tag = msg_tag_init4(0, 0, 0, -ECANCELED); + // break; + // } again: if (ipc->svr_tk == NULL) { diff --git a/mkrtos_knl/knl/task.c b/mkrtos_knl/knl/task.c index 5a0ba56a5..37aa6d8b4 100755 --- a/mkrtos_knl/knl/task.c +++ b/mkrtos_knl/knl/task.c @@ -41,6 +41,7 @@ enum task_op_code TASK_GET_PID, //!< 获取task的pid TASK_COPY_DATA, //!< 拷贝数据到task的数据区域 TASK_SET_OBJ_NAME, //!< 设置对象的名字 + TASK_GET_OBJ_NAME, //!< 获取对象的名字 TASK_COPY_DATA_TO, //!< 从当前task拷贝数据到目的task TASK_SET_COM_POINT, //!< 通信点 TASK_COM_UNLOCK, //!< 任务通信解锁 @@ -232,6 +233,29 @@ static void task_syscall_func(kobject_t *kobj, syscall_prot_t sys_p, msg_tag_t i switch (sys_p.op) { + case TASK_GET_OBJ_NAME: + { + mword_t status = spinlock_lock(&tag_task->kobj.lock); + if (status < 0) + { + tag = msg_tag_init4(0, 0, 0, -EINVAL); + break; + } + kobject_t *source_kobj = obj_space_lookup_kobj(&cur_task->obj_space, f->regs[0]); + + if (!source_kobj) + { + spinlock_set(&tag_task->kobj.lock, status); + tag = msg_tag_init4(0, 0, 0, -EINVAL); + break; + } + char *kobj_name = kobject_get_name(source_kobj); + + memcpy((char *)(&f->regs[1]), kobj_name, KOBJ_NAME_SIZE); + spinlock_set(&tag_task->kobj.lock, status); + tag = msg_tag_init4(0, 0, 0, 1); + } + break; case TASK_SET_OBJ_NAME: { mword_t status = spinlock_lock(&tag_task->kobj.lock); diff --git a/mkrtos_user/lib/sys/inc/u_task.h b/mkrtos_user/lib/sys/inc/u_task.h index 105ad8943..b10ff6f0d 100644 --- a/mkrtos_user/lib/sys/inc/u_task.h +++ b/mkrtos_user/lib/sys/inc/u_task.h @@ -18,6 +18,7 @@ typedef struct umword_t (*map_buf)[CONFIG_THREAD_MAP_BUF_LEN]; } fast_ipc_info_t; +msg_tag_t u_task_get_obj_name(obj_handler_t dst_task, obj_handler_t obj, char name[8/*FIXME:使用宏*/]); msg_tag_t u_task_set_obj_name(obj_handler_t dst_task, obj_handler_t obj, const char *name); msg_tag_t u_task_set_pid(obj_handler_t dst_task, umword_t pid); msg_tag_t u_task_get_pid(obj_handler_t dst_task, umword_t *data); diff --git a/mkrtos_user/lib/sys/src/u_task.c b/mkrtos_user/lib/sys/src/u_task.c index d78851532..7ec3bd87b 100644 --- a/mkrtos_user/lib/sys/src/u_task.c +++ b/mkrtos_user/lib/sys/src/u_task.c @@ -14,6 +14,7 @@ enum task_op_code TASK_GET_PID, TASK_COPY_DATA, TASK_SET_OBJ_NAME, + TASK_GET_OBJ_NAME, TASK_COPY_DATA_TO, //!< 从当前task拷贝数据到目的task TASK_SET_COM_POINT, TASK_COM_UNLOCK, @@ -41,6 +42,33 @@ msg_tag_t u_task_set_obj_name(obj_handler_t dst_task, obj_handler_t obj, const c return tag; } MK_SYSCALL +msg_tag_t u_task_get_obj_name(obj_handler_t dst_task, obj_handler_t obj, char name[8/*FIXME:使用宏*/]) +{ + register volatile umword_t r0 asm(ARCH_REG_0); + register volatile umword_t r1 asm(ARCH_REG_1); + register volatile umword_t r2 asm(ARCH_REG_2); + + mk_syscall(syscall_prot_create(TASK_GET_OBJ_NAME, TASK_PROT, dst_task).raw, + obj, + 0, + 0, + 0, + 0, + 0); + asm __volatile__("" + : + : + : ARCH_REG_0, ARCH_REG_1, ARCH_REG_2); + if (name) + { + uint32_t *name_word = (uint32_t *)name; + + *name_word++ = r1; + *name_word = r2; + } + return msg_tag_init(r0); +} +MK_SYSCALL msg_tag_t u_task_set_pid(obj_handler_t dst_task, umword_t pid) { register volatile umword_t r0 asm(ARCH_REG_0); diff --git a/mkrtos_user/lib/sys_svr/src/ns_cli.c b/mkrtos_user/lib/sys_svr/src/ns_cli.c index 229dfd6fb..31cd573e6 100644 --- a/mkrtos_user/lib/sys_svr/src/ns_cli.c +++ b/mkrtos_user/lib/sys_svr/src/ns_cli.c @@ -198,9 +198,13 @@ next: #endif int s_inx = msg_tag_get_val(tag); - if (s_inx == strlen(path)) + if (path[s_inx] != '/' && path[s_inx - 1] == '/') { - if (reg_hd(path, newfd, msg_tag_get_val(tag)) == FALSE) + s_inx--; + } + if (msg_tag_get_val(tag)== strlen(path)) + { + if (reg_hd(path, newfd, s_inx) == FALSE) { printf("The client service cache is full.\n"); #if 0 @@ -210,7 +214,7 @@ next: } } *svr_hd = newfd; - return msg_tag_get_val(tag); + return s_inx; } int ns_query_svr(const char *path, obj_handler_t *svr_hd) { diff --git a/mkrtos_user/lib/sys_util/CMakeLists.txt b/mkrtos_user/lib/sys_util/CMakeLists.txt index 59f7e67e4..39c067283 100644 --- a/mkrtos_user/lib/sys_util/CMakeLists.txt +++ b/mkrtos_user/lib/sys_util/CMakeLists.txt @@ -22,6 +22,7 @@ target_include_directories( ${CMAKE_SOURCE_DIR}/mkrtos_user/lib/cpio ${CMAKE_SOURCE_DIR}/mkrtos_user/lib/util/inc ${CMAKE_SOURCE_DIR}/mkrtos_user/lib/sys_svr/inc + ) target_link_libraries( sys_util diff --git a/mkrtos_user/lib/sys_util/src/u_sig.c b/mkrtos_user/lib/sys_util/src/u_sig.c index fe2de9e92..8d4c634e1 100644 --- a/mkrtos_user/lib/sys_util/src/u_sig.c +++ b/mkrtos_user/lib/sys_util/src/u_sig.c @@ -123,6 +123,7 @@ void sig_init(void) tag = u_facotry_create_sema(FACTORY_PROT, vpage_create_raw3(KOBJ_ALL_RIGHTS, 0, sema_wait_hd), 0, 1); assert(msg_tag_get_val(tag) >= 0); +#if 0 char proc_path[20]; umword_t pid; @@ -130,5 +131,6 @@ void sig_init(void) snprintf(proc_path, sizeof(proc_path), "/proc/%d", pid); assert(ns_register(proc_path, sig_ipc, 0) >= 0 && "task proc init failed.\n"); +#endif } #endif \ No newline at end of file diff --git a/mkrtos_user/server/fs/CMakeLists.txt b/mkrtos_user/server/fs/CMakeLists.txt index 4ae9078dc..cccdff34d 100644 --- a/mkrtos_user/server/fs/CMakeLists.txt +++ b/mkrtos_user/server/fs/CMakeLists.txt @@ -4,5 +4,5 @@ cmake_minimum_required(VERSION 3.13) # add_subdirectory(cpiofs) add_subdirectory(fatfs) add_subdirectory(appfs) -# add_subdirectory(procfs) +add_subdirectory(procfs) # add_subdirectory(lxext4) diff --git a/mkrtos_user/server/fs/procfs/CMakeLists.txt b/mkrtos_user/server/fs/procfs/CMakeLists.txt index ed43da17e..aba24f30c 100644 --- a/mkrtos_user/server/fs/procfs/CMakeLists.txt +++ b/mkrtos_user/server/fs/procfs/CMakeLists.txt @@ -1,5 +1,31 @@ cmake_minimum_required(VERSION 3.13) +file(GLOB proc_src src/proc.c src/procfs.c src/procfs_rpc.c src/procfs_impl.c) +add_library( + proc + STATIC + ${proc_src} +) +target_include_directories( + proc + PUBLIC + ${CMAKE_SOURCE_DIR}/mkrtos_user/server/fs/procfs/inc + ${CMAKE_SOURCE_DIR}/mkrtos_user/lib/sys/inc + ${CMAKE_SOURCE_DIR}/mkrtos_user/lib/sys/inc/${ARCH_NAME} +) +target_link_libraries( + proc + PUBLIC + -Bstatic + ${LIBC_NAME} + ${START_LIB} + sys + sys_util + sys_svr + fd + ${GCC_LIB_PATH}/libgcc.a +) + file( GLOB deps src/*.c diff --git a/mkrtos_user/server/fs/procfs/armv7_8m/link.lds b/mkrtos_user/server/fs/procfs/armv7_8m/link.lds new file mode 100644 index 000000000..f297e7ddb --- /dev/null +++ b/mkrtos_user/server/fs/procfs/armv7_8m/link.lds @@ -0,0 +1,124 @@ +ENTRY(_start_) + +SECTIONS +{ + .text : { + . = ALIGN(4); + __text_start__ = .; + KEEP(*(.first)) + *(.text) + *(.text.*) + + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(SORT(.rodata.*)) + *(.rodata) + + KEEP(*(.eh_frame*)) + + . = ALIGN(4); + __rel_start__ = .; + *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) + __rel_end__ = .; + } + .ARM.exidx : { + . = ALIGN(4); + __exdix_start = .; + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + /* This is used by the startup in order to initialize the .data secion */ + __exdix_end = .; + } + + .permissions_table : { + . = ALIGN(4); + __permissions_table_start__ = .; + KEEP(*(.permissions_table)) + __permissions_table_end__ = .; + } + + + PROVIDE(__ram_size__ = __bss_end__ - __data_start__); + .data : { + . = ALIGN(4); + __data_start__ = .; + __got_start__ = .; + *(.got) + __got_end__ = .; + . = ALIGN(4); + *(.data) + *(.data.*) + + *(vtable) + *(.data*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + . = ALIGN(4); + _shell_command_start = .; + KEEP(*(shellCommand)) + _shell_command_end = .; + + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + } + + PROVIDE(__heap_size__ = __heap_end__ - __heap_start__); + PROVIDE(__stack_size__ = __stack_end__ - __stack_start__); + .bss : { + . = ALIGN(4); + /* This is used by the startup in order to initialize the .bss secion */ + __bss_start__ = .; + *(.bss) + *(COMMON) + + . = ALIGN(4); + __heap_start__ = .; + KEEP(*(.bss.heap)) + __heap_end__ = .; + + . = ALIGN(4); + __stack_start__ = .; + KEEP(*(.bss.stack)) + __stack_end__ = .; + + *(.bss.*) + /* This is used by the startup in order to initialize the .bss secion */ + . = ALIGN(4); + __bss_end__ = .; + } + _end = .; +} diff --git a/mkrtos_user/server/fs/procfs/inc/proc.h b/mkrtos_user/server/fs/procfs/inc/proc.h new file mode 100644 index 000000000..5a4a00d8f --- /dev/null +++ b/mkrtos_user/server/fs/procfs/inc/proc.h @@ -0,0 +1,66 @@ +#pragma once + +#include +#include +#include "u_rpc.h" + +#ifndef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif + +#define NS_NODE_NAME_LEN 32 + +typedef enum proc_node_type +{ + NODE_TYPE_PROC_DUMMY, //!< 虚拟节点,可以有子节点 + NODE_TYPE_PROC_FILE, //!< 服务节点,不能有子节点 + NODE_TYPE_PROC_ROOT, //!< ROOT节点 +} proc_node_type_t; +struct proc_node; +typedef struct proc_node proc_node_t; +typedef struct proc_file_operation +{ + int (*proc_open)(proc_node_t *node, const char *path, int flags, int mode); + int (*proc_read)(proc_node_t *node, void *buf, size_t len, long offset); + int (*proc_write)(proc_node_t *node, void *buf, size_t len, long offset); + void (*proc_close)(proc_node_t *node); + // int (*proc_readdir)(proc_node_t *node, dirent_t *dir); + int (*proc_lseek)(proc_node_t *node, int offs, int whence); + // int (*proc_ftruncate)(proc_node_t *node, off_t off); + // int (*proc_fstat)(proc_node_t *node, void *buf); + int (*proc_ioctl)(proc_node_t *node, int req, void *arg); + // int (*proc_fcntl)(proc_node_t *node, int cmd, void *arg); + // int (*proc_fsync)(proc_node_t *node); +} proc_file_operation_t; + +typedef struct proc_node +{ + char name[NS_NODE_NAME_LEN]; //!< 节点名字 + proc_node_type_t type; //!< 节点类型 + struct proc_node *parent; //!< 父节点 + struct proc_node *next; //!< 兄弟节点的下一个节点 + struct proc_node *sub; //!< 子树节点 + const proc_file_operation_t *op; //!< proc的操作节点 + int ref; //!< 引用计数 +} proc_node_t; + + +void proc_root_node_init(void); +proc_node_t *proc_node_find(proc_node_t **pnode, const char *path, int *ret, int *svr_inx, int *p_inx); +proc_node_t *proc_node_find_full_dir(const char *path, int *ret, int *cur_inx); +proc_node_t *proc_node_find_full_file(const char *path, int *ret, int *cur_inx); +proc_node_t *proc_node_find_svr_file(const char *path, int *ret, int *cur_inx); +int proc_nodes_count(proc_node_t *tree); +proc_node_t *proc_node_get_inx(proc_node_t *tree, int inx); +int proc_delnode(const char *path); +int proc_mknode(const char *path, proc_node_type_t type, const proc_file_operation_t *op); +static inline proc_node_t *proc_node_get_next(proc_node_t *tree_node, proc_node_t *cur_node) +{ + assert(cur_node); + return cur_node->next; +} +static inline proc_node_t *proc_node_get_first(proc_node_t *tree_node) +{ + assert(tree_node); + return tree_node->sub; +} diff --git a/mkrtos_user/server/fs/procfs/inc/procfs.h b/mkrtos_user/server/fs/procfs/inc/procfs.h new file mode 100644 index 000000000..3d6fc97c1 --- /dev/null +++ b/mkrtos_user/server/fs/procfs/inc/procfs.h @@ -0,0 +1,27 @@ +#pragma once +#include "kstat.h" +#include "proc.h" +#include "u_rpc.h" +#include "u_types.h" +#include +#include + +void procfs_lock(void); +void proc_unlock(void); + +int proc_ns_open(const char *name, int flags, int mode); +int proc_ns_write(int fd, void *data, int len); +int proc_ns_read(int fd, void *data, int len); +int proc_ns_ioctl(int fd, unsigned long cmd, unsigned long arg); +int proc_ns_lseek(int fd, int offset, unsigned long whence); +int proc_ns_truncate(int fd, off_t length); +int proc_ns_fstat(int fd, struct kstat *st); +int proc_ns_stat(const char *path, struct kstat *st); +int proc_ns_close(int fd); +int proc_ns_remove(const char *name); +int proc_ns_readdir(int fd, struct dirent *_dir); +int proc_ns_mkdir(char *path); +int proc_ns_rmdir(const char *name); +void proc_ns_del_file_by_pid(const char *path, pid_t pid); +int proc_register_file(const char *path, const proc_file_operation_t *op); +int proc_ns_open_init(void); diff --git a/mkrtos_user/server/fs/procfs/inc/procfs_impl.h b/mkrtos_user/server/fs/procfs/inc/procfs_impl.h new file mode 100644 index 000000000..bba74ef30 --- /dev/null +++ b/mkrtos_user/server/fs/procfs/inc/procfs_impl.h @@ -0,0 +1,3 @@ +#pragma once + +int proc_default_file_register(void); diff --git a/mkrtos_user/server/fs/procfs/inc/procfs_rpc.h b/mkrtos_user/server/fs/procfs/inc/procfs_rpc.h new file mode 100644 index 000000000..c95732b10 --- /dev/null +++ b/mkrtos_user/server/fs/procfs/inc/procfs_rpc.h @@ -0,0 +1,4 @@ +#pragma once + + +void procfs_svr_init(void); diff --git a/mkrtos_user/server/fs/procfs/src/build.sh b/mkrtos_user/server/fs/procfs/src/build.sh new file mode 100755 index 000000000..787d7ee33 --- /dev/null +++ b/mkrtos_user/server/fs/procfs/src/build.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +set -e -x + +mkdir -p build +cmake -G Ninja -B build . +cd build && ninja diff --git a/mkrtos_user/server/fs/procfs/src/clean.sh b/mkrtos_user/server/fs/procfs/src/clean.sh new file mode 100755 index 000000000..8146e4f0f --- /dev/null +++ b/mkrtos_user/server/fs/procfs/src/clean.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +set -e -x + +rm -r build \ No newline at end of file diff --git a/mkrtos_user/server/fs/procfs/src/dummy.c b/mkrtos_user/server/fs/procfs/src/dummy.c deleted file mode 100644 index e69de29bb..000000000 diff --git a/mkrtos_user/server/fs/procfs/src/heap_stack.c b/mkrtos_user/server/fs/procfs/src/heap_stack.c new file mode 100644 index 000000000..9ca1decac --- /dev/null +++ b/mkrtos_user/server/fs/procfs/src/heap_stack.c @@ -0,0 +1,13 @@ +#include +#include + +#define HEAP_SIZE (4096) +#define STACK_SIZE (1024*2) + +#define HEAP_ATTR __attribute__((__section__(".bss.heap"))) +#define STACK_ATTR __attribute__((__section__(".bss.stack"))) + +__attribute__((used)) HEAP_ATTR static char _____heap_____[HEAP_SIZE]; +__attribute__((used)) STACK_ATTR static char _____stack_____[STACK_SIZE]; +__attribute__((used)) umword_t _____mm_bitmap_____[ROUND(HEAP_SIZE, MK_PAGE_SIZE) / (sizeof(umword_t) * 8) + 1]; + diff --git a/mkrtos_user/server/fs/procfs/src/main.c b/mkrtos_user/server/fs/procfs/src/main.c new file mode 100644 index 000000000..157dc6c3a --- /dev/null +++ b/mkrtos_user/server/fs/procfs/src/main.c @@ -0,0 +1,201 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "proc.h" +#include "procfs.h" +#include + +int procfs_mkdir_test(void) +{ + int ret; + + ret = proc_ns_mkdir("/bin/tst/"); + assert(ret < 0); + ret = proc_ns_mkdir("/bin/"); + assert(ret >= 0); + ret = proc_ns_mkdir("/bin2"); + assert(ret >= 0); + ret = proc_ns_mkdir("/bin/tst/"); + assert(ret >= 0); + ret = proc_ns_remove("/bin/tst"); + assert(ret < 0); + ret = proc_ns_rmdir("/bin/tst"); + assert(ret >= 0); + return 0; +} + +int procfs_scan_dir_test(void) +{ +#define TEST_CN 10 + int ret; + ret = proc_ns_mkdir("/bin/"); + assert(ret >= 0); + + for (int i = 0; i < TEST_CN; i++) + { + char dir_name[32]; + + snprintf(dir_name, sizeof(dir_name), "/bin/tst%d", i); + ret = proc_ns_mkdir(dir_name); + assert(ret >= 0); + } + int fd; + + fd = proc_ns_open("/bin/", O_RDWR, 0777); + assert(fd >= 0); + struct dirent dir_info; + for (int i = 0; i < (TEST_CN + 1); i++) + { + ret = proc_ns_readdir(fd, &dir_info); + if (i < TEST_CN) + { + assert(ret >= 0); + printf("readdir info :%s\n", dir_info.d_name); + fflush(stdout); + } + else + { + assert(ret < 0); + } + } + ret = proc_ns_lseek(fd, 2, SEEK_SET); + printf("old seek: %d\n", ret); + assert(ret >= 0); + for (int i = 0; i < (TEST_CN - 2 + 1); i++) + { + ret = proc_ns_readdir(fd, &dir_info); + if (i < TEST_CN - 2) + { + assert(ret >= 0); + printf("readdir info :%s\n", dir_info.d_name); + fflush(stdout); + } + else + { + assert(ret < 0); + } + } + + ret = proc_ns_close(fd); + assert(ret >= 0); + ret = proc_ns_readdir(fd, &dir_info); + assert(ret < 0); + + for (int i = 0; i < TEST_CN; i++) + { + char dir_name[32]; + snprintf(dir_name, sizeof(dir_name), "/bin/tst%d", i); + ret = proc_ns_rmdir(dir_name); + assert(ret >= 0); + } + ret = proc_ns_rmdir("/bin"); + assert(ret >= 0); +#undef TEST_CN + return 0; +} +int procfs_mksvr_node(void) +{ + int ret; + struct dirent dir; + + ret = proc_ns_mkdir("/bin/"); + assert(ret >= 0); + ret = proc_mknode("/bin/tst1", NODE_TYPE_PROC_FILE, NULL); + assert(ret >= 0); + int fd; + + fd = proc_ns_open("/bin/tst1", O_RDWR, 0777); + assert(fd < 0); + fd = proc_ns_open("/bin/", O_RDWR, 0777); + assert(fd >= 0); + ret = proc_ns_readdir(fd, &dir); + assert(ret >= 0); + printf("readdir info :%s\n", dir.d_name); + ret = proc_ns_close(fd); + assert(ret >= 0); + + ret = proc_ns_remove("/bin/tst1/"); + assert(ret >= 0); + ret = proc_ns_rmdir("/bin/"); + assert(ret >= 0); + return 0; +} +int procfs_query_svr_node(void) +{ + int ret; + ret = proc_ns_mkdir("/bin/"); + assert(ret >= 0); + proc_node_t *node; + proc_node_t *pnode; + int cur_inx; + int p_inx; + + node = proc_node_find_full_file("/bin/", &ret, &cur_inx); + assert(node == NULL && ret < 0); + +#define SVR_NODE "/svr_tst" + ret = proc_mknode(SVR_NODE, NODE_TYPE_PROC_FILE, NULL); + assert(ret >= 0); + + node = proc_node_find_full_file(SVR_NODE, &ret, &cur_inx); + assert(node != NULL && ret >= 0); + assert(cur_inx == strlen(SVR_NODE)); + + node = proc_node_find(&pnode, SVR_NODE "/1/2/3", &ret, &cur_inx, &p_inx); + assert(node != NULL && ret >= 0); + assert(cur_inx == strlen(SVR_NODE) + 1); + + ret = proc_ns_mkdir(SVR_NODE "/1"); + assert(ret < 0); +#undef SVR_NODE + ret = proc_ns_remove("/svr_tst"); + assert(ret >= 0); +#define SVR_NODE "/bin/svr_tst" + ret = proc_mknode(SVR_NODE, NODE_TYPE_PROC_FILE, NULL); + assert(ret >= 0); + node = proc_node_find_full_file(SVR_NODE, &ret, &cur_inx); + assert(node != NULL && ret >= 0); + assert(cur_inx == strlen(SVR_NODE)); + node = proc_node_find_svr_file(SVR_NODE "/1/2/3", &ret, &cur_inx); + assert(node != NULL && ret >= 0); + assert(cur_inx == strlen(SVR_NODE) + 1); + + ret = proc_ns_rmdir("/bin/"); + assert(ret < 0); + + ret = proc_ns_remove(SVR_NODE); + assert(ret >= 0); + ret = proc_ns_rmdir("/bin/"); + assert(ret >= 0); + return 0; +} +int procfs_stat_test(void) +{ + int ret; + struct kstat fst; + int fd; + + ret = proc_ns_mkdir("/tstdir/"); + assert(ret >= 0); + fd = proc_ns_open("/tstdir/", O_RDWR, 0777); + assert(fd >= 0); + ret = proc_ns_fstat(fd, &fst); + assert(ret >= 0); + ret = proc_ns_close(fd); + assert(ret >= 0); + return 0; +} +int main(int argc, char *argv[]) +{ + procfs_mkdir_test(); + procfs_scan_dir_test(); + procfs_stat_test(); + procfs_mksvr_node(); + procfs_query_svr_node(); + return 0; +} \ No newline at end of file diff --git a/mkrtos_user/server/fs/procfs/src/proc.c b/mkrtos_user/server/fs/procfs/src/proc.c new file mode 100644 index 000000000..6e9abf49a --- /dev/null +++ b/mkrtos_user/server/fs/procfs/src/proc.c @@ -0,0 +1,406 @@ + +#include +#include +#include +#include +#include +#include "proc.h" +#ifdef MKRTOS +#include +#include +#include +#endif +// 其他进程可以注册节点进来,并且可以注册子节点进来,子节点可以注册更多的子节点进来。 +// 可以注册两种节点DUMMY和SVR节点 +// 只有DUMMY节点里面可以注册SVR节点 +// 查找节点时采取最大服务匹配的原则,即匹配到最后一个SVR节点时,返回最后一个SVR节点的HD,以及截断的位置。 + +static proc_node_t root_node = { + .type = NODE_TYPE_PROC_DUMMY, +}; + +void proc_root_node_init(void) +{ + root_node.op = NULL; +} +/** + * 从路径中copy名字 + */ +static int proc_node_strcpy(char *dst, const char *src, int n) +{ + int j; + + for (j = 0; src[j] && src[j] != '/' && j < n; j++) + { + dst[j] = src[j]; + } + if (j < n) + { + dst[j] = 0; + } + return j; +} +/** + * 找到节点中的子节点 + */ +static proc_node_t *proc_node_find_sub(proc_node_t *tree, const char *name) +{ + assert(name); + if (tree == NULL) + { + return NULL; + } + proc_node_t *cur = tree->sub; + + while (cur) + { + if (strncmp(cur->name, name, NS_NODE_NAME_LEN) == 0) + { + return cur; + } + cur = cur->next; + } + return NULL; +} +int proc_nodes_count(proc_node_t *tree) +{ + int nr = 0; + assert(tree); + assert(tree->type == NODE_TYPE_PROC_DUMMY); + + proc_node_t *cur = tree->next; + + while (cur) + { + nr++; + cur = cur->next; + } + return nr; +} +static int proc_node_del(proc_node_t *tree, proc_node_t *del_node) +{ + proc_node_t *tmp = tree->sub; + proc_node_t *pre = NULL; + + while (tmp) + { + if (tmp == del_node) + { + if (pre == NULL) + { + // 删除第一个节点 + tree->sub = tmp->next; + return 0; + } + else + { + pre->next = tmp->next; + return 0; + } + } + pre = tmp; + tmp = tmp->next; + } + return -1; +} +static proc_node_t *node_create(const char *name, proc_node_type_t type) +{ + proc_node_t *tmp; + +#ifdef MKRTOS + tmp = calloc(sizeof(proc_node_t), 1); +#else + tmp = calloc(sizeof(proc_node_t), 1); +#endif + if (!tmp) + { + return NULL; + } + strncpy(tmp->name, name, NS_NODE_NAME_LEN); + tmp->name[NS_NODE_NAME_LEN - 1] = 0; + tmp->type = type; + return tmp; +} +proc_node_t *proc_node_get_inx(proc_node_t *tree, int inx) +{ + assert(tree); + assert(tree->type == NODE_TYPE_PROC_DUMMY); + int nr = 0; + proc_node_t *cur = tree->sub; + + while (cur) + { + if (nr == inx) + { + return cur; + } + nr++; + cur = cur->next; + } + return cur; +} +/** + * 查找节点,如果是dummy节点,则一直循环查找。 + * 如果是svr节点,则立刻终止查找,然后返回当前节点,以及截断的位置 + */ +proc_node_t *proc_node_find(proc_node_t **pnode, const char *path, int *ret, int *svr_inx, int *p_inx) +{ + assert(ret); + assert(path); + + proc_node_t *cur_node = NULL; + char name[NS_NODE_NAME_LEN]; + int find_node_cut_inx = 0; + + if (pnode) + { + *pnode = NULL; + } + if (path[0] != '/') + { + printf("[%s] path is error.\n", path); + *ret = -EINVAL; + return cur_node; + } + cur_node = &root_node; + int i = 0; + + while (path[i]) + { + proc_node_t *t_node; + int len; + + // 获得节点的名字 + len = proc_node_strcpy(name, path + i + 1, NS_NODE_NAME_LEN); + name[MIN(NS_NODE_NAME_LEN - 1, len)] = 0; + if (len == 0) + { + // find_node_cut_inx++; + goto end; + } + // 查找子节点 + t_node = proc_node_find_sub(cur_node, name); + if (pnode) + { + *pnode = cur_node; + } + + if (t_node) + { + if (t_node->type == NODE_TYPE_PROC_DUMMY) + { + cur_node = t_node; + } + else if (t_node->type == NODE_TYPE_PROC_FILE) + { + find_node_cut_inx = i + len + 1; + if (path[find_node_cut_inx] == '/') + { + find_node_cut_inx++; + } + // 找到服务节点,那直接返回,服务节点不会有子节点。 + cur_node = t_node; + goto end; + } + } + else + { + if (cur_node == NULL) + { + goto end; + } + cur_node = NULL; + } + if (p_inx) + { + *p_inx = i; + } + if (path[i] == '/') + { + i++; + } + i += len; + } +end: + *svr_inx = find_node_cut_inx; + *ret = 0; + return cur_node; +} + +/** + * 删除节点时,必须保证全路径匹配 + */ +int proc_delnode(const char *path) +{ + proc_node_t *cur_node; + int ret; + int cur_inx; + + cur_node = proc_node_find(NULL, path, &ret, &cur_inx, NULL); + if (cur_node == NULL) + { + printf("ns node not find.\n"); + return -ENOENT; + } + if (cur_node->type == NODE_TYPE_PROC_DUMMY && cur_node->ref != 0) + { + printf("ns dir is not empty.\n"); + return -ENOTEMPTY; + } + ret = proc_node_del(cur_node->parent, cur_node); + if (cur_node->type == NODE_TYPE_PROC_FILE) + { + printf("ns del [%s].\n", path); + } + cur_node->parent->ref--; +#ifdef MKRTOS + free(cur_node); +#else + free(cur_node); +#endif + return ret; +} +/** + * 查找到完整的路径目录 + */ +proc_node_t *proc_node_find_full_dir(const char *path, int *ret, int *cur_inx) +{ + assert(path); + assert(ret); + assert(cur_inx); + proc_node_t *dir_node; + + dir_node = proc_node_find(NULL, path, ret, cur_inx, NULL); + if (dir_node == NULL || dir_node->type != NODE_TYPE_PROC_DUMMY || *cur_inx != 0) + { +#if 0 + printf("ns node not find or path error.\n"); +#endif + // 未找到,节点不是dummy节点,路径不是结尾处 则直接退出 + *ret = -ENOENT; + return NULL; + } + + return dir_node; +} +/** + * 查找到完整的路径文件 + */ +proc_node_t *proc_node_find_full_file(const char *path, int *ret, int *cur_inx) +{ + assert(path); + assert(ret); + assert(cur_inx); + proc_node_t *dir_node; + + dir_node = proc_node_find(NULL, path, ret, cur_inx, NULL); + if (dir_node == NULL || dir_node->type != NODE_TYPE_PROC_FILE || path[*cur_inx] != '\0') + { +#if 0 + printf("ns node not find or path error.\n"); +#endif + // 未找到,节点不是 svr 节点,路径不是结尾处 则直接退出 + *ret = -ENOENT; + return NULL; + } + + return dir_node; +} +static inline int is_root_node(proc_node_t *node) +{ + return node == &root_node; +} +proc_node_t *proc_node_find_svr_file(const char *path, int *ret, int *cur_inx) +{ + assert(path); + assert(ret); + assert(cur_inx); + proc_node_t *dir_node; + proc_node_t *parent_node; + + dir_node = proc_node_find(&parent_node, path, ret, cur_inx, NULL); + if (is_root_node(dir_node)) + { + (*cur_inx)++; + return dir_node; + } + if (dir_node == NULL || dir_node->type != NODE_TYPE_PROC_FILE) + { +#if 0 + printf("ns node not find or path error.\n"); +#endif + if (is_root_node(parent_node)) + { + return parent_node; + } + if (!parent_node) + { + *ret = -ENOENT; + return NULL; + } + if ((parent_node->type == NODE_TYPE_PROC_DUMMY && (dir_node == NULL || dir_node->type == NODE_TYPE_PROC_DUMMY))) + { + return &root_node; + } + // 未找到,节点不是 svr 节点,路径不是结尾处 则直接退出 + *ret = -ENOENT; + return NULL; + } + + return dir_node; +} + +/** + * 创建一个节点 + * 只能在前置节点全部为dummy的节点里面创建节点 + */ +int proc_mknode(const char *path, proc_node_type_t type, const proc_file_operation_t *op) +{ + proc_node_t *dir_node; + proc_node_t *new_node; + proc_node_t *cur_node; + int ret; + int cur_inx; + int p_inx; + char name[NS_NODE_NAME_LEN]; + + cur_node = proc_node_find(&dir_node, path, &ret, &cur_inx, &p_inx); + if (dir_node == NULL || dir_node->type != NODE_TYPE_PROC_DUMMY || (cur_node != NULL)) + { + if (cur_node != NULL && cur_node->type == NODE_TYPE_PROC_FILE) + { + return -EEXIST; + } + if (cur_node != NULL && cur_node->type == NODE_TYPE_PROC_DUMMY) + { + return -EISDIR; + } + return -ENOENT; + } + // 获得节点的名字 + // int name_len = 0; + + proc_node_strcpy(name, path + p_inx + 1, NS_NODE_NAME_LEN); + + new_node = node_create(name, NODE_TYPE_PROC_DUMMY); + if (new_node == NULL) + { + return -ENOMEM; + } + // 加到目录的链表中 + new_node->next = dir_node->sub; + dir_node->sub = new_node; + new_node->type = type; + new_node->parent = dir_node; + if (type == NODE_TYPE_PROC_FILE) + { + new_node->op = op; + } + else + { + new_node->sub = NULL; + } + // 增加引用计数 + dir_node->ref++; + return 0; +} diff --git a/mkrtos_user/server/fs/procfs/src/procfs.c b/mkrtos_user/server/fs/procfs/src/procfs.c new file mode 100644 index 000000000..61fe81598 --- /dev/null +++ b/mkrtos_user/server/fs/procfs/src/procfs.c @@ -0,0 +1,689 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "proc.h" +#include "kstat.h" +#define DIR_INFO_CACHE_NR 32 + +typedef struct dir_info_cache +{ + proc_node_t *info; + int ref; +} dir_info_cache_t; + +static dir_info_cache_t dir_info_cache_list[DIR_INFO_CACHE_NR]; +static u_mutex_t procfs_mutex_lock; + +void procfs_lock(void) +{ + u_mutex_lock(&procfs_mutex_lock, 0, NULL); +} +void proc_unlock(void) +{ + u_mutex_unlock(&procfs_mutex_lock); +} +static int dir_info_cache_get(proc_node_t *info) +{ + if (info == NULL) + { + return -EINVAL; + } + for (int i = 0; i < DIR_INFO_CACHE_NR; i++) + { + if (dir_info_cache_list[i].info == NULL) + { + continue; + } + if (dir_info_cache_list[i].info == info) + { + dir_info_cache_list[i].ref++; + return i; + } + } + for (int i = 0; i < DIR_INFO_CACHE_NR; i++) + { + if (dir_info_cache_list[i].info == NULL) + { + dir_info_cache_list[i].info = info; + dir_info_cache_list[i].ref++; + return i; + } + } + return -1; +} +static void dir_info_cache_put(proc_node_t *info) +{ + assert(info); + for (int i = 0; i < DIR_INFO_CACHE_NR; i++) + { + if (dir_info_cache_list[i].info == NULL) + { + continue; + } + if (dir_info_cache_list[i].info == info) + { + dir_info_cache_list[i].ref--; + if (dir_info_cache_list[i].ref == 0) + { + dir_info_cache_list[i].info = NULL; + return; + } + } + } +} +enum proc_ns_type +{ + FS_NS_FILE_TYPE, + FS_NS_DIR_TYPE, +}; +#define DIR_INFO_NR 32 +typedef struct proc_ns_file +{ + int dir_info_fd; //!< dirinfo cache fd. + int tmp_fd; //!< current info fd. + uint8_t flags; //!< 文件操作的flags + int offset; //!< 文件操作的偏移 + enum proc_ns_type type; //!< 类型 + uint8_t used; +} proc_ns_file_t; + +static proc_ns_file_t proc_ns_files[DIR_INFO_NR]; + +static proc_ns_file_t *proc_ns_get_file(int fd); + +static int proc_ns_file_alloc(proc_node_t *file, int flags, enum proc_ns_type type) +{ + int dir_info_fd = -1; + + if (file != NULL) + { + dir_info_fd = dir_info_cache_get(file); + if (dir_info_fd < 0) + { + printf("dir_info cache is full.\n"); + return dir_info_fd; + } + } + + for (int i = 0; i < DIR_INFO_NR; i++) + { + if (proc_ns_files[i].used == 0) + { + // 不存在则增加一个新的 + proc_ns_files[i].dir_info_fd = dir_info_fd; + proc_ns_files[i].tmp_fd = -1; + proc_ns_files[i].flags = flags; + proc_ns_files[i].offset = 0; + proc_ns_files[i].type = type; + proc_ns_files[i].used = 1; + return i; + } + } + return -1; +} + +static proc_ns_file_t *proc_ns_get_file(int fd) +{ + if (fd < 0 || fd >= DIR_INFO_NR) + { + return NULL; + } + if (proc_ns_files[fd].used == 0) + { + return NULL; + } + return proc_ns_files + fd; +} + +int proc_ns_open(const char *name, int flags, int mode) +{ + int ret; + proc_node_t *file; + int fd; + int cur_inx; + enum proc_ns_type type; + + if (name[0] == '\0') + { + name = "/"; + } + // 路径必须'/'卡头 + if (name[0] != '/') + { + printf("nsfs path is error.\n"); + return -EINVAL; + } + if (flags & O_CREAT) + { + // not support to create file. + return -ENOSYS; + } + procfs_lock(); + // path must is dir. + file = proc_node_find_full_dir(name, &ret, &cur_inx); + if (file == NULL) + { + file = proc_node_find_full_file(name, &ret, &cur_inx); + if (file == NULL) + { + proc_unlock(); + return -EINVAL; + } + type = FS_NS_FILE_TYPE; + if (file->op && file->op->proc_open) + { + ret = file->op->proc_open(file, name, flags, mode); + if (ret < 0) + { + proc_unlock(); + return ret; + } + } + } else { + type = FS_NS_DIR_TYPE; + } + fd = proc_ns_file_alloc(file, flags, type); + if (fd < 0) + { + proc_unlock(); + return fd; + } + proc_unlock(); + return fd; +} +int proc_ns_write(int fd, void *data, int len) +{ + proc_ns_file_t *file; + int ret = 0; + + procfs_lock(); + file = proc_ns_get_file(fd); + if (!file || file->used == 0) + { + ret = -ENOENT; + goto end; + } + if (file->type != FS_NS_FILE_TYPE) + { + ret = -EBADF; + goto end; + } + proc_node_t *info; + + info = dir_info_cache_list[file->dir_info_fd].info; + if (!info->op || !info->op->proc_write) + { + ret = -EROFS; + goto end; + } + ret = info->op->proc_write(info, data, len, file->offset); + if (ret >= 0) + { + file->offset += ret; + } +end: + proc_unlock(); + return ret; +} +int proc_ns_read(int fd, void *data, int len) +{ + proc_ns_file_t *file; + int ret = 0; + + procfs_lock(); + file = proc_ns_get_file(fd); + if (!file || file->used == 0) + { + ret = -ENOENT; + goto end; + } + if (file->type != FS_NS_FILE_TYPE) + { + ret = -EBADF; + goto end; + } + proc_node_t *info; + + info = dir_info_cache_list[file->dir_info_fd].info; + if (!info->op || !info->op->proc_read) + { + ret = -EIO; + goto end; + } + ret = info->op->proc_read(info, data, len, file->offset); + if (ret >= 0) + { + file->offset += ret; + } +end: + proc_unlock(); + return ret; +} + +int proc_ns_ioctl(int fd, unsigned long cmd, unsigned long arg) +{ +proc_ns_file_t *file; + int ret = 0; + + procfs_lock(); + file = proc_ns_get_file(fd); + if (!file || file->used == 0) + { + ret = -ENOENT; + goto end; + } + if (file->type != FS_NS_FILE_TYPE) + { + ret = -EBADF; + goto end; + } + proc_node_t *info; + + info = dir_info_cache_list[file->dir_info_fd].info; + if (!info->op || !info->op->proc_ioctl) + { + ret = -EIO; + goto end; + } + ret = info->op->proc_ioctl(info, cmd, (void *)arg); + if (ret >= 0) + { + file->offset += ret; + } +end: + proc_unlock(); + return ret; +} +static int proc_ns_get_dir_size(proc_ns_file_t *file) +{ + return proc_nodes_count(dir_info_cache_list[file->dir_info_fd].info); +} +int proc_ns_lseek(int fd, int offset, unsigned long whence) +{ + proc_ns_file_t *file; + int new_offs = 0; + int old_offs = 0; + + procfs_lock(); + file = proc_ns_get_file(fd); + if (!file || file->used == 0) + { + proc_unlock(); + return -ENOENT; + } + old_offs = file->offset; + switch (whence) + { + case SEEK_SET: + new_offs = offset; + break; + case SEEK_END: + { + new_offs = proc_ns_get_dir_size(file) + offset; + } + break; + case SEEK_CUR: + { + new_offs = offset + file->offset; + } + break; + default: + proc_unlock(); + return -EINVAL; + } + if (new_offs > proc_ns_get_dir_size(file)) + { + new_offs = proc_ns_get_dir_size(file); + } + if (new_offs < 0) + { + new_offs = 0; + } + if (file->type == FS_NS_DIR_TYPE) + { + proc_node_t *new_dir_info; + + new_dir_info = proc_node_get_inx(dir_info_cache_list[file->dir_info_fd].info, new_offs); + if (new_dir_info == NULL) + { + proc_unlock(); + return -ENOENT; + } + if (file->tmp_fd >= 0) + { + dir_info_cache_put(dir_info_cache_list[file->tmp_fd].info); + } + file->tmp_fd = dir_info_cache_get(new_dir_info); + } + file->offset = new_offs; + proc_unlock(); + return old_offs; +} +int proc_ns_truncate(int fd, off_t length) +{ + return -ENOSYS; +} +int proc_ns_fstat(int fd, struct kstat *st) +{ + proc_ns_file_t *file; + + procfs_lock(); + file = proc_ns_get_file(fd); + if (!file || file->used == 0) + { + proc_unlock(); + return -ENOENT; + } + memset(st, 0, sizeof(*st)); + st->st_size = 0; + st->st_mode = file->type == FS_NS_FILE_TYPE ? S_IFREG : S_IFDIR; + st->st_nlink = dir_info_cache_list[file->dir_info_fd].info->ref; + proc_unlock(); + return 0; +} +int proc_ns_stat(const char *path, struct kstat *st) +{ + if (path[0] == '\0') + { + path = "/"; + } + memset(st, 0, sizeof(*st)); + + proc_node_t *file; + int ret; + int cur_inx; + + procfs_lock(); + file = proc_node_find_full_dir(path, &ret, &cur_inx); + if (file == NULL) + { + file = proc_node_find_full_file(path, &ret, &cur_inx); + if (file == NULL) + { + proc_unlock(); + return -ENOENT; + } + } + + st->st_size = 0; + st->st_mode = file->type != NODE_TYPE_PROC_DUMMY ? S_IFREG : S_IFDIR; + st->st_nlink = file->ref; + proc_unlock(); + return 0; +} +int proc_ns_close(int fd) +{ + proc_ns_file_t *file; + + procfs_lock(); + file = proc_ns_get_file(fd); + if (!file || file->used == 0) + { + proc_unlock(); + return -ENOENT; + } + proc_node_t *info = dir_info_cache_list[file->dir_info_fd].info; + if (file->type == FS_NS_FILE_TYPE) + { + if (info->op && info->op->proc_close) + { + // 不关心close的返回值 + info->op->proc_close(info); + } + } + if (file->tmp_fd >= 0) + { + dir_info_cache_put(dir_info_cache_list[file->tmp_fd].info); + } + dir_info_cache_put(dir_info_cache_list[file->dir_info_fd].info); + file->dir_info_fd = -1; + file->tmp_fd = -1; + file->flags = 0; + file->offset = 0; + file->used = 0; + file->type = FS_NS_FILE_TYPE; + proc_unlock(); + return 0; +} +int proc_ns_rmdir(const char *name) +{ + proc_node_t *file; + int ret; + int dir_info_fd; + int cur_inx; + + if (name[0] == '\0') + { + name = "/"; + } + procfs_lock(); + file = proc_node_find_full_dir(name, &ret, &cur_inx); + if (file == NULL) + { + proc_unlock(); + return -ENOENT; + } + + dir_info_fd = dir_info_cache_get(file); + if (dir_info_cache_list[dir_info_fd].ref == 1) + { + ret = proc_delnode(name); + if (ret < 0) + { + dir_info_cache_put(file); + proc_unlock(); + return ret; + } + } + dir_info_cache_put(file); + proc_unlock(); + return 0; +} +int proc_ns_remove(const char *name) +{ + proc_node_t *file; + int ret; + int dir_info_fd; + int cur_inx; + + if (name[0] == '\0') + { + name = "/"; + } + procfs_lock(); + file = proc_node_find_full_file(name, &ret, &cur_inx); + if (file == NULL) + { + proc_unlock(); + return -ENOENT; + } + + dir_info_fd = dir_info_cache_get(file); + if (dir_info_cache_list[dir_info_fd].ref == 1) + { + ret = proc_delnode(name); + if (ret < 0) + { + proc_unlock(); + return ret; + } + } + dir_info_cache_put(file); + proc_unlock(); + return 0; +} +int proc_ns_readdir(int fd, struct dirent *_dir) +{ + int ret = -1; + proc_ns_file_t *file; + + procfs_lock(); + file = proc_ns_get_file(fd); + if (!file || file->used == 0) + { + proc_unlock(); + return -ENOENT; + } + if (file->type != FS_NS_DIR_TYPE) + { + proc_unlock(); + return -EACCES; + } + if (file->tmp_fd == -1) + { + proc_node_t *dir_info; + + dir_info = proc_node_get_first(dir_info_cache_list[file->dir_info_fd].info); + if (dir_info == NULL) + { + proc_unlock(); + return -ENOENT; + } + ret = dir_info_cache_get(dir_info); + if (ret < 0) + { + proc_unlock(); + return ret; + } + file->tmp_fd = ret; + } + else if (file->tmp_fd == -2) + { + proc_unlock(); + return -ENOENT; + } + proc_node_t *node_info; + + node_info = dir_info_cache_list[file->tmp_fd].info; + _dir->d_reclen = sizeof(*_dir); + _dir->d_type = node_info->type == NODE_TYPE_PROC_DUMMY ? DT_DIR : DT_CHR; // DT_REG‌; + strncpy(_dir->d_name, node_info->name, sizeof(_dir->d_name)); + _dir->d_name[sizeof(_dir->d_name) - 1] = 0; + + proc_node_t *next_dir_info = proc_node_get_next(dir_info_cache_list[file->dir_info_fd].info, node_info); + dir_info_cache_put(node_info); + ret = dir_info_cache_get(next_dir_info); + if (ret >= 0) + { + file->tmp_fd = ret; + file->offset++; + } + else + { + file->tmp_fd = -2; // -2代表结束遍历 + } + proc_unlock(); + return sizeof(*_dir); +} +int proc_ns_mkdir(char *path) +{ + int ret; + + procfs_lock(); + ret = proc_mknode(path, NODE_TYPE_PROC_DUMMY, NULL); + proc_unlock(); + return ret; +} +int proc_ns_open_init(void) +{ + int ret; + + for (int i = 0; i < DIR_INFO_NR; i++) + { + proc_ns_files[i].dir_info_fd = -1; + proc_ns_files[i].tmp_fd = -1; + } + ret = u_mutex_init(&procfs_mutex_lock, handler_alloc()); + if (ret < 0) + { + return ret; + } + return 0; +} + +/** + * 通过pid删除nsfs中的文件 + */ +void proc_ns_del_file_by_pid(const char *path, pid_t pid) +{ + if (path == NULL) + { + return; + } + int fd; + char *new_path; + struct dirent dir; + int path_len; + + path_len = strlen(path) + 64; + new_path = malloc(path_len); + if (new_path == NULL) + { + return; + } + + fd = proc_ns_open(path, O_RDONLY, 0); + if (fd < 0) + { + free(new_path); + return; + } + while (1) + { + if (proc_ns_readdir(fd, &dir) < 0) + { + break; + } + if (path[0] == '/' && path[1] == '\0') + { + snprintf(new_path, path_len, "/%s", dir.d_name); + } + else + { + snprintf(new_path, path_len, "%s/%s", path, dir.d_name); + } + // 递归删除 + if (dir.d_type == DT_DIR) + { + proc_ns_del_file_by_pid(new_path, pid); + continue; + } + struct kstat st; + if (proc_ns_stat(new_path, &st) < 0) + { + continue; + } + if (st.pid == pid) + { + proc_ns_remove(new_path); + } + } + free(new_path); + proc_ns_close(fd); +} + +int proc_register_file(const char *path, const proc_file_operation_t *op) +{ + assert(op); + assert(path); + int ret; + + procfs_lock(); + ret = proc_mknode(path, NODE_TYPE_PROC_FILE, op); + if (ret < 0) + { + printf("register [%s] failed.\n", (char *)(path)); + } + proc_unlock(); + return ret; +} diff --git a/mkrtos_user/server/fs/procfs/src/procfs_impl.c b/mkrtos_user/server/fs/procfs/src/procfs_impl.c new file mode 100644 index 000000000..2d8203531 --- /dev/null +++ b/mkrtos_user/server/fs/procfs/src/procfs_impl.c @@ -0,0 +1,53 @@ +#include "proc.h" +#include "procfs.h" +#include "procfs_rpc.h" +#include +#include +static int proc_open(proc_node_t *node, const char *path, int flags, int mode) +{ + return 0; +} +static int proc_read(proc_node_t *node, void *buf, size_t len, long offset) +{ + msg_tag_t tag; + char name[8]; + + if (offset >= sizeof(name)) + { + return -1; + } + + tag = u_task_get_obj_name(TASK_THIS, TASK_THIS, name); + memcpy(buf, name + offset, MIN(len, sizeof(name) - offset)); + return MIN(len, sizeof(name)); +} +static int proc_write(proc_node_t *node, void *buf, size_t len, long offset) +{ + msg_tag_t tag; + char name[8]; + + if (len < sizeof(name) || offset >= sizeof(name)) + { + return -1; + } + memcpy(name, buf, MIN(len, sizeof(name))); + tag = u_task_set_obj_name(TASK_THIS, TASK_THIS, name); + return MIN(len, sizeof(name)); +} +static const proc_file_operation_t name_op = +{ + .proc_open = proc_open, + .proc_read = proc_read, + .proc_write = proc_write, +}; +int proc_default_file_register(void) +{ + int ret; + + ret = proc_register_file("/comm", &name_op); + if (ret < 0) { + printf("task reg [name] node failed.\n"); + return ret; + } + return 0; +} diff --git a/mkrtos_user/server/fs/procfs/src/procfs_rpc.c b/mkrtos_user/server/fs/procfs/src/procfs_rpc.c new file mode 100644 index 000000000..15ac2c964 --- /dev/null +++ b/mkrtos_user/server/fs/procfs/src/procfs_rpc.c @@ -0,0 +1,147 @@ +#include "cons_cli.h" +#include "fs_svr.h" +#include "kstat.h" +#include "rpc_prot.h" +#include "u_env.h" +#include "u_log.h" +#include "u_rpc.h" +#include "u_rpc_svr.h" +#include "u_sig.h" +#include "u_task.h" +#include "pm_cli.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "fd.h" +#include "u_path.h" +#include "procfs.h" +#include "procfs_impl.h" + +static fs_t fs; +static meta_t procfs_meta; +static obj_handler_t procfs_ipc_hd; +static int fs_sig_call_back(pid_t pid, umword_t sig_val); + +static int fs_svr_open(const char *path, int flags, int mode) +{ + return proc_ns_open(path, flags, mode); +} + +static int fs_svr_read(int fd, void *buf, size_t len) +{ + return proc_ns_read(fd, buf, len); +} +static int fs_svr_write(int fd, void *buf, size_t len) +{ + return proc_ns_write(fd, buf, len); +} +static void fs_svr_close(int fd) +{ + proc_ns_close(fd); +} +static int fs_svr_readdir(int fd, dirent_t *dir) +{ + return proc_ns_readdir(fd, dir); +} +static int fs_svr_lseek(int fd, int offs, int whence) +{ + return proc_ns_lseek(fd, offs, whence); +} +static int fs_svr_ftruncate(int fd, off_t off) +{ + return -ENOSYS; +} +static int fs_svr_fstat(int fd, void *_stat) +{ + return proc_ns_fstat(fd, _stat); +} +static int fs_svr_ioctl(int fd, int req, void *arg) +{ + return proc_ns_ioctl(fd, req, (unsigned long)arg); +} +static int fs_svr_fsync(int fd) +{ + return -ENOSYS; +} +static int fs_svr_unlink(const char *path) +{ + return proc_ns_remove(path); +} +static int fs_svr_symlink(const char *existing, const char *new) +{ + return -ENOSYS; +} +static int fs_svr_mkdir(char *path) +{ + return proc_ns_mkdir(path); +} +static int fs_svr_rmdir(char *path) +{ + return proc_ns_rmdir(path); +} +static int fs_svr_rename(char *oldname, char *newname) +{ + return -ENOSYS; +} +static int fs_svr_stat(const char *path, void *_buf) +{ + return proc_ns_stat(path, _buf); +} +static ssize_t fs_svr_readlink(const char *path, char *buf, size_t bufsize) +{ + return -ENOSYS; +} + +static int fs_svr_statfs(const char *path, struct statfs *buf) +{ + return -ENOSYS; +} +static const fs_operations_t ops = + { + .fs_svr_open = fs_svr_open, + .fs_svr_read = fs_svr_read, + .fs_svr_write = fs_svr_write, + .fs_svr_close = fs_svr_close, + .fs_svr_readdir = fs_svr_readdir, + .fs_svr_lseek = fs_svr_lseek, + .fs_svr_ftruncate = fs_svr_ftruncate, + .fs_svr_fstat = fs_svr_fstat, + .fs_svr_ioctl = fs_svr_ioctl, + // .fs_svr_fcntl = fs_svr_fcntl, + .fs_svr_fsync = fs_svr_fsync, + .fs_svr_unlink = fs_svr_unlink, + .fs_svr_symlink = fs_svr_symlink, + .fs_svr_mkdir = fs_svr_mkdir, + .fs_svr_rmdir = fs_svr_rmdir, + .fs_svr_rename = fs_svr_rename, + .fs_svr_stat = fs_svr_stat, + .fs_svr_readlink = fs_svr_readlink, +}; +AUTO_CALL(101) __USED +void procfs_svr_init(void) +{ + int ret; + char proc_path[20]; + umword_t pid; + + fs_init(&fs, &ops); + meta_obj_init(&procfs_meta); + rpc_meta_init(&procfs_meta, TASK_THIS, &procfs_ipc_hd); + meta_reg_svr_obj_raw(&procfs_meta, &fs.svr, FS_PROT); + + u_task_get_pid(TASK_THIS, &pid); + snprintf(proc_path, sizeof(proc_path), "/proc/%d", pid); + + ret = ns_register(proc_path, procfs_ipc_hd, 0); + if (ret < 0) + { + printf("task proc reg failed [%d].\n", ret); + } + proc_default_file_register(); +} diff --git a/mkrtos_user/server/shell/CMakeLists.txt b/mkrtos_user/server/shell/CMakeLists.txt index a9ce330e5..0dfcade4c 100644 --- a/mkrtos_user/server/shell/CMakeLists.txt +++ b/mkrtos_user/server/shell/CMakeLists.txt @@ -16,7 +16,7 @@ target_link_libraries(sh.elf sys sys_util sys_svr - # mr + proc LetterShell --no-whole-archive ${GCC_LIB_PATH}/libgcc.a @@ -29,6 +29,7 @@ target_include_directories( ${CMAKE_SOURCE_DIR}/mkrtos_user/lib/sys_svr/inc ${CMAKE_SOURCE_DIR}/mkrtos_user/lib/letter-shell/demo/mkrtos ${CMAKE_SOURCE_DIR}/mkrtos_user/lib/letter-shell/src + ${CMAKE_SOURCE_DIR}/mkrtos_user/server/fs/procfs/inc ) set_target_properties(sh.elf PROPERTIES LINK_FLAGS "-T ${CMAKE_CURRENT_LIST_DIR}/${ARCH_NAME}/link.lds ${CORTEX_M_LINK_FLAGS} --gc-section -no-dynamic-linker " @@ -64,5 +65,5 @@ add_dependencies(shell_dump sys_util) add_dependencies(shell_dump sys_svr) # add_dependencies(shell_dump start) # add_dependencies(shell_dump muslc) -add_dependencies(shell_dump LetterShell) +add_dependencies(shell_dump LetterShell proc) \ No newline at end of file diff --git a/mkrtos_user/user/app/binutils-2.33.1/binutils/bfdtest1 b/mkrtos_user/user/app/binutils-2.33.1/binutils/bfdtest1 index 06e2e00c3..ea7b801fd 100755 Binary files a/mkrtos_user/user/app/binutils-2.33.1/binutils/bfdtest1 and b/mkrtos_user/user/app/binutils-2.33.1/binutils/bfdtest1 differ diff --git a/mkrtos_user/user/app/binutils-2.33.1/binutils/bfdtest2 b/mkrtos_user/user/app/binutils-2.33.1/binutils/bfdtest2 index 12da785d4..0a8d1dc81 100755 Binary files a/mkrtos_user/user/app/binutils-2.33.1/binutils/bfdtest2 and b/mkrtos_user/user/app/binutils-2.33.1/binutils/bfdtest2 differ diff --git a/mkrtos_user/user/app/binutils-2.33.1/binutils/testsuite/gentestdlls b/mkrtos_user/user/app/binutils-2.33.1/binutils/testsuite/gentestdlls index bed287555..c4d820dfc 100755 Binary files a/mkrtos_user/user/app/binutils-2.33.1/binutils/testsuite/gentestdlls and b/mkrtos_user/user/app/binutils-2.33.1/binutils/testsuite/gentestdlls differ