Linux核心原始碼情景分析-虛擬檔案系統

來源:互聯網
上載者:User

標籤:

    我們先來看兩張圖:

    第一張是VFS與具體檔案系統的關係:



    第二張是Linux檔案系統的階層:


    特殊檔案:用來實現”管道“的檔案,特別是"具名管道"的FIFO檔案,還有Unix域的socket,也都屬於特殊檔案;還有在/proc目錄下的一系列檔案。

    磁碟檔案:就是存在硬碟上的檔案。

    裝置檔案:sudo mount -t ext2 /dev/sdb1 /mnt/sdb,這裡的/dev/sdb1就是裝置檔案。如果硬碟上的節點raw_inode->i_block[block],如果得到是目錄節點的inode,那麼i_block[]儲存著目錄項的位置。如果是檔案節點的inode,那麼i_block[]儲存著真正資料的位置,現在裝置節點的inode儲存著裝置號(包含了主裝置號和次裝置號)。

    區別的他們的代碼如下,ext2_read_inode代碼如下:

if (inode->i_ino == EXT2_ACL_IDX_INO ||    inode->i_ino == EXT2_ACL_DATA_INO)/* Nothing to do */ ;else if (S_ISREG(inode->i_mode)) {//硬碟檔案,普通檔案inode->i_op = &ext2_file_inode_operations;inode->i_fop = &ext2_file_operations;inode->i_mapping->a_ops = &ext2_aops;} else if (S_ISDIR(inode->i_mode)) {//硬碟檔案,目錄檔案inode->i_op = &ext2_dir_inode_operations;inode->i_fop = &ext2_dir_operations;} else if (S_ISLNK(inode->i_mode)) {//硬碟檔案,連結檔案if (!inode->i_blocks)inode->i_op = &ext2_fast_symlink_inode_operations;else {inode->i_op = &page_symlink_inode_operations;inode->i_mapping->a_ops = &ext2_aops;}} else init_special_inode(inode, inode->i_mode,   le32_to_cpu(raw_inode->i_block[0]));
void init_special_inode(struct inode *inode, umode_t mode, int rdev){inode->i_mode = mode;if (S_ISCHR(mode)) {//裝置檔案,字元裝置inode->i_fop = &def_chr_fops;inode->i_rdev = to_kdev_t(rdev);} else if (S_ISBLK(mode)) {//裝置檔案,塊裝置inode->i_fop = &def_blk_fops;inode->i_rdev = to_kdev_t(rdev);inode->i_bdev = bdget(rdev);} else if (S_ISFIFO(mode))//特殊檔案,具名管道inode->i_fop = &def_fifo_fops;else if (S_ISSOCK(mode))//特殊檔案,socket檔案inode->i_fop = &bad_sock_fops;elseprintk(KERN_DEBUG "init_special_inode: bogus imode (%o)\n", mode);}


    一、我們對比下open對特殊檔案,具名管道和硬碟檔案,普通檔案來做對比。

    特殊檔案,具名管道的開啟請參考Linux核心原始碼情景分析-處理序間通訊-具名管道。

    硬碟檔案,普通檔案的開啟請參考Linux核心原始碼情景分析-檔案的開啟。f->f_op已經指向了ext2_file_operations。

    兩者不同之處在於dentry_open()時,f->f_op->open,普通檔案指向ext2_open_file;而具名管道指向fifo_open。

f->f_op = fops_get(inode->i_fop);//f->f_op被賦值為inode_i_fop    if (inode->i_sb)        file_move(f, &inode->i_sb->s_files);//將其從中間隊列脫鏈而掛入該檔案所在裝置的super_block結構中的file結構隊列s_files    if (f->f_op && f->f_op->open) {        error = f->f_op->open(inode,f);//普通檔案指向ext2_open_file;而具名管道指向fifo_open        if (error)            goto cleanup_all;    }   
    另外在open中調用path_walk指向的過程中也會因為dentry->d_op和inode->i_op的不同執行的代碼也不同。


    二、對比普通檔案的讀和管道檔案的讀的不同。

    普通檔案的讀,read映射到核心是sys_read,代碼如下:

asmlinkage ssize_t sys_read(unsigned int fd, char * buf, size_t count){ssize_t ret;struct file * file;ret = -EBADF;file = fget(fd);if (file) {if (file->f_mode & FMODE_READ) {ret = locks_verify_area(FLOCK_VERIFY_READ, file->f_dentry->d_inode,file, file->f_pos, count);if (!ret) {ssize_t (*read)(struct file *, char *, size_t, loff_t *);ret = -EINVAL;if (file->f_op && (read = file->f_op->read) != NULL)ret = read(file, buf, count, &file->f_pos);//generic_file_read}}if (ret > 0)inode_dir_notify(file->f_dentry->d_parent->d_inode,DN_ACCESS);fput(file);}return ret;}
    硬碟檔案,普通檔案的開啟請參考Linux核心原始碼情景分析-檔案的開啟。f->f_op已經指向了ext2_file_operations。所以file->f_op->read指向generic_file_read。

   管道檔案的讀請參考Linux核心原始碼情景分析-處理序間通訊-管道。f->f_op指向pipe_read。


   三、不同檔案系統super_block結構中的指標s_op指向具體的super_operations資料結構。

   參考Linux核心原始碼情景分析-從路徑名到目標節點,get_new_inode相關代碼:

static struct inode * get_new_inode(struct super_block *sb, unsigned long ino, struct list_head *head, find_inode_t find_actor, void *opaque){struct inode * inode;inode = alloc_inode();if (inode) {struct inode * old;spin_lock(&inode_lock);/* We released the lock, so.. */old = find_inode(sb, ino, head, find_actor, opaque);//再一次在雜湊表隊列中尋找if (!old) {//如果沒有找到inodes_stat.nr_inodes++;list_add(&inode->i_list, &inode_in_use);list_add(&inode->i_hash, head);//加入到對應的hash表inode->i_sb = sb;//超級塊結構inode->i_dev = sb->s_dev;//裝置號inode->i_ino = ino;//節點號inode->i_flags = 0;atomic_set(&inode->i_count, 1);inode->i_state = I_LOCK;spin_unlock(&inode_lock);clean_inode(inode);sb->s_op->read_inode(inode);//根據不同的檔案系統指向不同的代碼/* * This is special!  We do not need the spinlock * when clearing I_LOCK, because we‘re guaranteed * that nobody else tries to do anything about the * state of the inode when it is locked, as we * just created it (so there can be no old holders * that haven‘t tested I_LOCK). */inode->i_state &= ~I_LOCK;wake_up(&inode->i_wait);return inode;}/* * Uhhuh, somebody else created the same inode under * us. Use the old inode instead of the one we just * allocated. */__iget(old);//如果找到了inode結構spin_unlock(&inode_lock);destroy_inode(inode);inode = old;//使用找到的inode結構wait_on_inode(inode);}return inode;}
    sb->s_op->read_inode(inode);//根據不同的檔案系統指向不同的代碼。


    總結:

    我們把檔案系統比喻作"介面卡",而把虛擬檔案系統VFS比喻成一條插槽。因此,file結構中的指標f_op就可以看作插槽中的一個觸點,並且在dentry、inode、super_operations資料結構中都有類似的觸點。

    我們在上文也看到了。主要是以下不同:

    檔案操作跳轉表,即file_operations資料結構:file結構中的指標f_op指向具體的file_operations結構,這是open()、read()、write()等檔案操作的跳轉表。一種檔案系統並不只限於一個file_operations結構,如ext2就有兩個這樣的資料結構,分別用於普通檔案和目錄檔案。

    目錄項操作跳轉表:即dentry_operations資料結構:dentry結構中的指標d_op指向具體的dentry_operations資料結構,這是核心中hash()、compare()等內部操作的跳轉表。

    索引節點操作跳轉表,即inode_operations資料結構;inode結構中的指標i_op指向具體的inode_operations資料結構,lookup()、permissions()等內建函式的跳轉表。

    超級塊操作跳轉表,即super_operations資料結構:super_block結構中的指標s_op指向具體的super_operations資料結構,這是read_inode()、write_inode()、delete_inode()等內部操作的跳轉表。

Linux核心原始碼情景分析-虛擬檔案系統

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.