ip route static frr:ramfs文件系统分析

来源:百度文库 编辑:偶看新闻 时间:2024/04/28 23:00:31

ramfs文件系统分析

楼层直达
只看楼主更多操作楼主  发表于: 2007-03-23 RAMFS是一个非常巧妙的,利用VFS自身结构而形成的内存文件系统.
RAMFS没有自已的文件存储结构,它的文件存储于page cache中,
目录结构由dentry链表本身描述,文件则由VFS的inode结构本身描述.
从RAMFS可看出,VFS本质上可看成一种内存文件系统,
它统一了文件在内核中的表示方式并对磁盘文件系统进行缓冲.

代码摘录分析如下:

/* ramfs文件系统类型 */
tatic struct file_system_type ramfs_fs_type = {
   .name        = "ramfs",
   .get_sb        = ramfs_get_sb, 读取超级块接口
   .kill_sb    = kill_litter_super,
};
/* rootfs文件系统(根文件系统) 该模块应该是放到cpio文件*/
static struct file_system_type rootfs_fs_type = {
   .name        = "rootfs",
   .get_sb        = rootfs_get_sb,
   .kill_sb    = kill_litter_super,
};

注册ramfs文件系统
static int __init init_ramfs_fs(void)
{
   return register_filesystem(&ramfs_fs_type);
}

static void __exit exit_ramfs_fs(void)
{
   unregister_filesystem(&ramfs_fs_type);
}

注册rootfs文件系统
int __init init_rootfs(void)
{
   return register_filesystem(&rootfs_fs_type);
}

根文件系统和ramfs文件系统读取超级快是同一接口:
static int ramfs_fill_super(struct super_block * sb, void * data, int silent)
{
   struct inode * inode;
   struct dentry * root;

   sb->s_maxbytes = MAX_LFS_FILESIZE;
   sb->s_blocksize = PAGE_CACHE_SIZE;
   sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
   sb->s_magic = RAMFS_MAGIC;
   sb->s_op = &ramfs_ops;
   sb->s_time_gran = 1;
   inode = ramfs_get_inode(sb, S_IFDIR | 0755, 0);
   if (!inode)
       return -ENOMEM;

   root = d_alloc_root(inode);
   if (!root) {
       iput(inode);
       return -ENOMEM;
   }
   sb->s_root = root;
   return 0;
}

再分配超级快时有一个小小的技巧:
static struct super_block *alloc_super(void)
{
   分配空间
   struct super_block *s = kzalloc(sizeof(struct super_block), GFP_USER);
   静态变量,超级块访问接口
   static struct super_operations default_op;

   if (s) {
       。。。。 //初始化超级块
       
       超级快访问接口,这里用的就是前面的静态变量
       s->s_op = &default_op;
       s->s_time_gran = 1000000000;
   }
out:
   return s;
}

/* ramfs文件系统的文件操作接口 */
static struct inode_operations ramfs_dir_inode_operations = {
   .create        = ramfs_create,
   .lookup        = simple_lookup,
   .link        = simple_link,
   .unlink        = simple_unlink,
   .symlink    = ramfs_symlink,
   .mkdir        = ramfs_mkdir,
   .rmdir        = simple_rmdir,
   .mknod        = ramfs_mknod,
   .rename        = simple_rename,
};
/* ramfs文件系统的目录操作接口 */
static struct super_operations ramfs_ops = {
   .statfs        = simple_statfs,
   .drop_inode    = generic_delete_inode,
};

struct address_space_operations ramfs_aops = { 文件的低级页操作接口
   .readpage    = simple_readpage, 读文件页块
   .prepare_write    = simple_prepare_write, 准备从用户写文件页块
   .commit_write    = simple_commit_write 从用户写文件页块完成
};

int simple_readpage(struct file *file, struct page *page)
{
   void *kaddr;

   将文件页块读入page所描述的页面
   if (PageUptodate(page))
       goto out;

   当lseek()在文件中造成空洞时,会运行到这里
   kaddr = kmap_atomic(page, KM_USER0);
   memset(kaddr, 0, PAGE_CACHE_SIZE);页面清零
   kunmap_atomic(kaddr, KM_USER0);
   flush_dcache_page(page);
   SetPageUptodate(page);标记为最新
out:
   unlock_page(page);
   return 0;
}

int simple_prepare_write(struct file *file, struct page *page,
           unsigned from, unsigned to)
{
   /* 系统将用户数据拷贝到page之前调用此函数,        ;offset是文件指针在页内的起始位置,to是在页内的终止位置    ;表示系统将要在page从offset到to的位置上拷贝用户数据.*/
   if (!PageUptodate(page)) {
       if (to - from != PAGE_CACHE_SIZE) {
       对于RAMFS,当lseek()在文件中产生空洞时,运行到这里
           void *kaddr = kmap_atomic(page, KM_USER0);取页面描述结构(page)所描述页面的地址
           memset(kaddr, 0, from);
           memset(kaddr + to, 0, PAGE_CACHE_SIZE - to);
           flush_dcache_page(page);
           kunmap_atomic(kaddr, KM_USER0);
       }
       SetPageUptodate(page);
   }
   return 0;
}

int simple_commit_write(struct file *file, struct page *page,
           unsigned offset, unsigned to)
{
   系统将用户数据拷贝到page之后调用此函数
   struct inode *inode = page->mapping->host;取page所代表的文件,mapping结构是inode的一部分
   
   page->index表示该page在文件中的页块号,to是该页的终止偏移量
   loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;

   /*
    * No need to use i_size_read() here, the i_size
    * cannot change under us because we hold the i_mutex.
    */
   if (pos > inode->i_size)// inode->i_size为文件的尺寸
       i_size_write(inode, pos);如果文件的写入的终止位置大于文件原来的尺寸,则更新i_size的值
   set_page_dirty(page);
   return 0;
}

const struct file_operations ramfs_file_operations = {
   .read        = generic_file_read,数据文件的通用高级读函数
   .write        = generic_file_write,数据文件的通用高级写函数
   .mmap        = generic_file_mmap,数据文件的通用高级内存映射函数
   .fsync        = simple_sync_file,
   .sendfile    = generic_file_sendfile,
   .llseek        = generic_file_llseek,
};

const struct file_operations simple_dir_operations = {
   .open        = dcache_dir_open,
   .release    = dcache_dir_close,
   .llseek        = dcache_dir_lseek,
   .read        = generic_read_dir,返回-EISDIR错误的函数
   .readdir    = dcache_readdir,目录文件的高级读目录函数
   .fsync        = simple_sync_file,
};

static struct inode_operations ramfs_dir_inode_operations = {
   .create        = ramfs_create,
   .lookup        = simple_lookup,
   .link        = simple_link,
   .unlink        = simple_unlink,
   .symlink    = ramfs_symlink,
   .mkdir        = ramfs_mkdir,
   .rmdir        = simple_rmdir,
   .mknod        = ramfs_mknod,
   .rename        = simple_rename,
};
static int ramfs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd)
{
在目录dir内创建一个以dentry为目录项的普通文件
   return ramfs_mknod(dir, dentry, mode | S_IFREG, 0);
}

static int
ramfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
{
   struct inode * inode = ramfs_get_inode(dir->i_sb, mode, dev);//创建inode
   int error = -ENOSPC;

   if (inode) {
       if (dir->i_mode & S_ISGID) {
           inode->i_gid = dir->i_gid;
           if (S_ISDIR(mode))
               inode->i_mode |= S_ISGID;
       }
       d_instantiate(dentry, inode); //把dentry加入到inode
       dget(dentry);    /* Extra count - pin the dentry in core */
       error = 0;
       dir->i_mtime = dir->i_ctime = CURRENT_TIME;
   }
   return error;
}

struct dentry *simple_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
{
   static struct dentry_operations simple_dentry_operations = {
       .d_delete = simple_delete_dentry,
   };

   对于ramfs,所有的目录项都已经在dentry链表中,只有企图寻找VFS中不存在的项时,才会运行到这/
   
   if (dentry->d_name.len > NAME_MAX)
       return ERR_PTR(-ENAMETOOLONG);
       
   将dentry加入目录链表,置空的inode,表示No such file ordirectories,就是说生成一个"虚"的目录项,    ;之所以这样,为了加速create过程
   dentry->d_op = &simple_dentry_operations;
   d_add(dentry, NULL);
   return NULL;
}

int simple_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
{
   struct inode *inode = old_dentry->d_inode;    
   ; 在目录dir内创建一个以dentry所表示目录项的链接,指向old_entry目录项所表示的文件    
   
   if (S_ISDIR(inode->i_mode))        return -EPERM;    
   
   inode->i_nlink++; 文件的连接数,为0表示文件已删除    
   atomic_inc(&inode->i_count);    /* New dentry reference */    
   dget(dentry);        /* Extra pinning count for the created dentry */    
   d_instantiate(dentry, inode); 使目录项dentry指向文件inode    
   return 0;
}

; 在目录dir内删除dentry所表示的目录项
int simple_unlink(struct inode *dir, struct dentry *dentry)
{
   struct inode *inode = dentry->d_inode;
   
   inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
   inode->i_nlink--;
   dput(dentry); // 根据引用计数来删除目录项
   return 0;
}

static int ramfs_symlink(struct inode * dir, struct dentry *dentry, const char * symname)
{
   struct inode *inode;
   int error = -ENOSPC;

   inode = ramfs_get_inode(dir->i_sb, S_IFLNK|S_IRWXUGO, 0);
   
   ; 在目录dir中创建名称为symname的符号链接文件目录项    ; 符号链接的名称作为符号链接文件的数据体存放在page cache中
   if (inode) {
       int l = strlen(symname)+1;
       error = page_symlink(inode, symname, l);
       if (!error) {
           if (dir->i_mode & S_ISGID)
               inode->i_gid = dir->i_gid;
           d_instantiate(dentry, inode);
           dget(dentry);
           dir->i_mtime = dir->i_ctime = CURRENT_TIME;
       } else
           iput(inode);
   }
   return error;
}

static int ramfs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
{
   ; 在目录dir内创建一个以dentry为目录项的目录
   int retval = ramfs_mknod(dir, dentry, mode | S_IFDIR, 0);
   if (!retval)
       dir->i_nlink++;
   return retval;
}

int simple_rename(struct inode *old_dir, struct dentry *old_dentry,
       struct inode *new_dir, struct dentry *new_dentry)
{
   struct inode *inode = old_dentry->d_inode;
   int they_are_dirs = S_ISDIR(old_dentry->d_inode->i_mode);

   if (!simple_empty(new_dentry))
       return -ENOTEMPTY;

   if (new_dentry->d_inode) {
       simple_unlink(new_dir, new_dentry);
       if (they_are_dirs)
           old_dir->i_nlink--;
   } else if (they_are_dirs) {
       old_dir->i_nlink--;
       new_dir->i_nlink++;
   }

   ; 将目录old_dir内的目录项改名为new_dir目录中的new_dentry所描述的目录项
   old_dir->i_ctime = old_dir->i_mtime = new_dir->i_ctime =
       new_dir->i_mtime = inode->i_ctime = CURRENT_TIME;

   return 0;
}
struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev)
{
   struct inode * inode = new_inode(sb);//创建新的inode

   //初始化inode
   if (inode) {
       inode->i_mode = mode;
       inode->i_uid = current->fsuid;
       inode->i_gid = current->fsgid;
       inode->i_blksize = PAGE_CACHE_SIZE;
       inode->i_blocks = 0;
       inode->i_mapping->a_ops = &ramfs_aops; //底层操作接口
       inode->i_mapping->backing_dev_info = &ramfs_backing_dev_info;
       inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
       switch (mode & S_IFMT) {
       default:
           init_special_inode(inode, mode, dev); //与设备文件相联的inode函数
           break;
       case S_IFREG:
           inode->i_op = &ramfs_file_inode_operations; //文件操作接口
           inode->i_fop = &ramfs_file_operations;
           break;
       case S_IFDIR:
           inode->i_op = &ramfs_dir_inode_operations; //目录操作接口
           inode->i_fop = &simple_dir_operations;

           /* directory inodes start off with i_nlink == 2 (for "." entry) */
           inode->i_nlink++;
           break;
       case S_IFLNK:
           inode->i_op = &page_symlink_inode_operations; //连接操作接口
           break;
       }
   }
   return inode;
}

void init_special_inode(struct inode *inode, umode_t mode, dev_t rdev)
{
   inode->i_mode = mode;
   if (S_ISCHR(mode)) {如果为字符设备文件,提供字符设备的inode函数
       inode->i_fop = &def_chr_fops;
       inode->i_rdev = rdev;
   } else if (S_ISBLK(mode)) {如果为块设备文件,提供块设备的inode函数
       inode->i_fop = &def_blk_fops;指向块设备描述结构
       inode->i_rdev = rdev;
   } else if (S_ISFIFO(mode))如果为FIFO文件,提供FIFO的inode函数
       inode->i_fop = &def_fifo_fops;
   else if (S_ISSOCK(mode))如果为SOCK文件,提供SOCK的inode函数
       inode->i_fop = &bad_sock_fops;
   else
       printk(KERN_DEBUG "init_special_inode: bogus i_mode (%o)\n",
            mode);
}