操作系统真象还原[14章/三]-挂载分区sdb1

本篇比较短小精悍,只针对书上的第14.2.3挂载分区这一小节,在前面我们已经通过fdisk将硬盘划分为了主分区与主扩展分区(主扩展分区又被划分成子扩展分区与逻辑分区),最终我们把主分区以及逻辑分区的信息读入到了ide.c中的partition_list队列中。本节要做的就是将分区的超级块sb,block位图以及inode位图读入到对应的partition的对应属性中,这就称之为分区的挂载,实际上就是将硬盘上分区的相关内容读入到内存的partition数据结构中。

再复习一下分区在硬盘中的结构,以及partition数据结构:

/* 分区结构 */
struct partition {
    uint32_t start_lba;
    uint32_t sec_cnt;
    struct disk* my_disk;
    struct list_elem part_tag;
    char name[8];
    struct super_block* sb;
    struct bitmap block_bitmap;
    struct bitmap inode_bitmap;
    struct list open_inodes;
};

/* 位图结构 */
struct bitmap {
	uint32_t btmp_bytes_len;
	uint8_t *bits;
};

/* 超级块结构 */
struct super_block {
    uint32_t magic;                     //标识文件系统类型

    uint32_t sec_cnt;                   //本分区总扇区数
    uint32_t inode_cnt;                 //本分区中inode数量
    uint32_t part_lba_base;             //本分区起始lba地址

    uint32_t block_bitmap_lba;          //块位图起始扇区lba地址
    uint32_t block_bitmap_sects;      //块位图占用的扇区数量

    uint32_t inode_bitmap_lba;          //i节点位图起始扇区地址
    uint32_t inode_bitmap_sects;      //i节点位图占用扇区数量

    uint32_t inode_table_lba;          //i节点数组起始扇区地址
    uint32_t inode_table_sects;      //i节点数组占用扇区数量

    uint32_t data_start_lba;            //空闲块起始lba地址
    uint32_t root_inode_no;             //根目录所在i节点号
    uint32_t dir_entry_size;            //目录项大小

    uint8_t pad[460];                   //加上460字节,凑够512字节1扇区大小
}__attribute__((packed));

        有了以上的铺垫,我们就可以正式敲代码了,代码的内容其实就是从硬盘中读出对应的数据结构填充到partition的sb属性、block_bitmap属性以及inode_bitmap属性中并将open_inodes队列进行初始化,代码如下(fs.c中):

static bool mount_partition(struct list_elem* pelem, int arg) {
    char* part_name = (char*) arg;
    struct partition* part = elem2entry(struct partition, part_tag, pelem);
    if(!strcmp(part->name, part_name)) {
        cur_part = part;
        /* 从硬盘中读取超级块到partition的sb字段中 */
        part->sb = (struct super_block*) sys_malloc(SECTOR_SIZE);
        if(part->sb == NULL) {
            PANIC("alloc memory failed!");
        }
        ide_read(part->my_disk, part->start_lba + 1, part->sb, 1);
        /* 从硬盘中读取block位图到partition的block_bitmap字段中 */
        part->block_bitmap.bits = (uint8_t*) sys_malloc(part->sb->block_bitmap_sects * SECTOR_SIZE);
        if(part->block_bitmap.bits == NULL) {
            PANIC("alloc memory failed!");
        }
        part->block_bitmap.btmp_bytes_len = part->sb->block_bitmap_sects * SECTOR_SIZE;
        ide_read(part->my_disk, part->sb->block_bitmap_lba, part->block_bitmap.bits, part->sb->block_bitmap_sects);
        /* 从硬盘中读取inode位图到partition的inode_bitmap字段中 */
        part->inode_bitmap.bits = (uint8_t*) sys_malloc(part->sb->inode_bitmap_sects * SECTOR_SIZE);
        if(part->inode_bitmap.bits == NULL) {
            PANIC("alloc memory failed!");
        }
        part->inode_bitmap.btmp_bytes_len = part->sb->inode_bitmap_sects * SECTOR_SIZE;
        ide_read(part->my_disk, part->sb->inode_bitmap_lba, part->inode_bitmap.bits, part->sb->inode_bitmap_sects);
        /* 初始化该分区的open_inodes队列 */
        list_init(&cur_part->open_inodes);
        printk("mount %s done!\n", part->name);
        return true;
    }
    return false;
}

        我们还要在filesys_init函数中调用mount_partition函数,mount_partition函数作为链表的回调函数进行调用。

void filesys_init() {
    uint8_t channel_no = 0, dev_no = 0, part_idx = 0;
    struct super_block* sb_buf = (struct super_block*) sys_malloc(SECTOR_SIZE);

    if(sb_buf == NULL) {
        PANIC("alloc memory failed!");
    }
    printk("searching filesystem......\n");

    while(channel_no < channel_cnt) {
        dev_no = 0;
        while(dev_no < 2) {
            if (dev_no == 0) {
                dev_no++;
                continue;
            }
            struct disk* hd = &channels[channel_no].devices[dev_no];
            struct partition* part = hd->prim_parts;
            while (part_idx < 12) {
                if(part_idx == 4) {
                    part = hd->logic_parts;
                }
                if(part->sec_cnt != 0) {
                    memset(sb_buf, 0, SECTOR_SIZE);
                    ide_read(hd, part->start_lba + 1, sb_buf, 1);
                    if(sb_buf->magic == 0x19970814) {
                        printk("%s has filesystem\n", part->name);
                    } else {
                        printk("formatting %s's partition %s......\n", hd->name, part->name);
                        partition_format(hd, part);
                    }
                }
                part_idx++;
                part++;
            }
            dev_no++;
        }
        channel_no++;
    }
    sys_free(sb_buf);

    /* 这两行代码进行了sdb1分区的挂载 */
    char default_part[8] = "sdb1";
    list_traversal(&partition_list, mount_partition, (int)default_part);
}

        到此,本篇结束,这篇是最近写文件系统最轻松的一篇了,文件系统这部分是真的长,要吐了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值