主頁 > 區塊鏈 > Linux虛擬檔案系統(VFS)

Linux虛擬檔案系統(VFS)

2021-06-15 07:44:02 區塊鏈

目錄

1 虛擬檔案系統概述

2 底層檔案系統與VFS四大物件

磁盤與底層檔案系統例子

超級塊物件super block

索引節點物件inode

目錄項dentry

FILE檔案物件


1 虛擬檔案系統概述

Linux中“一切皆檔案”,所有檔案都放置在以 “/” 為根目錄的一個目錄樹中,所有的硬體設備也都是檔案,各有自己的檔案系統(比如對新硬碟進行格式化的時候就要給其設定一個檔案系統),但是在Linux中訪問任何型別的檔案時,不管是普通檔案還是設備檔案等,都可以統一使用open(),read(),write()這樣的系統呼叫,這就是虛擬檔案系統VFS的核心思想,在具體的檔案系統之上提供更高一層的抽象,給各種檔案系統提供統一的IO操作介面

VFS是一個內核軟體層,主要利用四種物件來建立一種統一的檔案模型,VFS相當于定義了一種標準,只要是按照VFS標準介面開發的檔案系統都可以接入linux,按照VFS標準即表示這個底層檔案系統要有(或者支持)四大物件,當檔案系統被掛載時,所有與它有關的資訊都放入super_block結構體中,從用戶的角度看,Linux的檔案系統只有VFS,

VFS四大物件即四種記憶體內核區的結構體物件,在具體的檔案系統中有對應的資料來初始化這四種物件,所以要注意區分內核中的物件和具體檔案系統對應的磁盤資料區域

superblock(超級塊):存盤檔案系統的元資料,一個超級塊對應一個實際的檔案系統,

inode(索引節點):存盤磁盤上檔案的元資料

dentry(目錄項):保存檔案名與inode之間的映射關系,以及目錄與目錄下檔案之間的映射關系,是一種邏輯上的概念,有快取機制,

file:一個行程打開一個檔案時會創建一個FILE結構體,它與具體的行程和用戶關聯,需要注意的是FILE物件與行程相關聯,但是并不意味著FILE物件是某個行程專屬的,即不同行程檔案描述表中的FILE*指標可以指向相同的FILE物件,

2 底層檔案系統與VFS四大物件

磁盤與底層檔案系統例子

磁盤(disk):一個硬體設備,比如我們平時買的硬碟,可以分成很多個磁區,

磁區(partition):從磁盤上劃出來的一塊空間,類似windows中可以分CDE區,通常情況下,一個磁區只能格式化為一個檔案系統(雖然現在有新技術將一個磁區格式化為多個檔案系統),但我們通常可以認為一個磁區,

扇區(sector):硬體上I/O操作的最小單位,通常是512位元組,

塊(block):Linux虛擬檔案系統I/O操作的最小單位,作業系統在讀取硬碟的時候,一次性讀取的最小單位是一個塊,一般是4KB的大小,,

塊組(block group):一個磁區可以分成好幾個塊組,如下圖所示,同一個磁區內的塊組通常是屬于同一個檔案系統,

檔案系統在磁盤上的布局示意圖

以下概念均是底層檔案系統劃分的資料區域,并非VFS記憶體中四大物件,但是要用這些資訊來初始化四大物件,且對四大物件的改變最終要回寫回這些區域

引導塊(boot sector):一個磁區由引導塊和底層檔案系統組成,但是一般只有根檔案系統中這一塊有引導代碼,其它檔案系統中這一塊空著,

超級塊(super block):是一個檔案系統的核心,描述整個磁區的檔案系統資訊,在每個塊組的開頭有一份拷貝,記錄了該檔案系統的塊大小,上次掛載時間,塊組個數,每個塊組中塊的個數,以及空閑塊數和空閑Inode數等,超級塊區域的資料用于初始化VFS的超級塊物件,同樣的,VFS超級塊物件可以改變之后回寫回磁盤超級塊區域,

塊組描述符表(GDT):存盤當前塊組的全域資訊,比如邏輯塊位圖的塊號,i節點位圖的塊號,以及空閑的塊數和空閑的inode數等,

邏輯塊位圖(盤塊位圖Block Bitmap):如果某一位為1,則這個位對應的邏輯塊或者說資料區的那個塊是被使用了的,否則是空閑的,其本身只占一個塊,

索引節點位圖(inode Bitmap):如果某一位為1,則代表這一位對應的 inode 表中那個區域沒有存資訊,也是占一個塊,從這里也可以看出inode的數目是有限的,如果有非常多的小檔案的話可能造成一種情況,磁盤還有空間,inode號碼用完了,

索引節點表(inode table):inode表中每個inode節點(即索引節點)對應一個磁盤檔案,存盤了磁盤文的元資訊,即除了檔案名以外的所有資訊,比如用戶組,權限,大小,修改時間等,inode中還保存了指向檔案實際陣列的地址資訊,通過inode機制實作了檔案資料本身和資料描述資訊的分開存盤,

資料區(Data Blocks):這里存盤的就是實際的磁盤資料了,對于普通檔案,其內容就是檔案資料,對于目錄檔案,其內容是該目錄下的所有檔案名(包塊子目錄),對于軟鏈接,其內容是原目標路徑名,

超級塊物件super block

一個超級塊物件對應一個具體的檔案系統,超級塊在記憶體中的物體是一個結構體 struct super_block,超級塊實作了對具體的檔案系統的一種抽象,即不管底層是什么檔案系統,在VFS中處理的時候都將其抽象為一個 super_block結構體物件,超級塊是一個全域的資料結構,這里我們所說的超級塊都是只存在于記憶體中的資料結構,

具體地,內核中檔案系統部分呼叫alloc_super()函式從磁盤中讀取底層檔案系統超級塊區域,然后用其中的資料來給記憶體中超級塊物件賦值,

struct super_block {
    struct list_head s_list; /* 系統將所有檔案系統的超級塊組成鏈表*/
    dev_t s_dev; /* search index; _not_ kdev_t */
    unsigned long s_blocksize;
    unsigned char s_blocksize_bits;
    unsigned char s_dirt;
    unsigned long long s_maxbytes;    /* Max file size */
    struct file_system_type *s_type; //檔案系統型別
    const struct super_operations *s_op; //操作函式集
    struct dquot_operations *dq_op;
    struct quotactl_ops *s_qcop;
    struct export_operations *s_export_op;
    unsigned long s_flags;
    unsigned long s_magic;
    struct dentry *s_root; //掛載根目錄
    struct rw_semaphore s_umount;
    struct mutex s_lock;
    int s_count;
    int s_syncing;
    int s_need_sync_fs;
    atomic_t s_active;
#ifdef CONFIG_SECURITY
    void                    *s_security; //LSM框架的安全域
#endif
    struct xattr_handler **s_xattr;

    struct list_head s_inodes;    /* 所有的inode節點鏈表*/
    struct list_head s_dirty;    /* dirty inodes */
    struct list_head s_io;        /* parked for writeback */
    struct hlist_head s_anon;        /* anonymous dentries for (nfs) exporting */
    struct list_head s_files;

    struct block_device *s_bdev;
    struct list_head s_instances;
    struct quota_info s_dquot;    /* Diskquota specific options */

    int s_frozen;
    wait_queue_head_t s_wait_unfrozen;

    char s_id[32];/* Informational name */

    void *s_fs_info; /* Filesystem private info */

    /*
     * The next field is for VFS *only*. No filesystems have any business
     * even looking at it. You had been warned.
     */
    struct mutex s_vfs_rename_mutex;    /* Kludge */

    /* Granularity of c/m/atime in ns.
       Cannot be worse than a second */
    u32 s_time_gran;
};

s_list:是一個list_head結構體物件,list_head結構體如下定義,內核中使用一個雙向環形鏈表將所有超級塊連起來管理,即每個超級塊的s_list屬性都包含了指向內核鏈表中前一個元素和后一個元素的指標,全域變數super_blocks用于指向鏈表中第一個元素,Linux內核經常用該物件間接定義雙向回圈鏈表來管理資料,具體使用方法可以參考linux內核鏈表list_head的原理與使用_不休的博客-CSDN博客

struct{

    list_head *prev;

    list_head *next;

}

s_blocksize:檔案系統中資料塊大小,單位是位元組

s_dirt:臟位,在具體的硬體設備中有關于其檔案系統的資料,將設備掛載以后,會用其關于檔案系統的資料來初始化記憶體中的super_block結構體物件,而VFS是允許對超級塊物件進行修改的,修改后的資料最終是要寫回磁盤對應區域的,s_dirt用于判斷超級塊物件中資料是否臟了即被修改過了,即與磁盤上的超級塊區域是否一致,

s_dirty:臟inode的雙向回圈鏈表,用于同步記憶體資料和底層存盤介質,當我們在用戶去用open打開一個檔案,記憶體中會創建dentry和inode,當我們用write往檔案中寫入資料,則該inode臟了,將其加入到s_dirty鏈表

s_files:該超級塊表是的檔案系統中所有被打開的檔案,

s_type:是指向file_system_type型別的指標,file_system_type結構體用于保存具體的檔案系統的資訊,

s_op:super_operations結構體型別的指標,因為一個超級塊對應一種檔案系統,而每種檔案系統的操作函式可能是不同的,super_operations結構體由一些函式指標組成,這些函式指標用特定檔案系統的超級塊區域操作函式來初始化,比如里邊會有函式實作獲取和回傳呼層檔案系統inode的方法,

s_inodes:是一個list_head結構體物件,指向超級塊對應檔案系統中的所有inode索引節點的鏈表,

索引節點物件inode

保存檔案元資料,即檔案大小,設備識別符號,用戶識別符號,用戶組識別符號,檔案模式,擴展屬性,檔案讀取或修改的時間戳,鏈接數量,指向存盤該內容的磁盤區塊的指標,通過索引節點inode可以找到檔案的具體資料在磁盤中的位置,inode有兩種,一種是VFS的inode物件,一種是具體檔案系統的inode磁盤區域,前者在記憶體中,后者在磁盤中,所以每次其實是將磁盤中的inode讀取之后初始化記憶體中的inode,這樣才是算使用了磁盤檔案inode,inode是唯一的,一個inode物件了磁盤上的一個真實檔案,

<span style="font-size:14px;">440 struct inode {
441         struct list_head        i_hash;
442         struct list_head        i_list;
443         struct list_head        i_dentry;
444         
445         struct list_head        i_dirty_buffers;
446         struct list_head        i_dirty_data_buffers;
447 
448         unsigned long           i_ino;
449         atomic_t                i_count;
450         kdev_t                  i_dev;
451         umode_t                 i_mode;
452         unsigned int            i_nlink;
453         uid_t                   i_uid;
454         gid_t                   i_gid;
455         kdev_t                  i_rdev;
456         loff_t                  i_size;
457         time_t                  i_atime;
458         time_t                  i_mtime;
459         time_t                  i_ctime;
460         unsigned int            i_blkbits;
461         unsigned long           i_blksize;
462         unsigned long           i_blocks;
463         unsigned long           i_version;
464         unsigned short          i_bytes;
465         struct semaphore        i_sem;
466         struct rw_semaphore     i_alloc_sem;
467         struct semaphore        i_zombie;
468         struct inode_operations *i_op;
469         struct file_operations  *i_fop; /* former ->i_op->default_file_ops */
470         struct super_block      *i_sb;
471         wait_queue_head_t       i_wait;
472         struct file_lock        *i_flock;
473         struct address_space    *i_mapping;
474         struct address_space    i_data;
475         struct dquot            *i_dquot[MAXQUOTAS];
476         /* These three should probably be a union */
477         struct list_head        i_devices;
478         struct pipe_inode_info  *i_pipe;
479         struct block_device     *i_bdev;
480         struct char_device      *i_cdev;
481 
482         unsigned long           i_dnotify_mask; /* Directory notify events */
483         struct dnotify_struct   *i_dnotify; /* for directory notifications */
484 
485         unsigned long           i_state;
486 
487         unsigned int            i_flags;
488         unsigned char           i_sock;
489 
490         atomic_t                i_writecount;
491         unsigned int            i_attr_flags;
492         __u32                   i_generation;
493         union {
494                 struct minix_inode_info         minix_i;
495                 struct ext2_inode_info          ext2_i;
496                 struct ext3_inode_info          ext3_i;
497                 struct hpfs_inode_info          hpfs_i;
498                 struct ntfs_inode_info          ntfs_i;
499                 struct msdos_inode_info         msdos_i;
500                 struct umsdos_inode_info        umsdos_i;
501                 struct iso_inode_info           isofs_i;
502                 struct nfs_inode_info           nfs_i;
503                 struct sysv_inode_info          sysv_i;
504                 struct affs_inode_info          affs_i;
505                 struct ufs_inode_info           ufs_i;
506                 struct efs_inode_info           efs_i;
507                 struct romfs_inode_info         romfs_i;
508                 struct shmem_inode_info         shmem_i;
509                 struct coda_inode_info          coda_i;
510                 struct smb_inode_info           smbfs_i;
511                 struct hfs_inode_info           hfs_i;
512                 struct adfs_inode_info          adfs_i;
513                 struct qnx4_inode_info          qnx4_i;
514                 struct reiserfs_inode_info      reiserfs_i;
515                 struct bfs_inode_info           bfs_i;
516                 struct udf_inode_info           udf_i;
517                 struct ncp_inode_info           ncpfs_i;
518                 struct proc_inode_info          proc_i;
519                 struct socket                   socket_i;
520                 struct usbdev_inode_info        usbdev_i;
521                 struct jffs2_inode_info         jffs2_i;
522                 void                            *generic_ip;
523         } u;
524 };</span>

以上是通用的inode物件結構體定義,

i_no:便是inode的唯一性編號

i_count:訪問該inode結構體物件的行程數

i_nlink:硬鏈接計數,等于0時將檔案從磁盤移除,

i_hash:指向哈希鏈表指標,用于查詢,已經inode號碼和對應超級塊的時候,通過哈希表來快速查詢地址,具體看下邊管理inode節點,也是list_head型別物件,這種物件就對應了一個雙向回圈鏈表,

i_dentry:指向目錄項鏈表指標,因為一個inode可以物件多個dentry,因此用一個鏈表將于本inode關聯的目錄項都連在一起,

i_op:索引節點操作函式指標,指向了inode_operation結構體,提供與inode相關的操作

i_fop:指向file_operations結構提供檔案操作,在file結構體中也有指向file_operations結構的指標,

i_sb:inode所屬檔案系統的超級塊指標

管理inode節點的四個鏈表(前兩個是全域鏈表,第三個在超級塊中):

inode_unused:目前未被使用的inode節點鏈表,即尚在記憶體中沒有銷毀,但是沒有行程使用,i_count為0,

inode_in_use:當前正在使用的inode鏈表,i_count > 0且 i_nlink > 0

super_block中的s_dirty:將所有修改過的inode鏈接起來

inode_hashtable:為了加快查找效率,將正在使用的和臟的inode放入一個哈希表中,但是不同的inode的哈希值可能相等,hash值相等的inode哦那個過i_hash成員連接,

注意是所有位于記憶體中的inode會存放在一個名為inode_hashtable的全域哈希表中,如果inode還在磁盤,沒有快取到記憶體,則不會加入全域哈希表,inode_hashtable加快了對索引節點物件的搜索,但前提是要知道inode號碼和對應的超級塊物件,

注意在inode_hashtable哈希表中的元素是鏈表,是通過inode物件中的i_hash成員鏈接起來的雙向回圈鏈表,在這個子鏈表中對應的inode的哈希值是相等的,即inode_hashtable本質是一個資料和鏈表的結合體,

目錄項dentry

與超級塊物件super block和索引節點物件inode不同,dentry在底層磁盤上并沒有物件的物體,dentry是只存在于記憶體中的物件,其本質是快取了磁盤檔案查找的結果,即dentry中包含了檔案名到inode結構體地址的映射,所以也叫“dcache”,而VFS中的超級塊物件和索引節點物件一是為了為不同底層檔案系統提供更高層的表示,二是為了提高效率,所以其在記憶體和底層磁盤有具體對應的資料,

目錄項與目錄檔案是不同的,目錄檔案是磁盤上的具體的一種檔案,目錄項則是在記憶體用于記錄檔案名和inode節點映射關系的一種資料結構,可以說是為了提高查找效率而存在的,首先先要搞懂目錄是什么,

簡而言之,目錄的本質就是一個表,存盤了該目錄下檔案的檔案名和對應的inode編號,從inode table中找到對應編號的inode,就可以找到對應的資料,而目錄項dentry本質上是在查找檔案程序中快取在記憶體中的物件,所以目錄項也被稱為目錄項快取dcache,其與目錄檔案并不是一種像記憶體中與磁盤上的超級塊,索引節點那樣的對應關系,

也有些地方將目錄檔案中代表該目錄下一個檔案的表項叫做目錄項,其實也沒錯,知道其與記憶體中dentry的區別即可,其實也可以理解為磁盤上超級塊與記憶體中超級塊之間的關系,

舉個例子,如下圖中所示目錄結構:

對于CPP這個目錄檔案,其存盤的資料內容是:

目錄檔案表1
檔案名inode編號(只是舉例,不代表真實情況)
.1
..2
Calc3
test4
webserver5

即對于目錄檔案CPP來說,其內容是目錄下檔案名與其對應inode編號的映射,目錄檔案CPP下一共有五個檔案,都是目錄檔案,其中“.”是當前目錄檔案的硬鏈接,即其與CPP關聯的是同一個inode,“..”是上一級目錄的硬鏈接,

如圖中所示,CPP目錄檔案的硬鏈接數(下文中講解)是5,目錄檔案CPP本身,CPP目錄下的 “.”,以及目錄檔案Calc,test,webserver這三個目錄下的“..”,這五個目錄檔案互為硬鏈接,因此硬鏈接數是5,因為一個目錄下一定含有其本身的硬鏈接,這也就是為什么目錄檔案的硬鏈接數至少為2,

而對于目錄檔案test來說,其資料內容是:

目錄檔案表2
檔案名inode編號
.4
..1
makefile6
test.c7
test.o8
welove9

test目錄下包括了當前目錄檔案的inode編號以及上級目錄即CPP的inode編號,以及三個普通檔案與其inode編號的映射,

現在假設我們要查找 ../CPP/test/test.c 這個檔案,則步驟為(假設已知CPP的inode編號,胡羅CPP之前檔案的查找程序):

由CPP的inode編號找到檔案名CPP對應的索引節點,由索引節點找到對應資料塊,從資料塊中取出CPP檔案的內容,即上文中目錄檔案表1,

從目錄檔案表1找到 test 對應的inode編號,然后找到對應索引節點以及資料塊,從資料塊中取出目錄檔案test的內容,即目錄檔案表2,

從目錄檔案表2中找到test.c對應的inode編號,從而找到test.c在磁盤上的資料塊,取出內容,

這樣一個查找檔案的程序涉及大量的磁盤操作,由于磁盤相比記憶體速度很慢,因此產生了dentry的快取機制,即每次VFS訪問底層資料時,都將訪問結果保存下來,即在記憶體中構造dentry結構來保存檔案名(d_name)和inode號碼對應的索引節點的地址之間的映射,并且,當查找一個檔案時,查找到其路徑上的每個檔案時候在記憶體中都會構造一個dentry結構體物件,并通過一定的機制(其實就是定義各種鏈表來間接形成一個樹形層次結構以便于管理)來形成檔案系統的目錄樹結構,

對于上文中查找test.c檔案的例子來說,CPP,test,test.c,搜索到路徑上的這三個檔案時候都會建立相應的dentry,并且這三個檔案的目錄層次關系也會保留,

即dentry或者說dcache的目的有兩個,一是保存訪問到的檔案名與索引節點地址間的映射關系,二是維護好檔案之間的目錄層次關系,dentry結構體定義如下:

 struct dentry {  
    atomic_t d_count;//目錄項物件參考計數器  
    unsigned int d_flags; /* protected by d_lock */  
    spinlock_t d_lock; /* per dentry lock */  
    struct inode *d_inode; /* Where the name belongs to - NULL is 
    struct hlist_node d_hash; /* 鏈接到dentry cache的hash鏈表 */  
    struct dentry *d_parent; /* 指向父dentry結構的指標 */  
    struct qstr d_name;//檔案名  
    struct list_head d_lru; /* LRU list */  
    union {  
        struct list_head d_child; /* child of parent list */  
        struct rcu_head d_rcu;  
    } d_u;  
    struct list_head d_subdirs; /* 是子項的鏈表頭,子項可能是目錄也可能是檔案,所有子項都要鏈接到這個鏈表, */  
    struct list_head d_alias; /* inode alias list */  
    unsigned long d_time; /* used by d_revalidate */  
    struct dentry_operations *d_op;  
    struct super_block *d_sb; /* The root of the dentry tree */  
    void *d_fsdata; /* fs-specific data */  
    int d_mounted; /*表示dentry是否是一個掛載點,如果是掛載點,該成員不為0 
    unsigned char d_iname[DNAME_INLINE_LEN_MIN]; /* small names */  
};  

d_count:目錄項物件參考計數器

d_name:檔案名

d_inode:inode節點的指標,便于快速找到對應的索引節點

d_sb:指向對應超級塊的指標

d_op:指向dentry對應的操作函式集

d_subdirs & d_child:某目錄的d_subdirs與該目錄下所有檔案的d_child成員一起形成一個雙向回圈鏈表,將該目錄下的所有檔案連接在一起,目的是保留檔案的目錄結構,即一個d_subdirs和多個d_child一起形成鏈表,d_subdirs對應檔案在d_child對應檔案的上一層目錄,具體可見下圖,

d_parent:指向父目錄的dentry物件,具體看下圖,

通過d_subdirsd_child把同一目錄下的檔案都連接了起來形成鏈表,然后通過d_parent成員可以確定該鏈表對應的檔案所在的目錄,這三個成員一起就能完全保留檔案之間的目錄層次關系,比如當移動檔案的時候,只需要將dentry物件從舊得父dentry鏈表(d_subdirs)上脫離,鏈接到新的父dentry的d_subdirs鏈表上,并將d_parent成員指向新的父dentry即可,可以看到移動檔案并沒有移動底層檔案,甚至沒有改變inode,只是改變了快取中的dentry(最終改變目錄檔案),因此在同一個檔案系統中移動檔案會很快,但是跨檔案系統就會改變inode和底層資料區了,因此速度很慢,

dentry_hashtable & d_hash:dentry_table哈希表維護在記憶體中的所有目錄項,哈希表中每個元素都是一個雙向回圈鏈表,用于維護哈希值相等的目錄項,這個雙向回圈鏈表是通過dentry中的d_hash成員來鏈接在一起的,

FILE檔案物件

是VFS四大物件里唯一一個行程級物件,即與具體的行程相關聯,與行程相關聯的意思是,某個行程打開一個檔案,內核就會創建一個FILE物件,但是并不意味著這個FILE物件是這個行程專屬的,不同行程中的檔案描述符表中的指標可以指向相同的FILE物件(行程間通信?),從而共享這個物件,具體看下圖:

每個行程的行程控制塊PCB中都有一個檔案描述符表,檔案描述符表的索引就是所謂的檔案描述符,在系統呼叫層面,都是用檔案描述符來進行各種IO操作,這個表的默認大小是1024,行程每次呼叫open打開一個檔案的時候,內核就會創建一個FILE物件,然后把檔案描述符表中最小可用的索引號給這個FILE物件,并用一個FILE*指標作為檔案描述符表對應位置的表項,來指向代表打開檔案的這個FILE物件,系統級的打開檔案表是由所有內核創建的FILE物件通過其fu_list成員連接成的雙向回圈鏈表,即系統集打開檔案表中的表項就是FILE物件,FILE物件中有目錄項成員dentry,dentry中有指向inode索引節點的指標,即通過打開檔案表中的表項,就能找到對應的inode,注意上圖打開檔案表中把目錄項和inode指標列了兩列,實際上inode指標應該是目錄項中的成員,

行程A中,

檔案描述符0和1指向同一個檔案表項,可能是用了dup函式進行檔案描述符重定向

檔案描述2和0&1最終指向了同一個inode,即同一個底層檔案,原因應該是用open重復打開了同一個檔案,因此雖然檔案描述符2和 0&1 有不同的檔案表項,但是最終指向的檔案是一樣的,因為每呼叫一次open,內核就會創建一個FILE物件,不同的FILE物件雖然可以對應同一個磁盤檔案,但是其讀寫位置等資訊可以不一樣,

行程A中的檔案描述符012最終指向檔案與行程B中檔案描述符0指向檔案是一樣的,因為在不同的行程中用open打開了同一個檔案,

實際上,還存在下圖中的情況,不同行程中的檔案描述符項指向了同一個打開檔案表的檔案表項,下圖中行程A和B的檔案描述符2指向了同一個打開檔案表項,可能是因為用fork創建了子行程,子行程會與父行程共享檔案描述符表,

struct file {

  union {

        struct list_head fu_list; //檔案物件鏈表指標linux/include/linux/list.h

        struct rcu_head fu_rcuhead; //RCU(Read-Copy Update)是Linux 2.6內核中新的鎖機制

   } f_u;

  struct path f_path; //包含dentry和mnt兩個成員,用于確定檔案路徑

  #define f_dentry f_path.dentry //f_path的成員之一,當前檔案的dentry結構

  #define f_vfsmnt f_path.mnt //表示當前檔案所在檔案系統的掛載根目錄

  const struct file_operations *f_op; //與該檔案相關聯的操作函式

  atomic_t f_count; //檔案的參考計數(有多少行程打開該檔案)

  unsigned int f_flags; //對應于open時指定的flag

  mode_t f_mode; //讀寫模式:open的mod_t mode引數

   loff_t  f_pos;//當前檔案指標位置

  off_t f_pos; //該檔案在當前行程中的檔案偏移量

  struct fown_struct f_owner; //該結構的作用是通過信號進行I/O時間通知的資料,

  unsigned int f_uid, f_gid;// 檔案所有者id,所有者組id

  struct file_ra_state f_ra; //在linux/include/linux/fs.h中定義,檔案預讀相關

  unsigned long f_version;//記錄檔案的版本號,每次使用之后遞增

  #ifdef CONFIG_SECURITY

       void *f_security;

  #endif

  /* needed for tty driver, and maybe others */

  void *private_data;//使用這個成員來指向分配的資料

  #ifdef CONFIG_EPOLL

  /* Used by fs/eventpoll.c to link all the hooks to this file */

      struct list_head f_ep_links;

      spinlock_t f_ep_lock;

  #endif /* #ifdef CONFIG_EPOLL */

  struct address_space *f_mapping;

  };

fu_list:用于將所有的打開的FILE檔案連接起來形成打開檔案表

f_path:里邊包含目錄項dentry和掛載點資訊

f_op:指向與檔案相關的操作合集,比如read,write,lseek等

f_count:指示有多少個行程在使用該檔案,這里也能看出FILE并不是某個行程的私有物件

f_flags:打開檔案時候指定的標志,對應open的flags引數,

f_pos:檔案的讀寫位置

行程與VFS四大物件聯系示意圖,這幾個東西都是在內核空間中的

行程與超級塊、檔案、索引結點、目錄項的關系

一個目錄項dentry可以對應多個FILE(比如多次打開同一檔案),一個inode可以對應多個dentry(比如打開多個互為硬鏈接的檔案),inode與底層檔案之間是一對一的關系,

轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/287440.html

標籤:區塊鏈

上一篇:智能合約實戰 solidity 語法學習 08 [ require assert modifier revert ]

下一篇:特斯拉:努力促進行業和數字經濟健康蓬勃發展

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • JAVA使用 web3j 進行token轉賬

    最近新學習了下區塊鏈這方面的知識,所學不多,給大家分享下。 # 1. 關于web3j web3j是一個高度模塊化,反應性,型別安全的Java和Android庫,用于與智能合約配合并與以太坊網路上的客戶端(節點)集成。 # 2. 準備作業 jdk版本1.8 引入maven <dependency> < ......

    uj5u.com 2020-09-10 03:03:06 more
  • 以太坊智能合約開發框架Truffle

    前言 部署智能合約有多種方式,命令列的瀏覽器的渠道都有,但往往跟我們程式員的風格不太相符,因為我們習慣了在IDE里寫了代碼然后打包運行看效果。 雖然現在IDE中已經存在了Solidity插件,可以撰寫智能合約,但是部署智能合約卻要另走他路,沒辦法進行一個快捷的部署與測驗。 如果團隊管理的區塊節點多、 ......

    uj5u.com 2020-09-10 03:03:12 more
  • 谷歌二次驗證碼成為區塊鏈專用安全碼,你怎么看?

    前言 谷歌身份驗證器,前些年大家都比較陌生,但隨著國內互聯網安全的加強,它越來越多地出現在大家的視野中。 比較廣泛接觸的人群是國際3A游戲愛好者,游戲盜號現象嚴重+國外賬號安全應用廣泛,這類游戲一般都會要求用戶系結名為“兩步驗證”、“雙重驗證”等,平臺一般都推薦用谷歌身份驗證器。 后來區塊鏈業務風靡 ......

    uj5u.com 2020-09-10 03:03:17 more
  • 密碼學DAY1

    目錄 ##1.1 密碼學基本概念 密碼在我們的生活中有著重要的作用,那么密碼究竟來自何方,為何會產生呢? 密碼學是網路安全、資訊安全、區塊鏈等產品的基礎,常見的非對稱加密、對稱加密、散列函式等,都屬于密碼學范疇。 密碼學有數千年的歷史,從最開始的替換法到如今的非對稱加密演算法,經歷了古典密碼學,近代密 ......

    uj5u.com 2020-09-10 03:03:50 more
  • 密碼學DAY1_02

    目錄 ##1.1 ASCII編碼 ASCII(American Standard Code for Information Interchange,美國資訊交換標準代碼)是基于拉丁字母的一套電腦編碼系統,主要用于顯示現代英語和其他西歐語言。它是現今最通用的單位元組編碼系統,并等同于國際標準ISO/IE ......

    uj5u.com 2020-09-10 03:04:50 more
  • 密碼學DAY2

    ##1.1 加密模式 加密模式:https://docs.oracle.com/javase/8/docs/api/javax/crypto/Cipher.html ECB ECB : Electronic codebook, 電子密碼本. 需要加密的訊息按照塊密碼的塊大小被分為數個塊,并對每個塊進 ......

    uj5u.com 2020-09-10 03:05:42 more
  • NTP時鐘服務器的特點(京準電子)

    NTP時鐘服務器的特點(京準電子) NTP時鐘服務器的特點(京準電子) 京準電子官V——ahjzsz 首先對時間同步進行了背景介紹,然后討論了不同的時間同步網路技術,最后指出了建立全球或區域時間同步網存在的問題。 一、概 述 在通信領域,“同步”概念是指頻率的同步,即網路各個節點的時鐘頻率和相位同步 ......

    uj5u.com 2020-09-10 03:05:47 more
  • 標準化考場時鐘同步系統推進智能化校園建設

    標準化考場時鐘同步系統推進智能化校園建設 標準化考場時鐘同步系統推進智能化校園建設 安徽京準電子科技官微——ahjzsz 一、背景概述隨著教育事業的快速發展,學校建設如雨后春筍,隨之而來的學校教育、管理、安全方面的問題成了學校管理人員面臨的最大的挑戰,這些問題同時也是學生家長所擔心的。為了讓學生有更 ......

    uj5u.com 2020-09-10 03:05:51 more
  • 位元幣入門

    引言 位元幣基本結構 位元幣基礎知識 1)哈希演算法 2)非對稱加密技術 3)數字簽名 4)MerkleTree 5)哪有位元幣,有的是UTXO 6)位元幣挖礦與共識 7)區塊驗證(共識) 總結 引言 上一篇我們已經知道了什么是區塊鏈,此篇說一下區塊鏈的第一個應用——位元幣。其實先有位元幣,后有的區塊 ......

    uj5u.com 2020-09-10 03:06:15 more
  • 北斗對時服務器(北斗對時設備)電力系統應用

    北斗對時服務器(北斗對時設備)電力系統應用 北斗對時服務器(北斗對時設備)電力系統應用 京準電子科技官微(ahjzsz) 中國北斗衛星導航系統(英文名稱:BeiDou Navigation Satellite System,簡稱BDS),因為是目前世界范圍內唯一可以大面積提供免費定位服務的系統,所以 ......

    uj5u.com 2020-09-10 03:06:20 more
最新发布
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:46:47 more
  • Hyperledger Fabric 使用 CouchDB 和復雜智能合約開發

    在上個實驗中,我們已經實作了簡單智能合約實作及客戶端開發,但該實驗中智能合約只有基礎的增刪改查功能,且其中的資料管理功能與傳統 MySQL 比相差甚遠。本文將在前面實驗的基礎上,將 Hyperledger Fabric 的默認資料庫支持 LevelDB 改為 CouchDB 模式,以實作更復雜的資料... ......

    uj5u.com 2023-04-16 07:28:31 more
  • .NET Core 波場鏈離線簽名、廣播交易(發送 TRX和USDT)筆記

    Get Started NuGet You can run the following command to install the Tron.Wallet.Net in your project. PM> Install-Package Tron.Wallet.Net 配置 public reco ......

    uj5u.com 2023-04-14 08:08:00 more
  • DKP 黑客分析——不正確的代幣對比率計算

    概述: 2023 年 2 月 8 日,針對 DKP 協議的閃電貸攻擊導致該協議的用戶損失了 8 萬美元,因為 execute() 函式取決于 USDT-DKP 對中兩種代幣的余額比率。 智能合約黑客概述: 攻擊者的交易:0x0c850f,0x2d31 攻擊者地址:0xF38 利用合同:0xf34ad ......

    uj5u.com 2023-04-07 07:46:09 more
  • Defi開發簡介

    Defi開發簡介 介紹 Defi是去中心化金融的縮寫, 是一項旨在利用區塊鏈技術和智能合約創建更加開放,可訪問和透明的金融體系的運動. 這與傳統金融形成鮮明對比,傳統金融通常由少數大型銀行和金融機構控制 在Defi的世界里,用戶可以直接從他們的電腦或移動設備上訪問廣泛的金融服務,而不需要像銀行或者信 ......

    uj5u.com 2023-04-05 08:01:34 more
  • solidity簡單的ERC20代幣實作

    // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; import "hardhat/console.sol"; //ERC20 同質化代幣,每個代幣的本質或性質都是相同 //ETH 是原生代幣,它不是ERC20代幣, ......

    uj5u.com 2023-03-21 07:56:29 more
  • solidity 參考型別修飾符memory、calldata與storage 常量修飾符C

    在solidity語言中 參考型別修飾符(參考型別為存盤空間不固定的數值型別) memory、calldata與storage,它們只能修飾參考型別變數,比如字串、陣列、位元組等... memory 適用于方法傳參、返參或在方法體內使用,使用完就會清除掉,釋放記憶體 calldata 僅適用于方法傳參 ......

    uj5u.com 2023-03-08 07:57:54 more
  • solidity注解標簽

    在solidity語言中 注釋符為// 注解符為/* 內容*/ 或者 是 ///內容 注解中含有這幾個標簽給予我們使用 @title 一個應該描述合約/介面的標題 contract, library, interface @author 作者的名字 contract, library, interf ......

    uj5u.com 2023-03-08 07:57:49 more
  • 評價指標:相似度、GAS消耗

    【代碼注釋自動生成方法綜述】 這些評測指標主要來自機器翻譯和文本總結等研究領域,可以評估候選文本(即基于代碼注釋自動方法而生成)和參考文本(即基于手工方式而生成)的相似度. BLEU指標^[^?88^^?^]^:其全稱是bilingual evaluation understudy.該指標是最早用于 ......

    uj5u.com 2023-02-23 07:27:39 more
  • 基于NOSTR協議的“公有制”版本的Twitter,去中心化社交軟體Damus

    最近,一個幽靈,Web3的幽靈,在網路游蕩,它叫Damus,這玩意詮釋了什么叫做病毒式營銷,滑稽的是,一個Web3產品卻在Web2的產品鏈上瘋狂傳銷,各方大佬紛紛為其背書,到底發生了什么?Damus的葫蘆里,賣的是什么藥? 注冊和簡單實用 很少有什么產品在用戶注冊環節會有什么噱頭,但Damus確實出 ......

    uj5u.com 2023-02-05 06:48:39 more