• 操作系统真象还原中文件系统部分的一个实现错误


    file_table是file类型. 如下:

    struct file {
       uint32_t fd_pos;
       uint32_t fd_flag;
       struct inode* fd_inode;
    };
    

    file没有引用计数字段. 实际上应该有引用计数字段. 为什么需要引用计数字段, 这要到实现fork时才有清晰的原因.
    sys_fork调用了fork, fork调用了copy_process, 在copy_process中, 有update_inode_open_cnts, 这个函数干的事情是

    static void update_inode_open_cnts(struct task_struct* thread) {
       int32_t local_fd = 3, global_fd = 0;
       while (local_fd < MAX_FILES_OPEN_PER_PROC) {
          global_fd = thread->fd_table[local_fd];
          ASSERT(global_fd < MAX_FILE_OPEN);
          if (global_fd != -1) {
    	 file_table[global_fd].fd_inode->i_open_cnts++;
          }
          local_fd++;
       }
    }
    

    再看看sys_close的实现

    int32_t sys_close(int32_t fd) {
       int32_t ret = -1;
       if (fd > 2) {
          uint32_t _fd = fd_local2global(fd);
          ret = file_close(&file_table[_fd]);
          running_thread()->fd_table[fd] = -1;
       }
       return ret;
    }
    

    file_close是:

    int32_t file_close(struct file* file) {
       if (file == NULL) {
          return -1;
       }
       file->fd_inode->write_deny = false;
       inode_close(file->fd_inode);
       file->fd_inode = NULL; // 这一行使file_table中的项失效
       return 0;
    }
    

    现在来举出一个场景. 父进程fork出子进程, 子进程sys_close了一个文件, 看看上面的实现, file_table中的项必然失效了. 父进程即时不调用sys_close, 也会失效(因为子进程和父进程共用file_table). 其实书里也是有意识要解决这个问题的, 做的事就是前面列出过的update_inode_open_cnts, 但是那只是inode的引用计数++, 没有用. 我认为inode的引用计数不应该++, 应该在struct file中加上引用计数字段.

  • 相关阅读:
    jq的stop
    mouseover,mouseout与mouseenter,mouseleave
    jq的load
    KeyUp 和KeyDown 、KeyPress之间的区别
    jq的error
    $(function() {....}) ,(function($){...})(jQuery)
    delegate事件委托
    将项目提交到git
    linux下安装jenkins
    手写简单的linkedlist
  • 原文地址:https://www.cnblogs.com/Tokubara/p/15152442.html
Copyright © 2020-2023  润新知