linux挂载

来源:互联网 发布:java int 0xff 编辑:程序博客网 时间:2024/04/30 08:40

在windows操作系统中, 挂载通常是指给磁盘分区(包括被虚拟出来的磁盘分区)分配一个盘符。 第三方软件,如磁盘分区管理软件、虚拟磁盘软件等,通常也附带挂载功能。

 在linux操作系统中, 挂载是指将一个设备(通常是存储设备)挂接到一个已存在的目录上。 我们要访问存储设备中的文件,必须将文件所在的分区挂载到一个已存在的目录上, 然后通过访问这个目录来访问存储设备。

需要理解的是,
linux操作系统将所有的设备都看作文件,
它将整个计算机的资源都整合成一个大的文件目录。
我们要访问存储设备中的文件,必须将文件所在的分区挂载到一个已存在的目录上,
然后通过访问这个目录来访问存储设备。
linux中挂载命令为mount
实例:mount   /dev/hd1   /mnt
mount属于系统调用,会最终调用sys_mount://
 // 参数dev_name 是设备文件名,dir_name 是安装到的目录名,rw_flag 被安装文件的读写标志。// 将被加载的地方必须是一个目录名,并且对应的i 节点没有被其它程序占用。intsys_mount (char *dev_name, char *dir_name, int rw_flag){struct m_inode *dev_i, *dir_i;struct super_block *sb;int dev;// 首先根据设备文件名找到对应的i 节点,并取其中的设备号。// 对于块特殊设备文件,设备号在i 节点的i_zone[0]中。if (!(dev_i = namei (dev_name)))return -ENOENT;dev = dev_i->i_zone[0];// 如果不是块设备文件,则释放刚取得的i 节点dev_i,返回出错码。if (!S_ISBLK (dev_i->i_mode)){iput (dev_i);return -EPERM;}// 释放该设备文件的i 节点dev_i。iput (dev_i);// 根据给定的目录文件名找到对应的i 节点dir_i。if (!(dir_i = namei (dir_name)))return -ENOENT;// 如果该i 节点的引用计数不为1(仅在这里引用),或者该i 节点的节点号是根文件系统的节点// 号1,则释放该i 节点,返回出错码。if (dir_i->i_count != 1 || dir_i->i_num == ROOT_INO){iput (dir_i);return -EBUSY;}// 如果该节点不是一个目录文件节点,则也释放该i 节点,返回出错码。if (!S_ISDIR (dir_i->i_mode)){iput (dir_i);return -EPERM;}// 读取将安装文件系统的超级块,如果失败则也释放该i 节点,返回出错码。if (!(sb = read_super (dev))){iput (dir_i);return -EBUSY;}// 如果将要被安装的文件系统已经安装在其它地方,则释放该i 节点,返回出错码。if (sb->s_imount){iput (dir_i);return -EBUSY;}// 如果将要安装到的i 节点已经安装了文件系统(安装标志已经置位),则释放该i 节点,返回出错码。if (dir_i->i_mount){iput (dir_i);return -EPERM;}// 被安装文件系统超级块的“被安装到i 节点”字段指向安装到的目录名的i 节点。sb->s_imount = dir_i;// 设置安装位置i 节点的安装标志和节点已修改标志。/* 注意!这里没有iput(dir_i) */dir_i->i_mount = 1;           /* 这将在umount 内操作 */dir_i->i_dirt = 1;            /* NOTE! we don't iput(dir_i) */return 0;                     /* we do that in umount */}
总的来说,以上代码基本流程:
1)分析路径开始,准备查找hd1设备的挂节点:根据/dev/hd1线索把硬盘的超级块找到,进而找到s_imount
2)以根目录i节点为起点,得到dev目录文件的i节点
3)从dev目录文件中找到代表hd1设备文件的目录项
4)得到hd1设备文件的i节点号
5)释放dev目录文件的相关内容
6)得到hd1设备文件的i节点
7)获取hd1设备的设备号
8)释放hd1设备文件的i节点
9)获取虚拟盘上的挂节点
10)得到hd1设备文件的超级块
11)读取hd1设备文件的超级块,加载逻辑块位图和i节点位图
12)将hd1设备文件与mnt目录文件的i节点挂接
涉及到的几个关键数据结构
struct buffer_head{char *b_data;            /* pointer to data block (1024 bytes) *///指针。unsigned long b_blocknr; /* block number */// 块号。unsigned short b_dev;      /* device (0 = free) */// 数据源的设备号。unsigned char b_uptodate;   // 更新标志:表示数据是否已更新。unsigned char b_dirt;       /* 0-clean,1-dirty *///修改标志:0 未修改,1 已修改.unsigned char b_count;      /* users using this block */// 使用的用户数。unsigned char b_lock;       /* 0 - ok, 1 -locked */// 缓冲区是否被锁定。struct task_struct *b_wait;   // 指向等待该缓冲区解锁的任务。struct buffer_head *b_prev;   // hash 队列上前一块(这四个指针用于缓冲区的管理)。struct buffer_head *b_next;    // hash 队列上下一块。struct buffer_head *b_prev_free;  // 空闲表上前一块。struct buffer_head *b_next_free;   // 空闲表上下一块。};// 磁盘上的索引节点(i 节点)数据结构。struct d_inode{unsigned short i_mode;          // 文件类型和属性(rwx 位)。unsigned short i_uid;           // 用户id(文件拥有者标识符)。unsigned long i_size;           // 文件大小(字节数)。unsigned long i_time;           // 修改时间(自1970.1.1:0 算起,秒)。unsigned char i_gid;                    // 组id(文件拥有者所在的组)。unsigned char i_nlinks;         // 链接数(多少个文件目录项指向该i 节点)。unsigned short i_zone[9];               // 直接(0-6)、间接(7)或双重间接(8)逻辑块号。// zone 是区的意思,可译成区段,或逻辑块。};// 这是在内存中的i 节点结构。前7 项与d_inode 完全一样。struct m_inode{unsigned short i_mode;          // 文件类型和属性(rwx 位)。unsigned short i_uid;           // 用户id(文件拥有者标识符)。unsigned long i_size;           // 文件大小(字节数)。unsigned long i_mtime;          // 修改时间(自1970.1.1:0 算起,秒)。unsigned char i_gid;                    // 组id(文件拥有者所在的组)。unsigned char i_nlinks;         // 文件目录项链接数。unsigned short i_zone[9];               // 直接(0-6)、间接(7)或双重间接(8)逻辑块号。/* these are in memory also */struct task_struct *i_wait;     // 等待该i 节点的进程。unsigned long i_atime;          // 最后访问时间。unsigned long i_ctime;          // i 节点自身修改时间。unsigned short i_dev;           // i 节点所在的设备号。unsigned short i_num;           // i 节点号。unsigned short i_count;         // i 节点被使用的次数,0 表示该i 节点空闲。unsigned char i_lock;           // 锁定标志。unsigned char i_dirt;                   // 已修改(脏)标志。unsigned char i_pipe;           // 管道标志。unsigned char i_mount;          // 安装标志。unsigned char i_seek;           // 搜寻标志(lseek 时)。unsigned char i_update;         // 更新标志。};// 文件结构(用于在文件句柄与i 节点之间建立关系)struct file{unsigned short f_mode;          // 文件操作模式(RW 位)unsigned short f_flags;         // 文件打开和控制的标志。unsigned short f_count;         // 对应文件句柄(文件描述符)数。struct m_inode *f_inode;        // 指向对应i 节点。off_t f_pos;                            // 文件位置(读写偏移值)。};// 内存中磁盘超级块结构。struct super_block{unsigned short s_ninodes;               // 节点数。unsigned short s_nzones;                        // 逻辑块数。unsigned short s_imap_blocks;   // i 节点位图所占用的数据块数。unsigned short s_zmap_blocks;   // 逻辑块位图所占用的数据块数。unsigned short s_firstdatazone; // 第一个数据逻辑块号。unsigned short s_log_zone_size; // log(数据块数/逻辑块)。(以2 为底)。unsigned long s_max_size;               // 文件最大长度。unsigned short s_magic;                 // 文件系统魔数。/* These are only in memory */struct buffer_head *s_imap[8];  // i 节点位图缓冲块指针数组(占用8 块,可表示64M)。struct buffer_head *s_zmap[8];  // 逻辑块位图缓冲块指针数组(占用8 块)。unsigned short s_dev;                   // 超级块所在的设备号。struct m_inode *s_isup;                 // 被安装的文件系统根目录的i 节点。(isup-super i)struct m_inode *s_imount;               // 被安装到的i 节点。unsigned long s_time;                   // 修改时间。struct task_struct *s_wait;             // 等待该超级块的进程。unsigned char s_lock;                   // 被锁定标志。unsigned char s_rd_only;                        // 只读标志。unsigned char s_dirt;                   // 已修改(脏)标志。};// 磁盘上超级块结构。上面125-132 行完全一样。struct d_super_block{unsigned short s_ninodes;               // 节点数。unsigned short s_nzones;                        // 逻辑块数。unsigned short s_imap_blocks;   // i 节点位图所占用的数据块数。unsigned short s_zmap_blocks;   // 逻辑块位图所占用的数据块数。unsigned short s_firstdatazone; // 第一个数据逻辑块。unsigned short s_log_zone_size; // log(数据块数/逻辑块)。(以2 为底)。unsigned long s_max_size;               // 文件最大长度。unsigned short s_magic;                 // 文件系统魔数。};// 文件目录项结构。struct dir_entry{unsigned short inode;           // i 节点。char name[NAME_LEN];            // 文件名。};


0 0
原创粉丝点击