7.虛擬文件系統(tǒng)

虛擬文件系統(tǒng)

虛擬文件系統(tǒng)(VFS)作為內(nèi)核子系統(tǒng),為用戶空間程序提供了文件和文件系統(tǒng)相關的接口。系統(tǒng)中所有的文件系統(tǒng)不但依賴VFS共存,而且也依靠VFS系統(tǒng)協(xié)同工作。通過虛擬文件系統(tǒng),程序可以利用標準的Unix系統(tǒng)調(diào)用不同的文件系統(tǒng),甚至在不同介質(zhì)上的文件系統(tǒng)進行讀寫操作。

1.文件系統(tǒng)抽象層

Linux可以使用通用接口對所有類型的文件系統(tǒng)進行操作,是因為內(nèi)核在它的文件系統(tǒng)接口上建立了一個抽象層,使得Linux能夠支持各種文件系統(tǒng),即便他們在功能和行為上存在很大差別。

VFS抽象層之所以能夠銜接各種各樣的文件系統(tǒng),是因為它定義了所有文件系統(tǒng)都支持的、基本的、概念是的接口和數(shù)據(jù)結構。例如用戶進程進行下面寫操作:

ret = write(fd, buf, len);

該系統(tǒng)調(diào)用將buf指針指向長為len字節(jié)的數(shù)據(jù)寫入文件描述符fd對應的文件的當前位置。這個系統(tǒng)調(diào)用首先被一個通用調(diào)用sys_write()處理,sys_write()函數(shù)找到fd所在的文件系統(tǒng)實際給出的是哪個寫操作,然后再執(zhí)行該操作。

write()執(zhí)行過程

2.Unix文件系統(tǒng)

從本質(zhì)上文件系統(tǒng)是特殊的數(shù)據(jù)分層存儲結構,包括文件、目錄和相關的控制信息。文件系統(tǒng)的通用操作包含創(chuàng)建、刪除和安裝等。

Unix使用了四種和文件系統(tǒng)相關的傳統(tǒng)抽象概念:文件目錄項、索引節(jié)點安裝點(掛載點,mount point)

  • 文件,一個有序字節(jié)串,字節(jié)串的第一個字節(jié)是文件的頭,最后一個字節(jié)是文件的尾。與Unix文件形成對比的是面向記錄的文件系統(tǒng)(如OpenVMS的File-11),面向記錄的文件系統(tǒng)提供更豐富、更結構化的表示,而簡單的面向字節(jié)流的Unix則以簡單性和靈活性為優(yōu)點
  • 目錄,文件通過目錄組織。文件目錄好比一個文件夾,用來容納相關文件,同時目錄也可以層層嵌套。例如/home/file是文件路徑的例子,根目錄為/,homefile為目錄。Unix中,目錄也是普通文件,可以執(zhí)行文件的操作
  • 索引節(jié)點,Unix系統(tǒng)將文件的相關信息和文件本身分開,例如控制權限、大小、擁有者、創(chuàng)建時間等。文件相關信息又稱文件的元數(shù)據(jù),存儲在一個單獨的數(shù)據(jù)結構中,該結構稱為索引節(jié)點(inode)
  • 安裝點,文件系統(tǒng)被安裝在一個特定的安裝點,文件系統(tǒng)的安裝位置

Unix文件系統(tǒng)在物理磁盤上,也是按照上述方式存儲。Unix中文件的概念從物理上被映射到存儲介質(zhì)。Linux的VFS設計目標就是保證能與支持和實現(xiàn)這些概念的文件系統(tǒng)協(xié)同工作。例如像FAT或NTFS這樣的非Unix風格文件系統(tǒng),經(jīng)過封裝提供符合這些概念的界面(目的是用于支持inode)。

3.VFS對象及數(shù)據(jù)結構

VFS采用了面向?qū)ο蟮脑O計思路,因為使用的C語言,因此內(nèi)核的數(shù)據(jù)結構都是用C語言的結構體,這些結構體包含數(shù)據(jù)和操作數(shù)據(jù)的函數(shù)指針,其中操作函數(shù)由具體的文件系統(tǒng)實現(xiàn)。

VFS有四個主要的對象類型,分別是:

  • 超級塊對象,代表一個具體已安裝的文件系統(tǒng)
  • 索引節(jié)點對象,代表一個具體文件
  • 目錄項對象,代表一個目錄項,是路徑的組成部分
  • 文件對象,代表由進程打開的文件

每個主要對象都包含一個操作對象,這些操作對象描述了內(nèi)核針對主要對象可以使用的方法:

  • super_operations對象,其中包括內(nèi)核對文件系統(tǒng)所能調(diào)用的方法,例如write_inode()sync_fs等方法
  • inode_operations對象,其中包括內(nèi)核對特定文件所能調(diào)用的方法,比如create()link()等方法
  • dentry_operations對象,其中包括內(nèi)核對特定目錄所能調(diào)用的方法,比如d_compare()d_delete()等方法
  • file_operations對象,其中包括進程針對已打開文件所能調(diào)用的方法,比如read()write()等方法

注意,上述的操作對象均是指的結構體,上面4個對象名稱就是對應結構體名稱。

4.超級塊對象

各種文件系統(tǒng)都必須實現(xiàn)超級塊對象,該對象用于存儲特定文件系統(tǒng)的信息,通常包括對應于存放在磁盤特定扇區(qū)的文件系統(tǒng)超級塊或文件系統(tǒng)控制塊(所以稱為超級塊對象)。對于非基于磁盤的文件系統(tǒng)(如基于內(nèi)存的sysfs),它們會在使用現(xiàn)場創(chuàng)建超級塊并保存到內(nèi)存中。

超級塊對象由super_block結構體表示,定義在文件<linux/fs.h>,下面給出它的結構和各個域描述:

struct super_block {
        struct list_head        s_list;            /* list of all superblocks */
        dev_t                   s_dev;             /* identifier */
        unsigned long           s_blocksize;       /* block size in bytes */
        unsigned long           s_old_blocksize;   /* old block size in bytes */
        unsigned char           s_blocksize_bits;  /* block size in bits */
        unsigned char           s_dirt;            /* dirty flag */
        unsigned long long      s_maxbytes;        /* max file size */
        struct file_system_type s_type;            /* filesystem type */
        struct super_operations s_op;              /* superblock methods */
        struct dquot_operations *dq_op;            /* quota methods */
        struct quotactl_ops     *s_qcop;           /* quota control methods */
        struct export_operations *s_export_op;     /* export methods */
        unsigned long            s_flags;          /* mount flags */
        unsigned long            s_magic;          /* filesystem's magic number */
        struct dentry            *s_root;          /* directory mount point */
        struct rw_semaphore      s_umount;         /* unmount semaphore */
        struct semaphore         s_lock;           /* superblock semaphore */
        int                      s_count;          /* superblock ref count */
        int                      s_syncing;        /* filesystem syncing flag */
        int                      s_need_sync_fs;   /* not-yet-synced flag */
        atomic_t                 s_active;         /* active reference count */
        void                     *s_security;      /* security module */
        struct list_head         s_dirty;          /* list of dirty inodes */
        struct list_head         s_io;             /* list of writebacks */
        struct hlist_head        s_anon;           /* anonymous dentries */
        struct list_head         s_files;          /* list of assigned files */
        struct block_device      *s_bdev;          /* associated block device */
        struct list_head         s_instances;      /* instances of this fs */
        struct quota_info        s_dquot;          /* quota-specific options */
        char                     s_id[32];         /* text name */
        void                     *s_fs_info;       /* filesystem-specific info */
        struct semaphore         s_vfs_rename_sem; /* rename semaphore */
};

創(chuàng)建,管理和銷毀超級塊對象的代碼位于文件<fs/super.c>中,超級塊對象通過alloc_super()函數(shù)創(chuàng)建并初始化。在文件系統(tǒng)安裝時,內(nèi)核會調(diào)用該函數(shù)以便從磁盤讀取文件系統(tǒng)超級塊,并且將其信息填充到內(nèi)存中的超級塊對象中。其中最重要的一個是s_op,指向超級塊的操作函數(shù)表,由super_operations結構體表示,定義在<linux/fs.h>中,如下:

struct super_operations {
        struct inode *(*alloc_inode) (struct super_block *sb);
        void (*destroy_inode) (struct inode *);
        void (*read_inode) (struct inode *);
        void (*dirty_inode) (struct inode *);
        void (*write_inode) (struct inode *, int);
        void (*put_inode) (struct inode *);
        void (*drop_inode) (struct inode *);
        void (*delete_inode) (struct inode *);
        void (*put_super) (struct super_block *);
        void (*write_super) (struct super_block *);
        int (*sync_fs) (struct super_block *, int);
        void (*write_super_lockfs) (struct super_block *);
        void (*unlockfs) (struct super_block *);
        int (*statfs) (struct super_block *, struct statfs *);
        int (*remount_fs) (struct super_block *, int *, char *);
        void (*clear_inode) (struct inode *);
        void (*umount_begin) (struct super_block *);
        int (*show_options) (struct seq_file *, struct vfsmount *);
};

一個文件系統(tǒng)要寫自己的超級塊,需要調(diào)用:sb->s_op->write_super(sb)這里的sb是指向文件系統(tǒng)超級塊的指針,沿著該指針進入超級塊操作函數(shù)表,并從表中取得希望得到的write_super()函數(shù),該函數(shù)執(zhí)行寫入超級塊的實際操作。

5.索引節(jié)點對象

索引節(jié)點對象包含了內(nèi)核在操作文件或目錄(目錄在Unix里也是文件啊)時需要的全部信息。對于Unix風格的文件系統(tǒng)來說,這些信息可以從磁盤的索引節(jié)點直接讀取。另外無論什么文件系統(tǒng),索引節(jié)點對象必須在內(nèi)存中創(chuàng)建,以便于文件系統(tǒng)使用。

索引節(jié)點對象由inode結構體表示,定義在<linux/fs.h>中:

struct inode {
        struct hlist_node       i_hash;              /* hash list */
        struct list_head        i_list;              /* list of inodes */
        struct list_head        i_dentry;            /* list of dentries */
        unsigned long           i_ino;               /* inode number */
        atomic_t                i_count;             /* reference counter */
        umode_t                 i_mode;              /* access permissions */
        unsigned int            i_nlink;             /* number of hard links */
        uid_t                   i_uid;               /* user id of owner */
        gid_t                   i_gid;               /* group id of owner */
        kdev_t                  i_rdev;              /* real device node */
        loff_t                  i_size;              /* file size in bytes */
        struct timespec         i_atime;             /* last access time */
        struct timespec         i_mtime;             /* last modify time */
        struct timespec         i_ctime;             /* last change time */
        unsigned int            i_blkbits;           /* block size in bits */
        unsigned long           i_blksize;           /* block size in bytes */
        unsigned long           i_version;           /* version number */
        unsigned long           i_blocks;            /* file size in blocks */
        unsigned short          i_bytes;             /* bytes consumed */
        spinlock_t              i_lock;              /* spinlock */
        struct rw_semaphore     i_alloc_sem;         /* nests inside of i_sem */
        struct semaphore        i_sem;               /* inode semaphore */
        struct inode_operations *i_op;               /* inode ops table */
        struct file_operations  *i_fop;              /* default inode ops */
        struct super_block      *i_sb;               /* associated superblock */
        struct file_lock        *i_flock;            /* file lock list */
        struct address_space    *i_mapping;          /* associated mapping */
        struct address_space    i_data;              /* mapping for device */
        struct dquot            *i_dquot[MAXQUOTAS]; /* disk quotas for inode */
        struct list_head        i_devices;           /* list of block devices */
        struct pipe_inode_info  *i_pipe;             /* pipe information */
        struct block_device     *i_bdev;             /* block device driver */
        unsigned long           i_dnotify_mask;      /* directory notify mask */
        struct dnotify_struct   *i_dnotify;          /* dnotify */
        unsigned long           i_state;             /* state flags */
        unsigned long           dirtied_when;        /* first dirtying time */
        unsigned int            i_flags;             /* filesystem flags */
        unsigned char           i_sock;              /* is this a socket? */
        atomic_t                i_writecount;        /* count of writers */
        void                    *i_security;         /* security module */
        __u32                   i_generation;        /* inode version number */
        union {
                void            *generic_ip;         /* filesystem-specific info */
        } u;
};

一個索引節(jié)點代表一個文件,它也可以是設備或管道這種特殊文件。因此在索引節(jié)點對象中有一些特殊文件相關項,比如i_pipe代表有名管道數(shù)據(jù)結構,i_bdev指向塊設備結構,在最新內(nèi)核版本里面它們都是在一個union里表示這個索引節(jié)點只能是某一種文件。

和超級塊類似,對索引節(jié)點的操作調(diào)用方式如下:

i->i_op->truncate(i)

i指向給定的索引節(jié)點。索引節(jié)點的操作結構體inode_operations()結構體定義在文件<linux/fs.h>中:

struct inode_operations {
        int (*create) (struct inode *, struct dentry *,int);
        struct dentry * (*lookup) (struct inode *, struct dentry *);
        int (*link) (struct dentry *, struct inode *, struct dentry *);
        int (*unlink) (struct inode *, struct dentry *);
        int (*symlink) (struct inode *, struct dentry *, const char *);
        int (*mkdir) (struct inode *, struct dentry *, int);
        int (*rmdir) (struct inode *, struct dentry *);
        int (*mknod) (struct inode *, struct dentry *, int, dev_t);
        int (*rename) (struct inode *, struct dentry *, struct inode *, struct dentry *);
        int (*readlink) (struct dentry *, char *, int);
        int (*follow_link) (struct dentry *, struct nameidata *);
        int (*put_link) (struct dentry *, struct nameidata *);
        void (*truncate) (struct inode *);
        int (*permission) (struct inode *, int);
        int (*setattr) (struct dentry *, struct iattr *);
        int (*getattr) (struct vfsmount *, struct dentry *, struct kstat *);
        int (*setxattr) (struct dentry *, const char *,const void *, size_t, int);
        ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
        ssize_t (*listxattr) (struct dentry *, char *, size_t);
        int (*removexattr) (struct dentry *, const char *);
};

從上面還有可以看到很多跟linux指令相關的函數(shù),例如mkdir。

6.目錄項對象

雖然VFS把目錄當作文件對待,但是為了方便查找,VFS引入了目錄項概念。例如/bin/vi/、binvi都是目錄項對象,前兩個是文件,后一個是普通文件。解析一個文件路徑是耗時的常規(guī)字符串比較過程,因此VFS引入目錄項簡化這個過程。

目錄項對象由dentry結構體表示,定義在文件<linux/dcache.h>中:

struct dentry {
        atomic_t                 d_count;      /* usage count */
        unsigned long            d_vfs_flags;  /* dentry cache flags */
        spinlock_t               d_lock;       /* per-dentry lock */
        struct inode             *d_inode;     /* associated inode */
        struct list_head         d_lru;        /* unused list */
        struct list_head         d_child;      /* list of dentries within */
        struct list_head         d_subdirs;    /* subdirectories */
        struct list_head         d_alias;      /* list of alias inodes */
        unsigned long            d_time;       /* revalidate time */
        struct dentry_operations *d_op;        /* dentry operations table */
        struct super_block       *d_sb;        /* superblock of file */
        unsigned int             d_flags;      /* dentry flags */
        int                      d_mounted;    /* is this a mount point? */
        void                     *d_fsdata;    /* filesystem-specific data */
        struct rcu_head          d_rcu;        /* RCU locking */
        struct dcookie_struct    *d_cookie;    /* cookie */
        struct dentry            *d_parent;    /* dentry object of parent */
        struct qstr              d_name;       /* dentry name */
        struct hlist_node        d_hash;       /* list of hash table entries */
        struct hlist_head        *d_bucket;    /* hash bucket */
        unsigned char            d_iname[DNAME_INLINE_LEN_MIN]; /* short name */
};

目錄項對象有三個有效狀態(tài):被使用,未被使用負狀態(tài)。

  • 被使用,目錄項分配了一個有效索引節(jié)點,并且該對象存在使用者,不能被丟棄
  • 未被使用,目錄項分配了一個有效索引節(jié)點,但是VFS中沒有使用它,該目錄項指向一個有效對象,被保存在緩存中以便需要時再使用它,如果要回收內(nèi)存,可以撤銷未使用的目錄項
  • 負狀態(tài),或者說無效目錄項,沒有對應有效索引節(jié)點,因為索引節(jié)點被刪除了,或者路徑不正確,但是目錄項仍然保留,以便快速解析路徑查詢,如果有需要,可以撤銷它,實際上負狀態(tài)的目錄項也很少被使用

如果VFS層遍歷路徑名中所有的元素并將它們逐個地解析成目錄項對象,還要達到最深層目錄,將是一件費力的工作,因此內(nèi)核將目錄項對象緩存在目錄項緩存中(dcache),目錄項緩存包括三個主要部分:

  • 被使用的目錄項鏈表。該鏈表通過索引節(jié)點對象中的i_dentry項鏈接相關的索引節(jié)點,因為一個給定索引節(jié)點可能有多個鏈接,存在多個目錄項對象
  • 最近未被使用雙向鏈表。保存未使用和負狀態(tài)的目錄項對象,頭部是最新加入的,刪除從尾部刪
  • 散列表和散列函數(shù)用于快速地將給定路徑解析為相關目錄項對象

散列表由數(shù)組dentry_hashtable表示,其中每個元素都是一個指向具有相同鍵值的目錄項對象鏈表的指針,數(shù)組大小取決于系統(tǒng)中物理內(nèi)存大小。

實際的散列值由d_hash()函數(shù)計算,它是內(nèi)核提供給文件系統(tǒng)的唯一一個散列函數(shù)。通過d_lookup()函數(shù)查找散列表。

VFS會優(yōu)先從目錄項緩存中搜索路徑名,這樣加快了檢索速度。

目錄項操作dentry_operation結構體指明了VFS操作目錄項的所有方法,定義在<linux/dcache.h>

struct dentry_operations {
        int (*d_revalidate) (struct dentry *, int);
        int (*d_hash) (struct dentry *, struct qstr *);
        int (*d_compare) (struct dentry *, struct qstr *, struct qstr *);
        int (*d_delete) (struct dentry *);
        void (*d_release) (struct dentry *);
        void (*d_iput) (struct dentry *, struct inode *);
};

7.文件對象

文件對象是已經(jīng)打開的文件在內(nèi)存中的表示,包含我們非常熟悉的信息(如訪問模式,當前偏移量等)。文件對象僅僅在進程觀點上表示已打開文件,它反過來指向目錄項對象(再反過來指向索引節(jié)點),其實只有目錄項對象才表示已打開的實際文件。雖然一個文件對應的文件對象不是唯一的,但對應的索引節(jié)點和目錄項對象無疑是唯一的。

文件對象由file結構體表示,定義在<linux/fs.h>中:

struct file {
        struct list_head       f_list;        /* list of file objects */
        struct dentry          *f_dentry;     /* associated dentry object */
        struct vfsmount        *f_vfsmnt;     /* associated mounted fs */
        struct file_operations *f_op;         /* file operations table */
        atomic_t               f_count;       /* file object's usage count */
        unsigned int           f_flags;       /* flags specified on open */
        mode_t                 f_mode;        /* file access mode */
        loff_t                 f_pos;         /* file offset (file pointer) */
        struct fown_struct     f_owner;       /* owner data for signals */
        unsigned int           f_uid;         /* user's UID */
        unsigned int           f_gid;         /* user's GID */
        int                    f_error;       /* error code */
        struct file_ra_state   f_ra;          /* read-ahead state */
        unsigned long          f_version;     /* version number */
        void                   *f_security;   /* security module */
        void                   *private_data; /* tty driver hook */
        struct list_head       f_ep_links;    /* list of eventpoll links */
        spinlock_t             f_ep_lock;     /* eventpoll lock */
        struct address_space   *f_mapping;    /* page cache mapping */
};

類似于目錄項對象,文件對象實際上沒有對應的磁盤數(shù)據(jù)。所以在結構體中沒有代表其對象是否為臟,是否需要寫回磁盤的標志。文件對象通過f_dentry指針指向相關的目錄項對象,目錄項會指向相關索引節(jié)點,索引節(jié)點會記錄是否是臟的。
文件操作的結構體file_operations,定義在<linux/fs.h>中:

struct file_operations {
        struct module *owner;
        loff_t (*llseek) (struct file *, loff_t, int);
        ssize_t (*read) (struct file *, char *, size_t, loff_t *);
        ssize_t (*aio_read) (struct kiocb *, char *, size_t, loff_t);
        ssize_t (*write) (struct file *, const char *, size_t, loff_t *);
        ssize_t (*aio_write) (struct kiocb *, const char *, size_t, loff_t);
        int (*readdir) (struct file *, void *, filldir_t);
        unsigned int (*poll) (struct file *, struct poll_table_struct *);
        int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
        int (*mmap) (struct file *, struct vm_area_struct *);
        int (*open) (struct inode *, struct file *);
        int (*flush) (struct file *);
        int (*release) (struct inode *, struct file *);
        int (*fsync) (struct file *, struct dentry *, int);
        int (*aio_fsync) (struct kiocb *, int);
        int (*fasync) (int, struct file *, int);
        int (*lock) (struct file *, int, struct file_lock *);
        ssize_t (*readv) (struct file *, const struct iovec *,
                          unsigned long, loff_t *);
        ssize_t (*writev) (struct file *, const struct iovec *,
                           unsigned long, loff_t *);
        ssize_t (*sendfile) (struct file *, loff_t *, size_t,
                             read_actor_t, void *);
        ssize_t (*sendpage) (struct file *, struct page *, int,
                             size_t, loff_t *, int);
        unsigned long (*get_unmapped_area) (struct file *, unsigned long,
                                            unsigned long, unsigned long,
                                            unsigned long);
        int (*check_flags) (int flags);
        int (*dir_notify) (struct file *filp, unsigned long arg);
        int (*flock) (struct file *filp, int cmd, struct file_lock *fl);
};

8.文件系統(tǒng)相關的數(shù)據(jù)結構

除了上述幾種VFS基礎對象,內(nèi)核還使用了一些標準數(shù)據(jù)結構用于管理文件系統(tǒng)的其他數(shù)據(jù):file_system_typevfsmount。

linux支持不同文件系統(tǒng),內(nèi)核需要一個特殊結構用于描述文件系統(tǒng):file_system_type。file_system_type結構體定義在<linux/fs.h>中:

struct file_system_type {
        const char              *name;     /* filesystem's name */
        struct subsystem        subsys;    /* sysfs subsystem object */
        int                     fs_flags;  /* filesystem type flags */
        /* the following is used to read the superblock off the disk */
        struct super_block      *(*get_sb) (struct file_system_type *, int,char *, void *);
        /* the following is used to terminate access to the superblock */
        void                    (*kill_sb) (struct super_block *);
        struct module           *owner;    /* module owning the filesystem */
        struct file_system_type *next;     /* next file_system_type in list */
        struct list_head        fs_supers; /* list of superblock objects */
};

get_sb()函數(shù)從磁盤上讀取超級塊,并且在文件系統(tǒng)被安裝時,在內(nèi)存中組裝超級塊對象。每種文件系統(tǒng),不管有多少實例安裝到系統(tǒng)中,還是根本沒安裝,都只有一個file_system_type結構。

更有趣的是,當文件系統(tǒng)被實際安裝時,將有一個vfsmount結構體在安裝點被創(chuàng)建,該結構體用來代表文件系統(tǒng)的實例——換句話說,代表一個安裝點(掛載點)。

vfsmount結構被定義在<linux/mount.h>中:

struct vfsmount {
        struct list_head   mnt_hash;        /* hash table list */
        struct vfsmount    *mnt_parent;     /* parent filesystem */
        struct dentry      *mnt_mountpoint; /* dentry of this mount point */
        struct dentry      *mnt_root;       /* dentry of root of this fs */
        struct super_block *mnt_sb;         /* superblock of this filesystem */
        struct list_head   mnt_mounts;      /* list of children */
        struct list_head   mnt_child;       /* list of children */
        atomic_t           mnt_count;       /* usage count */
        int                mnt_flags;       /* mount flags */
        char               *mnt_devname;    /* device file name */
        struct list_head   mnt_list;        /* list of descriptors */
        struct list_head   mnt_fslink;      /* fs-specific expiry list */
        struct namespace   *mnt_namespace   /* associated namespace */
};

9.與進程相關的數(shù)據(jù)結構

系統(tǒng)中每一個進程都有一組自己打開的文件,像根文件系統(tǒng)、當前工作目錄、安裝點等。有三個數(shù)據(jù)結構將VFS層和系統(tǒng)進程緊密聯(lián)系在一起,它們分別是:file_struct、fs_structnamespace結構體。

file_struct結構體定義在文件<linux/fdtabl.h>中,該結構體由進程描述符files目錄項指向。所有與單個進程相關的信息(如打開的文件及文件描述符)都包含其中,其結構和描述如下:

struct files_struct {
        atomic_t    count;              /* structure's usage count */
        spinlock_t  file_lock;          /* lock protecting this structure */
        int         max_fds;            /* maximum number of file objects */
        int         max_fdset;          /* maximum number of file descriptors */
        int         next_fd;            /* next file descriptor number */
        struct file **fd;               /* array of all file objects */
        fd_set      *close_on_exec;     /* file descriptors to close on exec() */
        fd_set      *open_fds;           /* pointer to open file descriptors */
        fd_set      close_on_exec_init; /* initial files to close on exec() */
        fd_set      open_fds_init;      /* initial set of file descriptors */
        struct file *fd_array[NR_OPEN_DEFAULT]; /* default array of file objects */
};

fd_array數(shù)組指針指向已經(jīng)打開的文件對象,因為NR_OPEN_DEFAULT等于BITS_PER_LONG,所以64位機,該值就為64,表示該數(shù)組最多容納64個文件對象,如果超出,內(nèi)核就會分配一個新數(shù)組,并用fd指針指向它。為了優(yōu)化性能,管理員可以調(diào)整NR_OPEN_DEFAULT的預定義值。

第二個結構體是fs_struct。該結構由檢查描述符fs域指向,包含文件系統(tǒng)和進程相關的信息,定義在<linux/fs_struct.h>中:

 struct fs_struct {
     int users;
     spinlock_t lock;
     seqcount_t seq;
     int umask;
     int in_exec;
     struct path root, pwd;
 };

該結構包含當前進程的當前工作目錄(pwd)和根目錄。

最后一個是namespace結構體,由進程描述符mnt_namespace域指向,它使得每個進程在系統(tǒng)中都能看到唯一的安裝文件系統(tǒng)。定義在文件<linux/mnt_namespace.h>(實際上我沒找到??!)中:

struct namespace {
        atomic_t            count; /* structure usage count */
        struct vfsmount     *root; /* mount object of root directory */
        struct list_head    list;  /* list of mount points */
        struct rw_semaphore sem;   /* semaphore protecting the namespace */
};

默認情況下,所有的進程共享同樣的命名空間。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容