Browse Source

bugfix: 修复了pipe结构体的内部碎片问题

fslongjin 2 years ago
parent
commit
c80f572db7
2 changed files with 87 additions and 61 deletions
  1. 16 4
      kernel/filesystem/VFS/VFS.h
  2. 71 57
      kernel/ipc/pipe.c

+ 16 - 4
kernel/filesystem/VFS/VFS.h

@@ -34,7 +34,7 @@ extern struct vfs_superblock_t *vfs_root_sb;
 #define VFS_IF_FILE (1UL << 0)
 #define VFS_IF_DIR (1UL << 1)
 #define VFS_IF_DEVICE (1UL << 2)
-#define VFS_IF_DEAD (1UL<<3) /* removed, but still open directory */
+#define VFS_IF_DEAD (1UL << 3) /* removed, but still open directory */
 
 struct vfs_super_block_operations_t;
 struct vfs_inode_operations_t;
@@ -42,7 +42,7 @@ struct vfs_inode_operations_t;
 struct vfs_index_node_t;
 struct vfs_dir_entry_operations_t;
 
-#define VFS_DF_MOUNTED (1 << 0) // 当前dentry是一个挂载点
+#define VFS_DF_MOUNTED (1 << 0)      // 当前dentry是一个挂载点
 #define VFS_DF_CANNOT_MOUNT (1 << 1) // 当前dentry是一个挂载点
 struct vfs_dir_entry_t
 {
@@ -84,6 +84,18 @@ struct vfs_index_node_t
     void *private_inode_info;
 };
 
+/**
+ * @brief 文件的mode
+ *
+ */
+#define VFS_FILE_MODE_READ (1 << 0)
+#define VFS_FILE_MODE_WRITE (1 << 1)
+#define VFS_FILE_MODE_RW (VFS_FILE_MODE_READ | VFS_FILE_MODE_WRITE)
+
+#define vfs_file_can_read(file) (((file)->mode) & VFS_FILE_MODE_READ)
+#define vfs_file_can_write(file) (((file)->mode) & VFS_FILE_MODE_WRITE)
+#define vfs_file_can_rw(file) ((((file)->mode) & VFS_FILE_MODE_RW) == VFS_FILE_MODE_RW)
+
 /**
  * @brief 文件描述符
  *
@@ -223,10 +235,10 @@ struct vfs_dir_entry_t *vfs_alloc_dentry(const int name_size);
 
 /**
  * @brief 分配inode并将引用计数初始化为1
- * 
+ *
  * @return struct vfs_index_node_t * 分配得到的inode
  */
-struct vfs_index_node_t * vfs_alloc_inode();
+struct vfs_index_node_t *vfs_alloc_inode();
 
 /**
  * @brief 打开文件

+ 71 - 57
kernel/ipc/pipe.c

@@ -7,16 +7,24 @@
 #include <common/atomic.h>
 #include <mm/slab.h>
 
-#define MAX_PIPE_BUFF_SIZE  512
-
-struct pipe_t {
+struct pipe_data_t
+{
     volatile unsigned int valid_cnt;
     unsigned int read_pos;
     unsigned int write_pos;
     wait_queue_node_t read_wait_queue;
     wait_queue_node_t write_wait_queue;
-    char buf[MAX_PIPE_BUFF_SIZE];
     spinlock_t lock;
+} __attribute__((packed));
+
+// 由于kmalloc分配的内存是按照2^n对齐的,因此我们需要这样来确定pipe的buffer大小以消除内部碎片
+// 我们设定pipe的总大小为1024字节
+#define PIPE_BUFF_SIZE (1024 - sizeof(struct pipe_data_t))
+
+struct pipe_t
+{
+    struct pipe_data_t data;
+    char buf[PIPE_BUFF_SIZE];
 };
 
 long pipe_read(struct vfs_file_t *file_ptr, char *buf,
@@ -27,24 +35,27 @@ long pipe_read(struct vfs_file_t *file_ptr, char *buf,
 
     kdebug("pipe_read into!\n");
     pipe_ptr = (struct pipe_t *)file_ptr->private_data;
-    spin_lock(&pipe_ptr->lock);
-    while (pipe_ptr->valid_cnt == 0) {
+    spin_lock(&pipe_ptr->data.lock);
+    while (pipe_ptr->data.valid_cnt == 0)
+    {
         /* pipe 空 */
         kdebug("pipe_read empty!\n");
-        wait_queue_wakeup(&pipe_ptr->write_wait_queue, PROC_UNINTERRUPTIBLE);
-        wait_queue_sleep_on_unlock(&pipe_ptr->read_wait_queue, (void *)&pipe_ptr->lock);
-        spin_lock(&pipe_ptr->lock);
+        wait_queue_wakeup(&pipe_ptr->data.write_wait_queue, PROC_UNINTERRUPTIBLE);
+        wait_queue_sleep_on_unlock(&pipe_ptr->data.read_wait_queue, (void *)&pipe_ptr->data.lock);
+        spin_lock(&pipe_ptr->data.lock);
     }
-    for (i = 0; i < pipe_ptr->valid_cnt; i++) {
-        if (i == count) {
+    for (i = 0; i < pipe_ptr->data.valid_cnt; i++)
+    {
+        if (i == count)
+        {
             break;
         }
-        copy_to_user(buf + i, &pipe_ptr->buf[pipe_ptr->read_pos], sizeof(char));
-        pipe_ptr->read_pos = (pipe_ptr->read_pos + 1) % MAX_PIPE_BUFF_SIZE;
+        copy_to_user(buf + i, &pipe_ptr->buf[pipe_ptr->data.read_pos], sizeof(char));
+        pipe_ptr->data.read_pos = (pipe_ptr->data.read_pos + 1) % PIPE_BUFF_SIZE;
     }
-    pipe_ptr->valid_cnt = pipe_ptr->valid_cnt - i;
-    spin_unlock(&pipe_ptr->lock);
-    wait_queue_wakeup(&pipe_ptr->write_wait_queue, PROC_UNINTERRUPTIBLE);
+    pipe_ptr->data.valid_cnt = pipe_ptr->data.valid_cnt - i;
+    spin_unlock(&pipe_ptr->data.lock);
+    wait_queue_wakeup(&pipe_ptr->data.write_wait_queue, PROC_UNINTERRUPTIBLE);
     kdebug("pipe_read end!\n");
 
     return i;
@@ -57,24 +68,27 @@ long pipe_write(struct vfs_file_t *file_ptr, char *buf,
 
     kdebug("pipe_write into!\n");
     pipe_ptr = (struct pipe_t *)file_ptr->private_data;
-    spin_lock(&pipe_ptr->lock);
-    while (pipe_ptr->valid_cnt + count >= MAX_PIPE_BUFF_SIZE) {
+    spin_lock(&pipe_ptr->data.lock);
+    while (pipe_ptr->data.valid_cnt + count >= PIPE_BUFF_SIZE)
+    {
         /* pipe 满 */
         kdebug("pipe_write pipe full!\n");
-        wait_queue_wakeup(&pipe_ptr->read_wait_queue, PROC_UNINTERRUPTIBLE);
-        wait_queue_sleep_on_unlock(&pipe_ptr->write_wait_queue, (void *)&pipe_ptr->lock);
-        spin_lock(&pipe_ptr->lock);
+        wait_queue_wakeup(&pipe_ptr->data.read_wait_queue, PROC_UNINTERRUPTIBLE);
+        wait_queue_sleep_on_unlock(&pipe_ptr->data.write_wait_queue, (void *)&pipe_ptr->data.lock);
+        spin_lock(&pipe_ptr->data.lock);
     }
-    for (i = pipe_ptr->valid_cnt; i < MAX_PIPE_BUFF_SIZE; i++) {
-        if (i - pipe_ptr->valid_cnt == count) {
+    for (i = pipe_ptr->data.valid_cnt; i < PIPE_BUFF_SIZE; i++)
+    {
+        if (i - pipe_ptr->data.valid_cnt == count)
+        {
             break;
         }
-        copy_from_user(&pipe_ptr->buf[pipe_ptr->write_pos], buf + i, sizeof(char));
-        pipe_ptr->write_pos = (pipe_ptr->write_pos + 1) % MAX_PIPE_BUFF_SIZE;
+        copy_from_user(&pipe_ptr->buf[pipe_ptr->data.write_pos], buf + i, sizeof(char));
+        pipe_ptr->data.write_pos = (pipe_ptr->data.write_pos + 1) % PIPE_BUFF_SIZE;
     }
-    pipe_ptr->valid_cnt += count;
-    spin_unlock(&pipe_ptr->lock);
-    wait_queue_wakeup(&pipe_ptr->read_wait_queue, PROC_UNINTERRUPTIBLE);
+    pipe_ptr->data.valid_cnt += count;
+    spin_unlock(&pipe_ptr->data.lock);
+    wait_queue_wakeup(&pipe_ptr->data.read_wait_queue, PROC_UNINTERRUPTIBLE);
     kdebug("pipe_write out!\n");
 
     return count;
@@ -86,27 +100,27 @@ long pipe_close(struct vfs_index_node_t *inode, struct vfs_file_t *file_ptr)
 }
 
 struct vfs_file_operations_t g_pipe_file_ops = {
-    .open       = NULL,
-    .close      = pipe_close,
-    .read       = pipe_read,
-    .write      = pipe_write,
-    .lseek      = NULL,
-    .ioctl      = NULL,
-    .readdir    = NULL,
+    .open = NULL,
+    .close = pipe_close,
+    .read = pipe_read,
+    .write = pipe_write,
+    .lseek = NULL,
+    .ioctl = NULL,
+    .readdir = NULL,
 };
 
 static struct pipe_t *pipe_alloc()
 {
     struct pipe_t *pipe_ptr = NULL;
-    
-    pipe_ptr = (struct pipe_t *)kmalloc(sizeof(struct pipe_t), 0);
-    spin_init(&pipe_ptr->lock);
-    pipe_ptr->read_pos  = 0;
-    pipe_ptr->write_pos = 0;
-    pipe_ptr->valid_cnt = 0;
-    memset(pipe_ptr->buf, 0, MAX_PIPE_BUFF_SIZE);
-    wait_queue_init(&pipe_ptr->read_wait_queue, NULL);
-    wait_queue_init(&pipe_ptr->write_wait_queue, NULL);
+
+    pipe_ptr = (struct pipe_t *)kzalloc(sizeof(struct pipe_t), 0);
+    spin_init(&pipe_ptr->data.lock);
+    pipe_ptr->data.read_pos = 0;
+    pipe_ptr->data.write_pos = 0;
+    pipe_ptr->data.valid_cnt = 0;
+    memset(pipe_ptr->buf, 0, PIPE_BUFF_SIZE);
+    wait_queue_init(&pipe_ptr->data.read_wait_queue, NULL);
+    wait_queue_init(&pipe_ptr->data.write_wait_queue, NULL);
 
     return pipe_ptr;
 }
@@ -116,7 +130,7 @@ static struct pipe_t *pipe_alloc()
  *
  * @param fd(r8) 文件句柄指针
  * @param num(r9) 文件句柄个数
- * @return uint64_t 
+ * @return uint64_t
  */
 uint64_t sys_pipe(struct pt_regs *regs)
 {
@@ -130,19 +144,19 @@ uint64_t sys_pipe(struct pt_regs *regs)
     /* step1 申请pipe结构体、初始化 */
     pipe_ptr = pipe_alloc();
     /* step2 申请2个fd文件句柄,1个作为读端、1个作为写端 */
-    read_file = (struct vfs_file_t *)kmalloc(sizeof(struct vfs_file_t), 0);
-    memset(read_file, 0, sizeof(struct vfs_file_t));
+    read_file = (struct vfs_file_t *)kzalloc(sizeof(struct vfs_file_t), 0);
     fd[0] = process_fd_alloc(read_file);
-    if (fd[0] == -1) {
+    if (fd[0] == -1)
+    {
         kdebug("pipe alloc read fd fail!\n");
         kfree(pipe_ptr);
         kfree(read_file);
         return -1;
     }
-    write_file = (struct vfs_file_t *)kmalloc(sizeof(struct vfs_file_t), 0);
-    memset(write_file, 0, sizeof(struct vfs_file_t));
+    write_file = (struct vfs_file_t *)kzalloc(sizeof(struct vfs_file_t), 0);
     fd[1] = process_fd_alloc(write_file);
-    if (fd[1] == -1) {
+    if (fd[1] == -1)
+    {
         kdebug("pipe alloc write fd fail!\n");
         kfree(pipe_ptr);
         kfree(read_file);
@@ -150,12 +164,12 @@ uint64_t sys_pipe(struct pt_regs *regs)
         return -1;
     }
     /* step3 绑定pipe和file */
-    read_file->private_data     = (void *)pipe_ptr;
-    read_file->file_ops         = &g_pipe_file_ops;
-    read_file->mode             = ATTR_READ_ONLY;
-    write_file->private_data    = (void *)pipe_ptr;
-    write_file->file_ops        = &g_pipe_file_ops;
-    write_file->mode            = O_WRONLY;
+    read_file->private_data = (void *)pipe_ptr;
+    read_file->file_ops = &g_pipe_file_ops;
+    read_file->mode = VFS_FILE_MODE_READ;
+    write_file->private_data = (void *)pipe_ptr;
+    write_file->file_ops = &g_pipe_file_ops;
+    write_file->mode = VFS_FILE_MODE_WRITE;
     kdebug("pipe creat end!\n");
 
     return 0;