`
rstevens
  • 浏览: 94445 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Linux内核文件系统学习:虚拟文件系统(多图)

阅读更多
这是我的一篇旧文,发表在 CSDN,现重新进行了整理发表到 JAVAEYE。
分析是基于 Linux内核 2.4.30。

一、概述

Linux 文件系统是相当复杂的,本文只分析虚拟文件系统的实现,对具体的文件系统不涉及。
即使是虚拟文件系统,要在一篇文章中讲清楚也是不可能的,况且我自己的理解也不够透彻。

为什么选择 Linux 2.4.30?因为可以参考《Linux 源码情景分析》一书,减少学习难度。


二、基本概念
先介绍一些文件系统的基本概念:

1、一块磁盘(块设备),首先要按照某种文件系统格式(如 NTFS、EXT2)进行格式化,然后才能在其上进行创建目录、保存文件等操作。
2、 在 Linux 中,有“安装”文件系统和“卸载”文件系统的概念。一块经过格式化的“块设备”(不管是刚刚格式化完的,没有创建任何名录和文件;还是已经创建了目录和文件),只有先被“安装”,才能融入 Linux 的文件系统中,用户才可以在它上面进行正常的文件操作。

3、  Linux 把目录或普通文件,统一看成“目录节点”。通常一个“目录节点”具有两个重要属性:名称以及磁盘上实际对应的数据。本文中,“目录节点”有时简称为“节点”
“符号链接”是一种特殊的目录节点,它只有一个名称,没有实际数据。这个名称指向一个实际的目录节点。

4、  “接口结构”:在 内核代码中,经常可以看到一种结构,其成员全部是函数指针,例如:
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 (*write) (struct file *, 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 datasync);
  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 (*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);
};


这种结构的作用类似与 C++ 中的“接口类”,它是用 C 语言进行软件抽象设计时最重要的工具。通过它,将一组通用的操作抽象出来,核心的代码只针对这种“接口结构”进行操作,而这些函数的具体实现由不同的“子类”去完成。
以这个 file_operations“接口”为例,它是“目录节点”提供的操作接口。不同的文件系统需要提供这些函数的具体实现。

三、虚拟文件系统

什么是虚拟文件系统(后文简称VFS)?
Linux 支持很多种文件系统,如 NTFS、EXT2、EXT3 等等,这些都是某种具体的文件系统的实现。

VFS 是一套代码框架(framework),它处于文件系统的使用者与具体的文件系统之间,将两者隔离开来。这种引入一个抽象层次的设计思想,即“上层不依赖于具体实现,而依赖于接口;下层不依赖于具体实现,而依赖于接口”,就是著名的“依赖反转”,它在 Linux内核中随处可见。





VFS框架的设计,需要满足如下需求:
1、  为上层的用户提供统一的文件和目录的操作接口,如  open, read, write
2、  为下层的具体的文件系统,定义一系列统一的操作“接口”, 如 file_operations, inode_operations, dentry_operation,而具体的文件系统必须实现这些接口,才能融入VFS框架中。

为此,VFS 需要:
1、 定义一套文件系统的统一概念
2、 在这套概念基础上,实现提供给上层用户的操作接口,如 open, read, write 等
3、 提供一套机制,让下层的具体的文件系统可融入 VFS 框架中,如文件系统的“注册”和“安装”


本文重点就是学习VFS的重要概念以及在此基础上的重要操作。

四、VFS核心概念

1、 VFS 通过树状结构来管理文件系统,树状结构的任何一个节点都是“目录节点”
2、 树状结构具有一个“根节点”
3、 VFS 通过“超级块”来了解一个具体文件系统的所有需要的信息。具体文件系统必须先向VFS注册,注册后,VFS就可以获得该文件系统的“超级块”。
4、 具体文件系统可被安装到某个“目录节点”上,安装后,具体文件系统才可以被使用
5、 用户对文件的操作,就是通过VFS 的接口,找到对应文件的“目录节点”,然后调用该“目录节点”对应的操作接口。


例如下图:
1、 绿色代表“根文件系统”
2、 黄色代表某一个文件系统 XXFS
3、 根文件系统安装到“根目录节点”上
4、 XXFS 安装到目录节点B上




五、目录节点 

1、inode 和 file_operations
1、  inode 用以描述“目录节点” ,它描述了一个目录节点物理上的属性,例如大小,创建时间,修改时间、uid、gid 等
2、  file_operations 是“目录节点”提供的操作接口。包括 open, read, wirte, ioctl, llseek, mmap 等操作的实现。
3、  inode 通过成员 i_fop 对应一个 file_operations
4、  打开文件的过程就是寻找 “目录节点”对应的 inode 的过程
5、  文件被打开后,inode 和 file_operation 都已经在内存中建立,file_operations 的指针也已经指向了具体文件系统提供的函数,此后都文件的操作,都由这些函数来完成。

例如打开了一个普通文件 /root/file,其所在文件系统格式是 ext2,那么,内存中结构如下:




2、dentry
本来,inode 中应该包括“目录节点”的名称,但由于符号链接的存在,导致一个物理文件可能有多个文件名,因此把和“目录节点”名称相关的部分从 inode 结构中分开,放在一个专门的 dentry 结构中。这样:
1、  一个dentry 通过成员 d_inode 对应到一个 inode上,寻找 inode 的过程变成了寻找 dentry 的过程。因此,dentry 变得更加关键,inode 常常被 dentry 所遮掩。可以说, dentry 是文件系统中最核心的数据结构,它的身影无处不在。
2、  由于符号链接的存在,导致多个 dentry 可能对应到同一个 inode 上

例如,有一个符号链接 /tmp/abc 指向一个普通文件 /root/file,那么 dentry 与 inode 之间的关系大致如下:





六、超级块

1、super_block 和 super_operations

super_block 保存了文件系统的整体信息,如访问权限;
super_operations 则是“超级块”提供的操作接口

struct super_operations {

            struct inode *(*alloc_inode)(struct super_block *sb);
            void (*destroy_inode)(struct inode *);
            void (*read_inode) (struct inode *);
            void (*read_inode2) (struct inode *, void *) ;
            void (*dirty_inode) (struct inode *);
            void (*write_inode) (struct inode *, int);
            void (*put_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 *);
            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 *);
            struct dentry * (*fh_to_dentry)(struct super_block *sb, __u32 *fh, int len, int fhtype, int parent);
            int (*dentry_to_fh)(struct dentry *, __u32 *fh, int *lenp, int need_parent);
            int (*show_options)(struct seq_file *, struct vfsmount *);
};


我们通过分析“获取一个 inode ”的过程来只理解这个“接口”中两个成员  alloc_inode  和 read_inode 的作用。
在文件系统的操作中,经常需要获得一个“目录节点”对应的 inode,这个 inode 有可能已经存在于内存中了,也可能还没有,需要创建一个新的 inode,并从磁盘上读取相应的信息来填充。
对应的代码是 iget()   (inlcude/linux/fs.h),过程如下:
1、  通过 iget4_locked() 获取 inode。如果 inode 在内存中已经存在,则直接返回;否则创建一个新的 inode
2、  如果是新创建的 inode,通过 super_block->s_op->read_inode() 来填充它。也就是说,如何填充一个新创建的 inode, 是由具体文件系统提供的函数实现的。
 
static inline struct inode *iget(struct super_block *sb, unsigned long ino)
{
            struct inode *inode = iget4_locked(sb, ino, NULL, NULL);


            if (inode && (inode->i_state & I_NEW)) {
                        sb->s_op->read_inode(inode);
                        unlock_new_inode(inode);
            }
            return inode;
}

 
iget4_locked()  首先在全局的 inode hash table 中寻找,如果找不到,则调用 get_new_inode() ,进而调用 alloc_inode() 来创建一个新的 inode
在 alloc_inode() 中可以看到,如果具体文件系统提供了创建 inode 的方法,则由具体文件系统来负责创建,否则采用系统默认的的创建方法。

static struct inode *alloc_inode(struct super_block *sb)
{

            static struct address_space_operations empty_aops;
            static struct inode_operations empty_iops;
            static struct file_operations empty_fops;
            struct inode *inode;

             if (sb->s_op->alloc_inode)
                        inode = sb->s_op->alloc_inode(sb);
            else {
                        inode = (struct inode *) kmem_cache_alloc(inode_cachep, SLAB_KERNEL);
                         if (inode)
                                    memset(&inode->u, 0, sizeof(inode->u));
            }

             if (inode) {
                        struct address_space * const mapping = &inode->i_data;
                        inode->i_sb = sb;
                        inode->i_dev = sb->s_dev;
                        inode->i_blkbits = sb->s_blocksize_bits;
                        inode->i_flags = 0;
                        atomic_set(&inode->i_count, 1);
                        inode->i_sock = 0;
                        inode->i_op = &empty_iops;
                        inode->i_fop = &empty_fops;
                        inode->i_nlink = 1;
                        atomic_set(&inode->i_writecount, 0);
                        inode->i_size = 0;
                        inode->i_blocks = 0;
                        inode->i_bytes = 0;
                        inode->i_generation = 0;
                        memset(&inode->i_dquot, 0, sizeof(inode->i_dquot));
                        inode->i_pipe = NULL;
                        inode->i_bdev = NULL;
                        inode->i_cdev = NULL;

                        mapping->a_ops = &empty_aops;
                        mapping->host = inode;
                        mapping->gfp_mask = GFP_HIGHUSER;
                        inode->i_mapping = mapping;
            }
            return inode;
}


super_block 是在安装文件系统的时候创建的,后面会看到它和其它结构之间的关系。


七、 注册文件系统

一个具体的文件系统,必须首先向VFS注册,才能被使用。

通过register_filesystem() ,可以将一个“文件系统类型”结构 file_system_type注册到内核中一个全局的链表file_systems 上。

文件系统注册的主要目的,就是让 VFS 创建该文件系统的“超级块”结构。

struct file_system_type {

            const char *name;
            int fs_flags;
            struct super_block *(*read_super) (struct super_block *, void *, int);
            struct module *owner;
            struct file_system_type * next;
            struct list_head fs_supers;
};
 
int register_filesystem(struct file_system_type * fs)
{
            int res = 0;
            struct file_system_type ** p;
 
            if (!fs)
                        return -EINVAL;

            if (fs->next)
                        return -EBUSY;

            INIT_LIST_HEAD(&fs->fs_supers);
            write_lock(&file_systems_lock);
            p = find_filesystem(fs->name);

            if (*p)
                        res = -EBUSY;
            else
                        *p = fs;

            write_unlock(&file_systems_lock);
            return res;
}



这个结构中最关键的就是 read_super() 这个函数指针,它就是用于创建并设置 super_block 的目的的。
因为安装一个文件系统的关键一步就是要为“被安装设备”创建和设置一个 super_block,而不同的具体的文件系统的 super_block 有自己特定的信息,因此要求具体的文件系统首先向内核注册,并提供 read_super() 的实现。


八、 安装文件系统
1、  一个经过格式化的块设备,只有安装后,才能融入 Linux 的 VFS 之中。
2、  安装一个文件系统,必须指定一个目录作为安装点。
3、  一个设备可以同时被安装到多个目录上。
4、  如果某个目录下原来有一些文件和子目录,一旦将一个设备安装到目录下后,则原有的文件和子目录消失。因为这个目录已经变成了一个安装点。
5、  一个目录节点下可以同时安装多个设备。


1、“根安装点”、“根设备”和“根文件系统”
安装一个文件系统,除了需要“被安装设备”外,还要指定一个“安装点”。“安装点”是已经存在的一个目录节点。例如把 /dev/sda1 安装到 /mnt/win 下,那么 /mnt/win 就是“安装点”。
可是文件系统要先安装后使用。因此,要使用 /mnt/win 这个“安装点”,必然要求它所在文件系统已也经被安装。
也就是说,安装一个文件系统,需要另外一个文件系统已经被安装。
这是一个鸡生蛋,蛋生鸡的问题:最顶层的文件系统是如何被安装的?
答案是,最顶层文件系统在内核初始化的时候被安装在“根安装点”上的,而根安装点不属于任何文件系统,它对应的 dentry 、inode 等结构是由内核在初始化阶段凭空构造出来的。

最顶层的文件系统叫做“根文件系统”。Linux 在启动的时候,要求用户必须指定一个“根设备”,内核在初始化阶段,将“根设备”安装到“根安装点”上,从而有了根文件系统。这样,文件系统才算准备就绪。此后,用户就可以通过 mount 命令来安装新的设备。
 
2、安装连接件 vfsmount
“安装”一个文件系统涉及“被安装设备”和“安装点”两个部分,安装的过程就是把“安装点”和“被安装设备”关联起来,这是通过一个“安装连接件”结构 vfsmount 来完成的。
vfsmount  将“安装点”dentry 和“被安装设备”的根目录节点 dentry 关联起来。
每安装一次文件系统,会导致:
1、  创建一个 vfsmount
2、  为“被安装设备”创建一个 super_block,并由具体的文件系统来设置这个 super_block。(我们在“注册文件系统”一节将再来分析这一步)
3、  为被安装设备的根目录节点创建 dentry
4、  为被安装设备的根目录节点创建 inode, 并由 super_operations->read_inode() 来设置此 inode
5、  将 super_block 与“被安装设备“根目录节点 dentry 关联起来
6、  将 vfsmount 与“被安装设备”的根目录节点 dentry 关联起来
在内核将根设备安装到“根安装点”上后,内存中有如下结构关系:




现在假设我们在 /mnt/win 下安装了 /dev/sda1, /dev/sda1 下有 dir1,然后又在 dir1 下安装了 /dev/sda2,那么内存中就有了如下的结构关系





九、寻找目标节点
VFS 中一个最关键以及最频繁的操作,就是根据路径名寻找目标节点的 dentry 以及 inode 。
例如要打开 /mnt/win/dir1/abc 这个文件,就是根据这个路径,找到‘abc’ 对应的 dentry ,进而得到 inode 的过程。

1、 寻找过程
寻找过程大致如下:
1、  首先找到根文件系统的根目录节点 dentry 和 inode
2、  由这个 inode 提供的操作接口 i_op->lookup(),找到下一层节点 ‘mnt’ 的 dentry 和 inode
3、  由 ‘mnt’ 的 inode 找到 ‘win’ 的 dentry 和 inode
4、  由于 ‘win’ 是个“安装点”,因此需要找到“被安装设备”/dev/sda1 根目录节点的 dentry 和 inode,只要找到 vfsmount B,就可以完成这个任务。
5、  然后由 /dev/sda1 根目录节点的 inode 负责找到下一层节点 ‘dir1’ 的 dentry 和 inode
6、  由于 dir1 是个“安装点”,因此需要借助 vfsmount C 找到 /dev/sda2 的根目录节点 dentry 和 inode
7、  最后由这个 inode 负责找到 ‘abc’ 的 dentry 和 inode
可以看到,整个寻找过程是一个递归的过程。
完成寻找后,内存中结构如下,其中红色线条是寻找目标节点的路径





现在有两个问题:
1、在寻找过程的第一步,如何得到“根文件系统”的根目录节点的 dentry?
答案是这个 dentry 是被保存在进程的 task_struct 中的。后面分析进程与文件系统关系的时候再说这个。
2、如何寻找 vfsmount B 和 C?
这是接下来要分析的。

2、vfsmount 之间的关系
我们知道, vfsmount A、B、C 之间形成了一种父子关系,为什么不根据 A 来找到 B ,根据 B 找到 C 了?
这是因为一个文件系统可能同时被安装到不同的“安装点”上。
假设把 /dev/sda1 同时安装到 /mnt/win 和 /mnt/linux 下
现在 /mnt/win/dir1 和 /mnt/linux/dir1 对应的是同一个 dentry!!!
然后,又把 /dev/sda2 分别安装到 /mnt/win/dir1 和 /mnt/linux/dir1 下

现在, vfsmount 与 dentry 之间的关系大致如下。可以看到:
1、  现在有四个 vfsmount A, B, C, D
2、  A 和B对应着不同的安装点 ‘win’ 和 ‘linux’,但是都指向 /dev/sda1 根目录的 dentry
3、  C 和D 对应着这相同的安装点 ‘dir1’,也都指向 /dev/sda2 根目录的 dentry
4、  C 是 A 的 child, A是 C 的 parent
5、  D 是 B 的 child, B 是 D 的 parent






3、 搜索辅助结构 nameidata
在递归寻找目标节点的过程中,需要借助一个搜索辅助结构 nameidata,这是一个临时结构,仅仅用在寻找目标节点的过程中。
 
struct nameidata {

       struct dentry *dentry;
       struct vfsmount *mnt;
       struct qstr last;
       unsigned int flags;
       int last_type;
};


在搜索初始化时,创建 nameidata,其中 mnt 指向 current->fs->rootmnt,dentry 指向 current->fs->root
dentry 随着目录节点的深入而不断变化;
而 mnt 则在每进入一个新的文件系统后发生变化
以寻找 /mnt/win/dir1/abc 为例
开始的时候, mnt 指向 vfsmount A,dentry 指向根设备的根目录
随后,dentry  先后指向 ‘mnt’ 和 ‘win’ 对应的 dentry
然后当寻找到 vfsmount B 后,mnt 指向了它,而 dentry 则指向了 /dev/sda1 根目录的 dentry
有了这个结构,上一节的问题就可以得到解决了:
在寻找 /mnt/win/dir1/abc 的过程中,首先找到 A,接下来在要决定选 C 还是 D,因为是从 A 搜索下来的, C 是 A 的 child,因此选择 C 而不是 D;同样,如果是寻找 /mnt/linux/dir1/abc,则会依次选择 B 和D。这就是为什么 nameidata 中要带着一个 vfsmount 的原因。
 

十、文件的打开与读写

1、 “打开文件”结构 file
一个文件每被打开一次,就对应着一个 file 结构。
我们知道,每个文件对应着一个 dentry 和 inode,每打开一个文件,只要找到对应的 dentry 和 inode 不就可以了么?为什么还要引入这个 file 结构?
这是因为一个文件可以被同时打开多次,每次打开的方式也可以不一样。
而dentry 和 inode 只能描述一个物理的文件,无法描述“打开”这个概念。
因此有必要引入 file 结构,来描述一个“被打开的文件”。每打开一个文件,就创建一个 file 结构。

file 结构中包含以下信息:
打开这个文件的进程的 uid,pid
打开的方式
读写的方式
当前在文件中的位置
实际上,打开文件的过程正是建立file, dentry, inode 之间的关联的过程。






2、文件的读写
文件一旦被打开,数据结构之间的关系已经建立,后面对文件的读写以及其它操作都变得很简单。就是根据 fd 找到 file 结构,然后找到 dentry 和 inode,最后通过 inode->i_fop 中对应的函数进行具体的读写等操作即可。
 
十一、进程与文件系统的关联
最后,来了解一下一个进程,与文件系统有哪些关联。


1、 “打开文件”表和 files_struct结构
一个进程可以打开多个文件,每打开一个文件,创建一个 file 结构。所有的 file 结构的指针保存在一个数组中。而文件描述符正是这个数组的下标。
我记得以前刚开始学习编程的时候,怎么都无法理解这个“文件描述符”的概念。现在从内核的角度去看,就很容易明白“文件描述符”是怎么回事了。用户仅仅看到一个“整数”,实际底层对应着的是 file, dentry, inode 等复杂的数据结构。
files_struct 用于管理这个“打开文件”表。

struct files_struct {
    atomic_t count;
    rwlock_t file_lock;    /* Protects all the below members.  Nests inside tsk->alloc_lock */
    int max_fds;
    int max_fdset;
    int next_fd;
    struct file ** fd;    /* current fd array */
    fd_set *close_on_exec;
    fd_set *open_fds;
    fd_set close_on_exec_init;
    fd_set open_fds_init;
    struct file * fd_array[NR_OPEN_DEFAULT];
};


其中的 fd_arrar[] 就是“打开文件”表。

task_struct 中通过成员 files 与 files_struct 关联起来。


2、  struct  fs_struct
task_struct 中与文件系统相关的还有另外一个成员 fs,它指向一个 fs_struct 。
struct fs_struct {

       atomic_t count;
       rwlock_t lock;
       int umask;
       struct dentry * root, * pwd, * altroot;
       struct vfsmount * rootmnt, * pwdmnt, * altrootmnt;
};



其中:
root 指向此进程的“根目录”,通常就是“根文件系统”的根目录 dentry
pwd 指向此进程当前所在目录的 dentry
因此,通过 task_struct->fs->root,就可以找到“根文件系统”的根目录 dentry,这就回答了 5.1 小节的第一个问题。
rootmnt :指向“安装”根文件系统时创建的那个 vfsmount

pwdmnt:指向“安装”当前工作目录所在文件系统时创建的那个 vfsmount
这两个域用于初始化 nameidata 结构。



3、 进程与文件系统的结构关系图
下图描述了进程与文件系统之间的结构关系图:






十二、参考资料
1、《Linux 源码情景分析》上册
2、Linux 2.4.30 源码
  • 大小: 16.6 KB
  • 大小: 16.8 KB
  • 大小: 15.1 KB
  • 大小: 39 KB
  • 大小: 40.6 KB
  • 大小: 16.4 KB
  • 大小: 25.4 KB
  • 大小: 30.8 KB
  • 大小: 10.2 KB
  • 大小: 32.4 KB
分享到:
评论
2 楼 rstevens 2010-12-27  
呵,这是我以前写的,重新整理了贴在这里的
有什么问题,可以一起交流交流
1 楼 liuxuejin 2010-12-25  
好文章啊!不知道小弟有问题可以请教吗?

相关推荐

    Linux服务器配置与管理:Linux系统图形及字符界面.pptx

    Shell是操作系统提供给用户使用的界面(图形、字符),它提供了用户与内核进行交互操作的一种接口。 Shell的分类: 图形Shell : GNOME、KDE 字符Shell(命令行Shell) 3.虚拟控制台的选择与切换 RHEL7默认有6个...

    包含LINUX内核同步、信号、内存、调度、文件系统.rar

    进程调度 位于 下图 Linux 内核整体架构图 中的 内核空间 ; 二、内存管理 内存管理 涉及到 物理内存管理 和 虚拟内存管理 , 是 Linux 内核中 最复杂的模块 ; 虚拟内存管理 包括 : 反向映射 , KSM , MMAP 映射 , ...

    linux源代码分析:Linux操作系统源代码详细

    内容介绍: Linux 拥有现代操作系统所有功能如真正抢先式多任务处理、支持多用户内存保护虚拟内存支持 SMP、UP符合POSIX标准联网、图形用户接口和桌面环境具有快速性、稳定性等特点本书通过分析Linux内核 源代码充分...

    深入Linux内核架构(英文原版Professional Linux® Kernel Architecture)

    主要内容包括多任务、调度和进程管理,物理内存的管理以及内核与相关硬件的交互,用户空间的进程如何访问虚拟内存,如何编写设备驱动程序,模块机制以及虚拟文件系统,Ext文件系统属性和访问控制表的实现方式,内核...

    linux内核调试分析指南

    btrfs文件系统分析 区间树核心代码分析 B树核心代码分析 调试相关子系统 kgdb源码分析 sysrq oprofile kprobes 驱动分析 载入模块符号 ***第三部分:其他工具*** kexec strace ltrace SystemTap MEMWATCH YAMD Magic...

    LINUX操作系统(电子教案,参考答案)

    本章主要介绍了Linux中的文件系统维护与监视。其中包括交换空间、/proc的信息以及各种日志文件和进程记账等。 第12章:图形界面。本章主要介绍了X Window以及它的配置,并且介绍了在KDE环境下汉化的基本思想,用实例...

    Linux指令一周通 (技术图书大系).azw3

    6.24 lsmod 指令:显示Linux内核的模块信息 6.25 minfo指令:显示MS-DOS文件系统的各项参数 6.26 mkkickstart 指令:建立安装的组态文件 6.27 modinfo指令:显示内核信息 6.28 modprobe 指令:自动处理可载入模块 ...

    LINUX编程白皮书 (全集)

    7.2.5 在虚拟文件系统中查找文件 87 7.2.6 卸载文件系统 87 7.2.7 VFS文件系统的inode缓存 87 7.2.8 目录缓存 88 7.3 缓冲区缓存 88 7.3.1 bdflush内核守护进程 90 7.3.2 update进程 90 7.4 /proc文件系统 91 7.5 ...

    LINUX系统管理白皮书

    涵盖的主题包括文件系统、目录、引导和关机、打印、网络兼容性、网络应用、网络登录、安全、用户账号、数据备份等等。此外,还针对TCP/IP网络、电子邮件、硬件问题以及网络的管理与配置,进行了专门讨论。 目录...

    详解Linux内核内存管理架构

    内存管理子系统可能是linux内核中最为复杂的一个子系统,其支持的功能需求众多,如页面映射、页面分配、页面回收、页面交换、冷热页面、紧急页面、页面碎片管理、页面缓存、页面统计等,而且对性能也有很高的要求。...

    Linux编程从入门到精通

    7.2.5 在虚拟文件系统中查找文件 87 7.2.6 卸载文件系统 87 7.2.7 VFS文件系统的inode缓存 87 7.2.8 目录缓存 88 7.3 缓冲区缓存 88 7.3.1 bdflush内核守护进程 90 7.3.2 update进程 90 7.4 /proc文件系统 91 7.5 ...

    linux教程——很使用的那种

    linux中的文件(普通文件或设备文件等)都必须有挂在点,只有挂载到一个目录下才能访问,swap分区是不需要挂载点的,在分区的时候,将文件系统类型选为swap,挂载点自动会变为灰色。一般linux中的swap大小为内存的两倍。...

    linux学习笔记(包含Linux系统和shell编程).rar

    这使得系统以为自己拥有比物理内存更多的可用内存。 内存被划分为若干块,这些块称作页面(page)。内核会将每个内存页面置于物理内存或交换空间中。然后,内核会维护一张内存页面表,指明哪些页面位于物理内存,...

    入门学习Linux常用必会60个命令实例详解doc/txt

    不过目前大多数较新的Linux发行版本(包括红旗 Linux、中软Linux、Mandrake Linux等)都可以自动挂装文件系统,但Red Hat Linux除外。 umount 1.作用 umount命令的作用是卸载一个文件系统,它的使用权限是超级...

    linux编程白皮书

    7.2.5 在虚拟文件系统中查找文件 87 7.2.6 卸载文件系统 87 7.2.7 VFS文件系统的inode缓存 87 7.2.8 目录缓存 88 7.3 缓冲区缓存 88 7.3.1 bdflush内核守护进程 90 7.3.2 update进程 90 7.4 /proc文件系统 91 7.5 ...

    Linux-2.2.26源代码

    Linux 拥有现代操作系统所有的功能,如真正的抢先式多任务处理、支持多用户,内存保护,虚拟内存,支持SMP、UP,符合POSIX标准,联网、图形用户接口和桌面环境。具有快速性、稳定性等特点。 这个资源是一个完整的...

    华中科技大学操作系统课程设计——4.GTK系统监视器

    5 虚拟文件系统(实现的比较简单)(含代码和makefile) 说明:GTK实现的系统监视器,功能如下: 1.CPU各种信息,包括物理信息以及CPU利用率绘图 2.内存各种信息,包括利用率,内存使用率绘图等 3.进程信息,可以杀...

Global site tag (gtag.js) - Google Analytics