From 27a97abd2474b03ad09b562e5ed11e1fdae8eb32 Mon Sep 17 00:00:00 2001 From: DaJiYuQia <88259094+DaJiYuQia@users.noreply.github.com> Date: Sat, 26 Nov 2022 17:34:00 +0800 Subject: [PATCH] Patch procf (#90) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 1234 * 123 * 合并master * procfs * 1 * procfs展示进程基本信息 * modified code * 恢复权限 * 恢复权限 #恢复权限 * modify permission * 删除run.sh * 解决第一次编译时磁盘镜像权限错误的问题 * 恢复.vscode/c_cpp_properties.json * 删除process.c中错误的do_fork * remake procfs * 修改一些变量名 * 修改类型 * modified * data_puts缓冲区溢出后return Co-authored-by: longjin --- .vscode/settings.json | 9 +- kernel/src/common/glib.h | 19 +- kernel/src/common/list.h | 1 + kernel/src/common/string.h | 11 +- kernel/src/filesystem/Makefile | 2 +- kernel/src/filesystem/VFS/VFS.c | 48 ++- kernel/src/filesystem/VFS/VFS.h | 15 +- kernel/src/filesystem/procfs/Makefile | 17 + kernel/src/filesystem/procfs/procfs.c | 497 ++++++++++++++++++++++++++ kernel/src/filesystem/procfs/procfs.h | 43 +++ kernel/src/filesystem/rootfs/rootfs.c | 4 + kernel/src/libs/string.c | 12 + kernel/src/main.c | 3 + kernel/src/process/fork.c | 4 + kernel/src/process/process.c | 1 + kernel/src/syscall/syscall.c | 16 +- tools/create_hdd_image.sh | 1 + tools/write_disk_image.sh | 5 +- user/apps/shell/cmd.c | 1 - 19 files changed, 664 insertions(+), 45 deletions(-) create mode 100644 kernel/src/filesystem/procfs/Makefile create mode 100644 kernel/src/filesystem/procfs/procfs.c create mode 100644 kernel/src/filesystem/procfs/procfs.h diff --git a/.vscode/settings.json b/.vscode/settings.json index f20a1c31..61c890ec 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -148,13 +148,18 @@ "timer.h": "c", "hid.h": "c", "cfs.h": "c", + "proc.h": "c", + "compiler.h": "c", + "hpet.h": "c", + "numa.h": "c", + "procfs.h": "c", "err.h": "c", "rtc.h": "c", "list.h": "c", - "compiler.h": "c", "completion.h": "c", "fat32.h": "c", - "irqflags.h": "c" + "irqflags.h": "c", + "dirent.h": "c" }, "C_Cpp.errorSquiggles": "Enabled", "esbonio.sphinx.confDir": "", diff --git a/kernel/src/common/glib.h b/kernel/src/common/glib.h index 8bed13d6..661abeaf 100644 --- a/kernel/src/common/glib.h +++ b/kernel/src/common/glib.h @@ -253,14 +253,17 @@ static inline uint64_t copy_to_user(void *dst, void *src, uint64_t size) * @brief 先每次搬运8 bytes,剩余就直接一个个byte搬运 * */ - asm volatile("rep \n\t" - "movsq \n\t" - "movq %3, %0 \n\t" - "rep \n\t" - "movsb \n\t" - : "=&c"(size), "=&D"(tmp0), "=&S"(tmp1) - : "r"(size & 7), "0"(size >> 3), "1"(dst), "2"(src) - : "memory"); + // todo:编译有bug + // asm volatile("rep \n\t" + // "movsq \n\t" + // "movq %3, %0 \n\t" + // "rep \n\t" + // "movsb \n\t" + // : "=&c"(size), "=&D"(tmp0), "=&S"(tmp1) + // : "r"(size & 7), "0"(size >> 3), "1"(dst), "2"(src) + // : "memory"); + memcpy(dst,src,size); + return size; } diff --git a/kernel/src/common/list.h b/kernel/src/common/list.h index aad36543..db02ab6c 100644 --- a/kernel/src/common/list.h +++ b/kernel/src/common/list.h @@ -2,6 +2,7 @@ #include #include +#include //链表数据结构 struct List diff --git a/kernel/src/common/string.h b/kernel/src/common/string.h index b2417c2e..899367b2 100644 --- a/kernel/src/common/string.h +++ b/kernel/src/common/string.h @@ -75,4 +75,13 @@ static inline int memcmp(const void *s1, const void *s2, size_t len) diff = *(const unsigned char *)(s1 - 1) - *(const unsigned char *)(s2 - 1); return diff; -} \ No newline at end of file +} + +/** + * @brief 拼接两个字符串(将src接到dest末尾) + * + * @param dest 目标串 + * @param src 源串 + * @return char* + */ +char *strcat(char *dest, const char *src); \ No newline at end of file diff --git a/kernel/src/filesystem/Makefile b/kernel/src/filesystem/Makefile index 4f50c9f3..67f16d43 100644 --- a/kernel/src/filesystem/Makefile +++ b/kernel/src/filesystem/Makefile @@ -3,7 +3,7 @@ CFLAGS += -I . kernel_fs_objs:= $(shell find ./*.c) -kernel_fs_subdirs:= devfs VFS fat32 rootfs +kernel_fs_subdirs:= devfs VFS fat32 rootfs procfs ECHO: @echo "$@" diff --git a/kernel/src/filesystem/VFS/VFS.c b/kernel/src/filesystem/VFS/VFS.c index 5874fcfe..1a449f41 100644 --- a/kernel/src/filesystem/VFS/VFS.c +++ b/kernel/src/filesystem/VFS/VFS.c @@ -173,7 +173,7 @@ struct vfs_dir_entry_t *vfs_path_walk(const char *path, uint64_t flags) memcpy(dentry->name, (void *)tmp_path, tmp_path_len); dentry->name[tmp_path_len] = '\0'; - // kdebug("tmp_path_len=%d, dentry->name= %s", tmp_path_len, dentry->name); + // kdebug("tmp_path_len=%d, dentry->name=%s", tmp_path_len, dentry->name); dentry->name_length = tmp_path_len; if (parent->dir_inode->inode_ops->lookup(parent->dir_inode, dentry) == NULL) @@ -370,11 +370,16 @@ uint64_t sys_mkdir(struct pt_regs *regs) * * @param filename 文件路径 * @param flags 标志位 + * @param from_user 是否由用户态调用,1为是,0为否 * @return uint64_t 错误码 */ -uint64_t do_open(const char *filename, int flags) +uint64_t do_open(const char *filename, int flags, bool from_user) { - long path_len = strnlen_user(filename, PAGE_4K_SIZE) + 1; + long path_len = 0; + if (from_user) + path_len = strnlen_user(filename, PAGE_4K_SIZE) + 1; + else + path_len = strnlen(filename, PAGE_4K_SIZE) + 1; if (path_len <= 0) // 地址空间错误 return -EFAULT; @@ -385,8 +390,12 @@ uint64_t do_open(const char *filename, int flags) char *path = (char *)kzalloc(path_len, 0); if (path == NULL) return -ENOMEM; - - strncpy_from_user(path, filename, path_len); + + if (from_user) + strncpy_from_user(path, filename, path_len); + else + strncpy(path, filename, path_len); + // 去除末尾的 '/' if (path_len >= 2 && path[path_len - 2] == '/') { @@ -430,7 +439,7 @@ uint64_t do_open(const char *filename, int flags) dentry = vfs_alloc_dentry(path_len - tmp_index); dentry->name_length = path_len - tmp_index - 2; - + // kdebug("to create new file:%s namelen=%d", dentry->name, dentry->name_length); strncpy(dentry->name, path + tmp_index + 1, dentry->name_length); dentry->parent = parent_dentry; @@ -527,10 +536,33 @@ uint64_t sys_open(struct pt_regs *regs) { char *filename = (char *)(regs->r8); int flags = (int)(regs->r9); - - return do_open(filename, flags); + return do_open(filename, flags, true); } +/** + * @brief 关闭文件 + * + * @param fd_num 文件描述符 + * @return uint64_t 错误码 + */ +uint64_t vfs_close(int fd_num) +{ + // 校验文件描述符范围 + if (fd_num < 0 || fd_num > PROC_MAX_FD_NUM) + return -EBADF; + // 文件描述符不存在 + if (current_pcb->fds[fd_num] == NULL) + return -EBADF; + struct vfs_file_t *file_ptr = current_pcb->fds[fd_num]; + uint64_t ret; + // If there is a valid close function + if (file_ptr->file_ops && file_ptr->file_ops->close) + ret = file_ptr->file_ops->close(file_ptr->dEntry->dir_inode, file_ptr); + + kfree(file_ptr); + current_pcb->fds[fd_num] = NULL; + return 0; +} /** * @brief 动态分配dentry以及路径字符串名称 * diff --git a/kernel/src/filesystem/VFS/VFS.h b/kernel/src/filesystem/VFS/VFS.h index 9be08e42..218737ab 100644 --- a/kernel/src/filesystem/VFS/VFS.h +++ b/kernel/src/filesystem/VFS/VFS.h @@ -157,14 +157,14 @@ struct vfs_inode_operations_t struct vfs_index_node_t *new_inode, struct vfs_dir_entry_t *new_dEntry); long (*getAttr)(struct vfs_dir_entry_t *dEntry, uint64_t *attr); long (*setAttr)(struct vfs_dir_entry_t *dEntry, uint64_t *attr); - + /** * @brief 取消inode和dentry之间的链接关系(删除文件) - * + * * @param inode 要被取消关联关系的目录项的【父目录项】 * @param dentry 要被取消关联关系的子目录项 */ - long (*unlink)(struct vfs_index_node_t * inode, struct vfs_dir_entry_t * dentry); + long (*unlink)(struct vfs_index_node_t *inode, struct vfs_dir_entry_t *dentry); }; struct vfs_dir_entry_operations_t @@ -249,14 +249,15 @@ struct vfs_dir_entry_t *vfs_alloc_dentry(const int name_size); */ struct vfs_index_node_t *vfs_alloc_inode(); +uint64_t do_open(const char *filename, int flags, bool from_user); + /** - * @brief 打开文件 + * @brief 关闭文件 * - * @param filename 文件路径 - * @param flags 标志位 + * @param fd_num 文件描述符 * @return uint64_t 错误码 */ -uint64_t do_open(const char *filename, int flags); +uint64_t vfs_close(int fd_num); /** * @brief 创建文件夹 diff --git a/kernel/src/filesystem/procfs/Makefile b/kernel/src/filesystem/procfs/Makefile new file mode 100644 index 00000000..1236dd66 --- /dev/null +++ b/kernel/src/filesystem/procfs/Makefile @@ -0,0 +1,17 @@ + +CFLAGS += -I . + + +kernel_fs_procfs_objs:= $(shell find ./*.c) + + +ECHO: + @echo "$@" + + +$(kernel_fs_procfs_objs): ECHO + $(CC) $(CFLAGS) -c $@ -o $@.o + + +all: $(kernel_fs_procfs_objs) + diff --git a/kernel/src/filesystem/procfs/procfs.c b/kernel/src/filesystem/procfs/procfs.c new file mode 100644 index 00000000..61ea349c --- /dev/null +++ b/kernel/src/filesystem/procfs/procfs.c @@ -0,0 +1,497 @@ +#include "procfs.h" + +//定义文件类型 +#define PROC_STATUS 1 + +//定义buffer大小 +#define FDATA_RBUF_SIZE 1024 + +struct vfs_super_block_operations_t procfs_sb_ops; +struct vfs_dir_entry_operations_t procfs_dentry_ops; +struct vfs_file_operations_t procfs_file_ops; +struct vfs_inode_operations_t procfs_inode_ops; + +struct vfs_superblock_t procfs_sb = {0}; +struct vfs_dir_entry_t *procfs_root_dentry; // 根结点的dentry +static spinlock_t procfs_global_lock; // procfs的全局锁 +const char __procfs_mount_path[] = "/proc"; // 挂在路径 + +static int64_t proc_create_file(const char *path, mode_t type, long pid); +static int __check_name_available(const char *name, int namelen, int8_t reserved); +static long simple_procfs_read(void *to, int64_t count, long *position, void *from, int64_t available); + +/** + * @brief 文件的私有信息结构 + * + */ +struct procfs_file_private_data +{ + int readlen; + char *rbuffer; + int writelen; + char *wbuffer; +}; + +/** + * @brief 创建procfs的super block + * + * @param blk 未使用(procfs为伪文件系统,不需要物理设备) + * @return struct vfs_superblock_t* + */ +struct vfs_superblock_t *procfs_read_superblock(struct block_device *blk) +{ + procfs_sb.blk_device = NULL; + procfs_sb.root = procfs_root_dentry; + procfs_sb.sb_ops = &procfs_sb_ops; + procfs_sb.dir_ops = &procfs_dentry_ops; + procfs_sb.private_sb_info = NULL; + kdebug("procfs read superblock done"); + return &procfs_sb; +} + +static void procfs_write_superblock(struct vfs_superblock_t *sb) +{ + return; +} +static void procfs_put_superblock(struct vfs_superblock_t *sb) +{ + return; +} +static void procfs_write_inode(struct vfs_index_node_t *inode) +{ + return; +} +struct vfs_super_block_operations_t procfs_sb_ops = { + .write_superblock = &procfs_write_superblock, + .put_superblock = &procfs_put_superblock, + .write_inode = &procfs_write_inode, +}; + +static long procfs_compare(struct vfs_dir_entry_t *parent_dEntry, char *source_filename, char *dest_filename) +{ + return 0; +} +static long procfs_hash(struct vfs_dir_entry_t *dEntry, char *filename) +{ + return 0; +} +static long procfs_release(struct vfs_dir_entry_t *dEntry) +{ + return 0; +} +static long procfs_iput(struct vfs_dir_entry_t *dEntry, struct vfs_index_node_t *inode) +{ + return 0; +} +struct vfs_dir_entry_operations_t procfs_dentry_ops = { + .compare = &procfs_compare, + .hash = &procfs_hash, + .release = &procfs_release, + .iput = &procfs_iput, +}; + +void data_puts(struct procfs_file_private_data *fdata, const char *s) +{ + int len = strlen(s); + if(fdata->readlen+len > FDATA_RBUF_SIZE) + { + kerror("out of buffer"); + return; + } + strncpy(fdata->rbuffer + fdata->readlen, s, len); + fdata->readlen += len; +} + +static long procfs_open(struct vfs_index_node_t *inode, struct vfs_file_t *file_ptr) +{ + if (inode->attribute & VFS_IF_DIR) + { + return 0; + } + struct procfs_inode_info_t *finode = inode->private_inode_info; + if (finode == NULL) + { + return 0; + } + // kdebug("finode=%#018lx", finode); + struct procfs_file_private_data *fdata = kzalloc(sizeof(struct procfs_file_private_data), 0); + struct process_control_block *pcb_t = process_find_pcb_by_pid(finode->pid); + //判断文件类型 + int mode = finode->type; + fdata->rbuffer = kzalloc(FDATA_RBUF_SIZE, 0); + int len = 0; + switch (mode) + { + case 1: + data_puts(fdata, "Name:"); + data_puts(fdata, pcb_t->name); + data_puts(fdata, "\nstate:"); + data_puts(fdata, ltoa(pcb_t->state)); + data_puts(fdata, "\npid:"); + data_puts(fdata, ltoa(pcb_t->pid)); + data_puts(fdata, "\nPpid:"); + data_puts(fdata, ltoa(pcb_t->parent_pcb->pid)); + data_puts(fdata, "\ncpu_id:"); + data_puts(fdata, ltoa(pcb_t->cpu_id)); + data_puts(fdata, "\npriority:"); + data_puts(fdata, ltoa(pcb_t->priority)); + // data_puts(fdata,"\n"); + + uint64_t hiwater_vm, text, data; + hiwater_vm = pcb_t->mm->vmas->vm_end - pcb_t->mm->vmas->vm_start; + text = pcb_t->mm->code_addr_end - pcb_t->mm->code_addr_start; + data = pcb_t->mm->data_addr_end - pcb_t->mm->data_addr_start; + + data_puts(fdata, "\nVmPeak:"); + data_puts(fdata, ltoa(hiwater_vm)); + data_puts(fdata, " kB"); + data_puts(fdata, "\nVmData:"); + data_puts(fdata, ltoa(data)); + data_puts(fdata, " kB"); + data_puts(fdata, "\nVmExe:"); + data_puts(fdata, ltoa(text)); + data_puts(fdata, " kB\n"); + + break; + + default: + break; + } + + inode->file_size = fdata->readlen; + file_ptr->private_data = fdata; + return 0; +} +static long procfs_close(struct vfs_index_node_t *inode, struct vfs_file_t *file_ptr) +{ + return 0; +} +static long procfs_read(struct vfs_file_t *file_ptr, char *buf, int64_t count, long *position) +{ + // 获取私有信息 + struct procfs_file_private_data *priv = (struct procfs_file_private_data *)file_ptr->private_data; + // kdebug("priv=%#018lx", priv); + if (!priv->rbuffer) + return -EINVAL; + + return simple_procfs_read(buf, count, position, priv->rbuffer, priv->readlen); +} + +/** + * @brief 检查读取并将数据从内核拷贝到用户 + * + * @param to: 要读取的用户空间缓冲区 + * @param count: 要读取的最大字节数 + * @param position: 缓冲区中的当前位置 + * @param from: 要读取的缓冲区 + * @param available: 读取的缓冲区大小 + * + * @return long 读取字节数 + */ +static long simple_procfs_read(void *to, int64_t count, long *position, void *from, int64_t available) +{ + long pos = *position; + // kdebug("pos:%ld",pos); + // kdebug("count:%ld",count); + // kdebug("available:%ld",available); + int64_t ret = 0; + + if (pos < 0) + return -EINVAL; + if (pos >= available || !count) + return 0; + if (count > available - pos) + count = available - pos; + // kdebug("count:%d",count); + ret = copy_to_user(to, from + pos, count); + + *position = pos + ret; + return ret; +} + +static long procfs_write(struct vfs_file_t *file_ptr, char *buf, int64_t count, long *position) +{ + return 0; +} +/** + * @brief 调整文件的访问位置 + * + * @param file_ptr 文件描述符号 + * @param offset 偏移量 + * @param whence 调整模式 + * @return uint64_t 调整结束后的文件访问位置 + */ +static long procfs_lseek(struct vfs_file_t *file_ptr, long offset, long whence) +{ + struct vfs_index_node_t *inode = file_ptr->dEntry->dir_inode; + + long pos = 0; + switch (whence) + { + case SEEK_SET: // 相对于文件头 + pos = offset; + break; + case SEEK_CUR: // 相对于当前位置 + pos = file_ptr->position + offset; + break; + case SEEK_END: // 相对于文件末尾 + pos = file_ptr->dEntry->dir_inode->file_size + offset; + break; + + default: + return -EINVAL; + break; + } + + if (pos < 0 || pos > file_ptr->dEntry->dir_inode->file_size) + return -EOVERFLOW; + file_ptr->position = pos; + + return pos; +} +static long procfs_ioctl(struct vfs_index_node_t *inode, struct vfs_file_t *file_ptr, uint64_t cmd, uint64_t arg) +{ + return 0; +} + +/** + * @brief 读取该目录下的目录项 + * + * @param file_ptr 文件结构体的指针 + * @param dirent 返回的dirent + * @param filler 填充dirent的函数 + * + * @return long 错误码 + */ +static long procfs_readdir(struct vfs_file_t *file_ptr, void *dirent, vfs_filldir_t filler) +{ + struct vfs_dir_entry_t *dentry = file_ptr->dEntry; + struct List *list = &dentry->subdirs_list; + // 先切换到position处 + for (int i = 0; i <= file_ptr->position; ++i) + { + list = list_next(list); + if (list == &dentry->subdirs_list) // 找完了 + goto failed; + } + + // 若存在目录项,则增加偏移量 + ++file_ptr->position; + // 获取目标dentry(由于是子目录项,因此是child_node_list) + struct vfs_dir_entry_t *target_dent = container_of(list, struct vfs_dir_entry_t, child_node_list); + + char *name = (char *)kzalloc(target_dent->name_length + 1, 0); + strncpy(name, target_dent->name, target_dent->name_length); + uint32_t dentry_type; + if (target_dent->dir_inode->attribute & VFS_IF_DIR) + dentry_type = VFS_IF_DIR; + + return filler(dirent, file_ptr->position - 1, name, target_dent->name_length, dentry_type, file_ptr->position - 1); +failed:; + return 0; +} + +struct vfs_file_operations_t procfs_file_ops = { + .open = &procfs_open, + .close = &procfs_close, + .read = &procfs_read, + .write = &procfs_write, + .lseek = &procfs_lseek, + .ioctl = &procfs_ioctl, + .readdir = &procfs_readdir, +}; + +/** + * @brief 检查文件名是否合法 + * + * @param name 文件名 + * @param namelen 文件名长度 + * @param reserved 保留字段 + * @return int 合法:0, 其他:错误码 + */ +static int __check_name_available(const char *name, int namelen, int8_t reserved) +{ + if (namelen > 255 || namelen <= 0) + return -ENAMETOOLONG; + // 首个字符不能是空格或者'.' + if (name[0] == 0x20 || name[0] == '.') + return -EINVAL; + + return 0; +}; + +/** + * @brief 在procfs中创建文件 + * + * @param parent_inode 父目录的inode + * @param dest_dEntry 目标dentry + * @param mode 创建模式 + * @return long 错误码 + */ +static long procfs_create(struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_t *dest_dEntry, int mode) +{ + int64_t retval = 0; + + //检验名称和法性 + retval = __check_name_available(dest_dEntry->name, dest_dEntry->name_length, 0); + if (retval != 0) + return retval; + if (dest_dEntry->dir_inode != NULL) + return -EEXIST; + + struct vfs_index_node_t *inode = vfs_alloc_inode(); + dest_dEntry->dir_inode = inode; + dest_dEntry->dir_ops = &procfs_dentry_ops; + + inode->attribute = VFS_IF_FILE; + inode->file_ops = &procfs_file_ops; + inode->file_size = 0; + inode->sb = parent_inode->sb; + inode->inode_ops = &procfs_inode_ops; + // kdebug("finode:%#018lx",inode->private_inode_info); + inode->blocks = 0; + + return 0; +} +static struct vfs_dir_entry_t *procfs_lookup(struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_t *dest_dEntry) +{ + return NULL; +} + +/** + * @brief 在procfs中创建文件夹(作用是完善子文件夹的inode信息) + * + * @param inode 父目录的inode + * @param dEntry 目标dentry + * @param mode 创建模式 + * @return long 错误码 + */ +static long procfs_mkdir(struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_t *dEntry, int mode) +{ + int64_t retval = 0; + + //检验名称和法性 + retval = __check_name_available(dEntry->name, dEntry->name_length, 0); + if (retval != 0) + return retval; + + struct vfs_index_node_t *inode = vfs_alloc_inode(); + dEntry->dir_inode = inode; + dEntry->dir_ops = &procfs_dentry_ops; + + //结点信息初始化 + struct procfs_inode_info_t *finode = (struct procfs_inode_info_t *)kzalloc(sizeof(struct procfs_inode_info_t), 0); + finode->pid = 0; + finode->type = 0; + + inode->attribute = VFS_IF_DIR; + inode->file_ops = &procfs_file_ops; + inode->file_size = 0; + inode->sb = parent_inode->sb; + inode->inode_ops = &procfs_inode_ops; + inode->private_inode_info = (void *)finode; + // kdebug("inode->private_inode_info=%#018lx", inode->private_inode_info); + inode->blocks = 0; + + return 0; +} +struct vfs_inode_operations_t procfs_inode_ops = { + .create = &procfs_create, + .lookup = &procfs_lookup, + .mkdir = &procfs_mkdir, +}; + +struct vfs_filesystem_type_t procfs_fs_type = { + .name = "procfs", + .fs_flags = 0, + .read_superblock = procfs_read_superblock, + .next = NULL, +}; + +static __always_inline void __procfs_init_root_inode() +{ + procfs_root_dentry->dir_inode = vfs_alloc_inode(); + procfs_root_dentry->dir_inode->file_ops = &procfs_file_ops; + procfs_root_dentry->dir_inode->inode_ops = &procfs_inode_ops; + + procfs_root_dentry->dir_inode->private_inode_info = NULL; + procfs_root_dentry->dir_inode->sb = &procfs_sb; + procfs_root_dentry->dir_inode->attribute = VFS_IF_DIR; +} +/** + * @brief 初始化procfs的根dentry + */ +static __always_inline void __procfs_init_root_dentry() +{ + procfs_root_dentry = vfs_alloc_dentry(0); + procfs_root_dentry->dir_ops = &procfs_dentry_ops; + + __procfs_init_root_inode(); +} + +/** + * @brief 创建进程对应文件夹 + * + * @param pid 进程号 + * @return int64_t 错误码 + */ +int64_t procfs_register_pid(long pid) +{ + int retval = 0; + + //创建文件夹 + char tmp[70] = {0}; + int len = strlen(ltoa(pid)); + // kdebug("len:%d",len); + strcpy(tmp, "/proc/"); + strcpy(tmp + 6, ltoa(pid)); + // kdebug("tmp:%s",tmp); + retval = vfs_mkdir(tmp, 0, false); + + // kdebug("aaaaaaaaaaaaaaa"); + //创建各相关文件 + strcpy(tmp + 6 + len, "/status"); + // kdebug("tmp:%s",tmp); + retval = proc_create_file(tmp, PROC_STATUS, pid); + + return retval; +} + +/** + * @brief 创建文件 + * + * @param path 文件夹路径 + * @param type 文件类型 + * @param pid pid + * @return int64_t 错误码 + */ +static int64_t proc_create_file(const char *path, mode_t type, long pid) +{ + kdebug("procfs: Creating: %s", path); + int ret = do_open(path, O_CREAT, false); + // kdebug("ret:%d", ret); + struct vfs_dir_entry_t *dentry = vfs_path_walk(path, 0); + // kdebug("dentry=%#018lx", dentry); + + //结点信息配置 + struct procfs_inode_info_t *finode = (struct procfs_inode_info_t *)kzalloc(sizeof(struct procfs_inode_info_t), 0); + finode->pid = pid; + // kdebug("pid:%d",finode->pid); + finode->type = type; + dentry->dir_inode->private_inode_info = (void *)finode; + ret = vfs_close(ret); + + return ret; +} + +/** + * @brief 初始化procfs + * + */ +void procfs_init() +{ + __procfs_init_root_dentry(); + vfs_register_filesystem(&procfs_fs_type); + spin_init(&procfs_global_lock); + vfs_mount_fs(__procfs_mount_path, "procfs", NULL); +} diff --git a/kernel/src/filesystem/procfs/procfs.h b/kernel/src/filesystem/procfs/procfs.h new file mode 100644 index 00000000..51324002 --- /dev/null +++ b/kernel/src/filesystem/procfs/procfs.h @@ -0,0 +1,43 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * @brief 初始化procfs + * + */ +void procfs_init(); + +/** + * @brief proc文件系统的超级块信息结构体 + * + */ +struct procfs_sb_info_t +{ + struct lockref lockref; //该lockref包含自旋锁以及引用计数 +}; + +/** + * @brief procfs文件系统的结点私有信息 + * + */ +struct procfs_inode_info_t +{ + long pid; + int type; +}; + +/** + * @brief 创建进程对应文件 + * + * @param pid 进程号 + * @return int64_t 错误码 + */ +int64_t procfs_register_pid(long pid); diff --git a/kernel/src/filesystem/rootfs/rootfs.c b/kernel/src/filesystem/rootfs/rootfs.c index 54a40f73..bd49baaf 100644 --- a/kernel/src/filesystem/rootfs/rootfs.c +++ b/kernel/src/filesystem/rootfs/rootfs.c @@ -160,6 +160,10 @@ void rootfs_init() // 创建/dev等目录的dentry(以便文件系统的mount) if (rootfs_add_dir("dev") != 0) kerror("create dir 'dev' in rootfs failed"); + + // 创建/procfs目录的dentry + if (rootfs_add_dir("proc") != 0) + kerror("create dir 'proc' in rootfs failed"); } /** diff --git a/kernel/src/libs/string.c b/kernel/src/libs/string.c index 830d8f85..f25b84e3 100644 --- a/kernel/src/libs/string.c +++ b/kernel/src/libs/string.c @@ -107,3 +107,15 @@ long strnlen_user(const char *src, unsigned long maxlen) return size <= maxlen ? size : maxlen; } +/** + * @brief 拼接两个字符串(将src接到dest末尾) + * + * @param dest 目标串 + * @param src 源串 + * @return char* + */ +char *strcat(char *dest, const char *src) +{ + strcpy(dest + strlen(dest), src); + return dest; +} \ No newline at end of file diff --git a/kernel/src/main.c b/kernel/src/main.c index 74aede30..231104d7 100644 --- a/kernel/src/main.c +++ b/kernel/src/main.c @@ -21,6 +21,7 @@ #include #include +#include #include #include "driver/acpi/acpi.h" @@ -142,6 +143,8 @@ void system_initialize() vfs_init(); devfs_init(); + procfs_init(); + cpu_init(); ps2_keyboard_init(); tty_init(); diff --git a/kernel/src/process/fork.c b/kernel/src/process/fork.c index b074bee1..90b01abd 100644 --- a/kernel/src/process/fork.c +++ b/kernel/src/process/fork.c @@ -2,6 +2,7 @@ #include #include #include +#include extern spinlock_t process_global_pid_write_lock; extern long process_global_pid; @@ -135,6 +136,9 @@ unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned // 唤醒进程 process_wakeup(tsk); + //创建对应procfs文件 + procfs_register_pid(tsk->pid); + return retval; copy_thread_failed:; diff --git a/kernel/src/process/process.c b/kernel/src/process/process.c index 2883a746..9eb9b062 100644 --- a/kernel/src/process/process.c +++ b/kernel/src/process/process.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include diff --git a/kernel/src/syscall/syscall.c b/kernel/src/syscall/syscall.c index 5ba420db..c0b07f9b 100644 --- a/kernel/src/syscall/syscall.c +++ b/kernel/src/syscall/syscall.c @@ -135,21 +135,7 @@ uint64_t sys_close(struct pt_regs *regs) int fd_num = (int)regs->r8; // kdebug("sys close: fd=%d", fd_num); - // 校验文件描述符范围 - if (fd_num < 0 || fd_num > PROC_MAX_FD_NUM) - return -EBADF; - // 文件描述符不存在 - if (current_pcb->fds[fd_num] == NULL) - return -EBADF; - struct vfs_file_t *file_ptr = current_pcb->fds[fd_num]; - uint64_t ret; - // If there is a valid close function - if (file_ptr->file_ops && file_ptr->file_ops->close) - ret = file_ptr->file_ops->close(file_ptr->dEntry->dir_inode, file_ptr); - - kfree(file_ptr); - current_pcb->fds[fd_num] = NULL; - return 0; + return vfs_close(fd_num); } /** diff --git a/tools/create_hdd_image.sh b/tools/create_hdd_image.sh index 792b0adb..54f07623 100755 --- a/tools/create_hdd_image.sh +++ b/tools/create_hdd_image.sh @@ -22,4 +22,5 @@ sudo losetup -d ${LOOP_DEVICE} echo "Successfully created disk image." mkdir -p ../bin +chmod 777 disk.img mv ./disk.img ../bin/ diff --git a/tools/write_disk_image.sh b/tools/write_disk_image.sh index cecff432..7da825a9 100644 --- a/tools/write_disk_image.sh +++ b/tools/write_disk_image.sh @@ -23,7 +23,7 @@ bins[0]=${kernel} for file in ${bins[*]};do if [ ! -x $file ]; then echo "$file 不存在!" -exit +exit 1 fi done @@ -43,7 +43,7 @@ fi # 判断是否存在硬盘镜像文件,如果不存在,就创建一个(docker模式下,由于镜像中缺少qemu-img不会创建) if [ ! -f "${root_folder}/bin/disk.img" ]; then echo "创建硬盘镜像文件..." - sudo bash ./create_hdd_image.sh + sudo bash ./create_hdd_image.sh || exit 1 fi mkdir -p ${root_folder}/bin/disk_mount @@ -53,6 +53,7 @@ cp ${kernel} ${root_folder}/bin/disk_mount/boot # 拷贝用户程序到磁盘镜像 mkdir -p ${root_folder}/bin/disk_mount/bin mkdir -p ${root_folder}/bin/disk_mount/dev +mkdir -p ${root_folder}/bin/disk_mount/proc cp -r ${root_folder}/bin/user/* ${root_folder}/bin/disk_mount/bin touch ${root_folder}/bin/disk_mount/dev/keyboard.dev diff --git a/user/apps/shell/cmd.c b/user/apps/shell/cmd.c index cd476ea6..e4065951 100644 --- a/user/apps/shell/cmd.c +++ b/user/apps/shell/cmd.c @@ -312,7 +312,6 @@ int shell_cmd_cat(int argc, char **argv) file_size -= l; printf("%s", buf); } - close(fd); free(buf); free(file_path);