日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

Linux那些事儿之我是Sysfs(7)dentry与inode

發布時間:2023/11/27 生活经验 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux那些事儿之我是Sysfs(7)dentry与inode 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

我們在進程中要怎樣去描述一個文件呢?我們用目錄項(dentry)和索引節點(inode)。它們的定義如下:

include/linux/dcache.h

struct dentry {/* RCU lookup touched fields */unsigned int d_flags;		/* protected by d_lock */seqcount_t d_seq;		/* per dentry seqlock */struct hlist_bl_node d_hash;	/* lookup hash list */struct dentry *d_parent;	/* parent directory */struct qstr d_name;struct inode *d_inode;		/* Where the name belongs to - NULL is* negative */unsigned char d_iname[DNAME_INLINE_LEN];	/* small names *//* Ref lookup also touches following */struct lockref d_lockref;	/* per-dentry lock and refcount */const struct dentry_operations *d_op;struct super_block *d_sb;	/* The root of the dentry tree */unsigned long d_time;		/* used by d_revalidate */void *d_fsdata;			/* fs-specific data */struct list_head d_lru;		/* LRU list */struct list_head d_child;	/* child of parent list */struct list_head d_subdirs;	/* our children *//** d_alias and d_rcu can share memory*/union {struct hlist_node d_alias;	/* inode alias list */struct rcu_head d_rcu;} d_u;
};


include/linux/fs.h

struct inode {umode_t			i_mode;unsigned short		i_opflags;kuid_t			i_uid;kgid_t			i_gid;unsigned int		i_flags;#ifdef CONFIG_FS_POSIX_ACLstruct posix_acl	*i_acl;struct posix_acl	*i_default_acl;
#endifconst struct inode_operations	*i_op;struct super_block	*i_sb;struct address_space	*i_mapping;#ifdef CONFIG_SECURITYvoid			*i_security;
#endif/* Stat data, not accessed from path walking */unsigned long		i_ino;/** Filesystems may only read i_nlink directly.  They shall use the* following functions for modification:**    (set|clear|inc|drop)_nlink*    inode_(inc|dec)_link_count*/union {const unsigned int i_nlink;unsigned int __i_nlink;};dev_t			i_rdev;loff_t			i_size;struct timespec		i_atime;struct timespec		i_mtime;struct timespec		i_ctime;spinlock_t		i_lock;	/* i_blocks, i_bytes, maybe i_size */unsigned short          i_bytes;unsigned int		i_blkbits;blkcnt_t		i_blocks;#ifdef __NEED_I_SIZE_ORDEREDseqcount_t		i_size_seqcount;
#endif/* Misc */unsigned long		i_state;struct mutex		i_mutex;unsigned long		dirtied_when;	/* jiffies of first dirtying */struct hlist_node	i_hash;struct list_head	i_wb_list;	/* backing dev IO list */struct list_head	i_lru;		/* inode LRU list */struct list_head	i_sb_list;union {struct hlist_head	i_dentry;struct rcu_head		i_rcu;};u64			i_version;atomic_t		i_count;atomic_t		i_dio_count;atomic_t		i_writecount;
#ifdef CONFIG_IMAatomic_t		i_readcount; /* struct files open RO */
#endifconst struct file_operations	*i_fop;	/* former ->i_op->default_file_ops */struct file_lock	*i_flock;struct address_space	i_data;
#ifdef CONFIG_QUOTAstruct dquot		*i_dquot[MAXQUOTAS];
#endifstruct list_head	i_devices;union {struct pipe_inode_info	*i_pipe;struct block_device	*i_bdev;struct cdev		*i_cdev;};__u32			i_generation;#ifdef CONFIG_FSNOTIFY__u32			i_fsnotify_mask; /* all events this inode cares about */struct hlist_head	i_fsnotify_marks;
#endifvoid			*i_private; /* fs or device private pointer */
};

?

??????? 所謂"文件", 就是按一定的形式存儲在介質上的信息,所以一個文件其實包含了兩方面的信息,一是存儲的數據本身,二是有關該文件的組織和管理的信息。在內存中, 每個文件都有一個dentry(目錄項)和inode(索引節點)結構,dentry記錄著文件名,上級目錄等信息,正是它形成了我們所看到的樹狀結構;而有關該文件的組織和管理的信息主要存放inode里面,它記錄著文件在存儲介質上的位置與分布。同時dentry->d_inode指向相應的inode結構。dentry與inode是多對一的關系,因為有可能一個文件有好幾個文件名(硬鏈接, hard link, 可以參考這個網頁 http://www.ugrad.cs.ubc.ca/~cs219/CourseNotes/Unix/commands-links.html)。

所有的dentry用d_parent和d_child連接起來,就形成了我們熟悉的樹狀結構。

inode代表的是物理意義上的文件,通過inode可以得到一個數組,這個數組記錄了文件內容的位置,如該文件位于硬盤的第3,8,10塊,那么這個數組的內容就是3,8,10。其索引節點號inode->i_ino,在同一個文件系統中是唯一的,內核只要根據i_ino,就可以計算出它對應的inode在介質上的位置。就硬盤來說,根據i_ino就可以計算出它對應的inode屬于哪個塊(block),從而找到相應的inode結構。但僅僅用inode還是無法描述出所有的文件系統,對于某一種特定的文件系統而言,比如ext3,在內存中用ext3_inode_info描述。他是一個包含inode的"容器"。

fs/ext3/ext3.h

struct ext3_inode_info {__le32	i_data[15];	/* unconverted */__u32	i_flags;
#ifdef EXT3_FRAGMENTS__u32	i_faddr;__u8	i_frag_no;__u8	i_frag_size;
#endifext3_fsblk_t	i_file_acl;__u32	i_dir_acl;__u32	i_dtime;/** i_block_group is the number of the block group which contains* this file's inode.  Constant across the lifetime of the inode,* it is ued for making block allocation decisions - we try to* place a file's data blocks near its inode block, and new inodes* near to their parent directory's inode.*/__u32	i_block_group;unsigned long	i_state_flags;	/* Dynamic state flags for ext3 *//* block reservation info */struct ext3_block_alloc_info *i_block_alloc_info;__u32	i_dir_start_lookup;
#ifdef CONFIG_EXT3_FS_XATTR/** Extended attributes can be read independently of the main file* data. Taking i_mutex even when reading would cause contention* between readers of EAs and writers of regular file data, so* instead we synchronize on xattr_sem when reading or changing* EAs.*/struct rw_semaphore xattr_sem;
#endifstruct list_head i_orphan;	/* unlinked but open inodes *//** i_disksize keeps track of what the inode size is ON DISK, not* in memory.  During truncate, i_size is set to the new size by* the VFS prior to calling ext3_truncate(), but the filesystem won't* set i_disksize to 0 until the truncate is actually under way.** The intent is that i_disksize always represents the blocks which* are used by this file.  This allows recovery to restart truncate* on orphans if we crash during truncate.  We actually write i_disksize* into the on-disk inode when writing inodes out, instead of i_size.** The only time when i_disksize and i_size may be different is when* a truncate is in progress.  The only things which change i_disksize* are ext3_get_block (growth) and ext3_truncate (shrinkth).*/loff_t	i_disksize;/* on-disk additional length */__u16 i_extra_isize;/** truncate_mutex is for serialising ext3_truncate() against* ext3_getblock().  In the 2.4 ext2 design, great chunks of inode's* data tree are chopped off during truncate. We can't do that in* ext3 because whenever we perform intermediate commits during* truncate, the inode and all the metadata blocks *must* be in a* consistent state which allows truncation of the orphans to restart* during recovery.  Hence we must fix the get_block-vs-truncate race* by other means, so we have truncate_mutex.*/struct mutex truncate_mutex;/** Transactions that contain inode's metadata needed to complete* fsync and fdatasync, respectively.*/atomic_t i_sync_tid;atomic_t i_datasync_tid;struct inode vfs_inode;
};


?

__le32 i_data[15]這個數組就是上一段中所提到的那個數組。

注意,在遙遠的2.4的古代,不同文件系統索引節點的內存映像(ext3_inode_info,reiserfs_inode_info,msdos_inode_info ...)都是用一個union內嵌在inode數據結構中的. 但inode作為一種非?;镜臄祿Y構而言,這樣搞太大了,不利于快速的分配和回收。但是后來發明了container_of(...)這種方法后,就把union移到了外部,我們可以用類似container_of(inode, struct ext3_inode_info, vfs_inode),從inode出發,得到其的"容器"。

dentry和inode終究都是在內存中的,它們的原始信息必須要有一個載體。否則斷電之后豈不是玩完了?且聽我慢慢道來。

文件可以分為磁盤文件,設備文件,和特殊文件三種。設備文件暫且不表。

磁盤文件
就磁盤文件而言,dentry和inode的載體在存儲介質(磁盤)上。對于像ext3這樣的磁盤文件來說,存儲介質中的目錄項和索引節點載體如下,

fs/ext3/ext3.h

struct ext3_inode {__le16	i_mode;		/* File mode */__le16	i_uid;		/* Low 16 bits of Owner Uid */__le32	i_size;		/* Size in bytes */__le32	i_atime;	/* Access time */__le32	i_ctime;	/* Creation time */__le32	i_mtime;	/* Modification time */__le32	i_dtime;	/* Deletion Time */__le16	i_gid;		/* Low 16 bits of Group Id */__le16	i_links_count;	/* Links count */__le32	i_blocks;	/* Blocks count */__le32	i_flags;	/* File flags */union {struct {__u32  l_i_reserved1;} linux1;struct {__u32  h_i_translator;} hurd1;struct {__u32  m_i_reserved1;} masix1;} osd1;				/* OS dependent 1 */__le32	i_block[EXT3_N_BLOCKS];/* Pointers to blocks */__le32	i_generation;	/* File version (for NFS) */__le32	i_file_acl;	/* File ACL */__le32	i_dir_acl;	/* Directory ACL */__le32	i_faddr;	/* Fragment address */union {struct {__u8	l_i_frag;	/* Fragment number */__u8	l_i_fsize;	/* Fragment size */__u16	i_pad1;__le16	l_i_uid_high;	/* these 2 fields    */__le16	l_i_gid_high;	/* were reserved2[0] */__u32	l_i_reserved2;} linux2;struct {__u8	h_i_frag;	/* Fragment number */__u8	h_i_fsize;	/* Fragment size */__u16	h_i_mode_high;__u16	h_i_uid_high;__u16	h_i_gid_high;__u32	h_i_author;} hurd2;struct {__u8	m_i_frag;	/* Fragment number */__u8	m_i_fsize;	/* Fragment size */__u16	m_pad1;__u32	m_i_reserved2[2];} masix2;} osd2;				/* OS dependent 2 */__le16	i_extra_isize;__le16	i_pad1;
};

?

fs/ext3/ext3.h

struct ext3_dir_entry_2 {__le32	inode;			/* Inode number */__le16	rec_len;		/* Directory entry length */__u8	name_len;		/* Name length */__u8	file_type;char	name[EXT3_NAME_LEN];	/* File name */
};


__le32 i_block[EXT3_N_BLOCKS];

i_block數組指示了文件的內容所存放的地點(在硬盤上的位置)。

ext3_inode是放在索引節點區,而ext3_dir_entry_2是以文件內容的形式存放在數據區。我們只要知道了ino,由于ext3_inode大小已知,我們就可以計算出ext3_inode在索引節點區的位置( ino * sizeof(ext3_inode) ),而得到了ext3_inode,我們根據i_block就可以知道這個文件的數據存放的地點。將磁盤上ext3_inode的內容讀入到ext3_inode_info中的函數是ext3_read_inode()。以一個有100 block的硬盤為例,一個文件系統的組織布局大致如下圖。位圖區中的每一位表示每一個相應的對象有沒有被使用。

?

特殊文件
特殊文件在內存中有inode和dentry數據結構,但是不一定在存儲介質上有"索引節點",它斷電之后的確就玩完了,所以不需要什么載體。當從一個特殊文件讀時,所讀出的數據是由系統內部按一定的規則臨時生成的,或從內存中收集,加工出來的。sysfs里面就是典型的特殊文件。它存儲的信息都是由系統動態的生成的,它動態的包含了整個機器的硬件資源情況。從sysfs讀寫就相當于向kobject層次結構提取數據。

還請注意, 我們談到目錄項和索引節點時,有兩種含義。一種是在存儲介質(硬盤)中的(如ext3_inode),一種是在內存中的,后者是根據前者生成的。內存中的表示就是dentry和inode,它是VFS中的一層,不管什么樣的文件系統,最后在內存中描述它的都是dentry和inode結構。我們使用不同的文件系統,就是將它們各自的文件信息都抽象到dentry和inode中去。這樣對于高層來說,我們就可以不關心底層的實現,我們使用的都是一系列標準的函數調用。這就是VFS的精髓,實際上就是面向對象。

我們在進程中打開一個文件F,實際上就是要在內存中建立F的dentry,和inode結構,并讓它們與進程結構聯系來,把VFS中定義的接口給接起來。我們來看一看這個經典的圖。這張圖之于文件系統,就像每天愛你多一些之于張學友,番茄炒蛋之于復旦南區食堂,刻骨銘心。

?

總結

以上是生活随笔為你收集整理的Linux那些事儿之我是Sysfs(7)dentry与inode的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。