### 简介
此文承接上文
简单Linux文件系统数据结构设计,内容是文件系统中核心函数的实现。
申请iNode节点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
| int FileSystem::alloc_inode(unsigned long size, iNode &node,bool is_dentry) { unsigned int blocks_needed = ceil((double)size / s_block.blockSize); if (size>s_block.maxBytes || s_block.inode_remain == 0){ return -1; } if (size == 0){ blocks_needed = 10; } fileDisk.seekg(s_block.inodemap_pos, ios::beg); bool is_end = false; int inode_no = 1; unsigned char* bytes = new unsigned char[s_block.blockSize];
int block_node_num = s_block.blockSize / sizeof(unsigned int); if (blocks_needed <= 10){ } else if (blocks_needed <= (10 + block_node_num)){ blocks_needed += 1; } else if (blocks_needed <= (10 + block_node_num + block_node_num*block_node_num)){ blocks_needed += 2 + block_node_num; } else if (blocks_needed <= (10 + block_node_num + block_node_num*block_node_num + block_node_num*block_node_num*block_node_num)){ blocks_needed += 3 + 2 * block_node_num + block_node_num*block_node_num; } if (blocks_needed > s_block.block_remain){ return -1; } for (int i = 0; i < ceil(s_block.inode_num / (8 * s_block.blockSize)); i++){ if (is_end) break; fileDisk.read((char *)bytes, s_block.blockSize); unsigned char mask = 1; mask = mask << 7; for (int index = 0; index<s_block.blockSize; index++){ if (is_end) break; unsigned char byte = bytes[index]; for (int j = 0; j < 8; j++){ if (!((byte << j)&mask)){ bytes[index] = byte | (1 << (7-j)); fileDisk.seekg(s_block.inodemap_pos + i*s_block.blockSize, ios::beg); fileDisk.write((char *)bytes, s_block.blockSize); is_end = true; break; } inode_no += 1; if (inode_no>s_block.inode_num){ is_end = true; break; } } } } vector<unsigned int> block_list; alloc_blocks(blocks_needed, block_list); node = iNode(inode_no,size,blocks_needed,block_list); node.i_mode = (7<<8)+(7<<4)+7; if (is_dentry){ unsigned short mode = 1; mode = mode << 14; node.i_mode = mode + (7 << 8) + (7 << 4) + 7; } node.i_uid = currUser.u_id; node.i_gid = currUser.u_id; write_inode(node); s_block.inode_remain--; s_block.block_remain -= blocks_needed; seekAndSave<superBlock>(0, s_block); return 1; }
|
申请块
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
| int FileSystem::alloc_blocks(int num, vector<unsigned int> &list){ fileDisk.seekg(s_block.bitmap_pos, ios::beg); bool is_end = false; unsigned int block_no = 1; unsigned char* bytes = new unsigned char[s_block.blockSize]; for (int i = 0; i < ceil(s_block.block_num / (8 * s_block.blockSize)); i++){ if (is_end) break; fileDisk.read((char *)bytes, s_block.blockSize); bool modify = false; unsigned char mask = 1; mask = mask << 7; for (int index = 0; index<s_block.blockSize; index++){ if (is_end) break; unsigned char byte = bytes[index]; for (int j = 0; j < 8; j++){ if (block_no < s_block.first_data_block_no){ block_no++; continue; } if (!((byte << j)&mask)){ bytes[index] = byte | (1 << (7 - j)); byte = bytes[index]; list.push_back(block_no); modify = true; if (num == list.size()){ is_end = true; break; } } block_no += 1; if (block_no>s_block.block_num){ is_end = true; break; } } } if (modify){ fileDisk.seekg(s_block.bitmap_pos + i*s_block.blockSize, ios::beg); fileDisk.write((char *)bytes, s_block.blockSize); } } clearBlockContent(list); int block_per_num = s_block.blockSize / sizeof(unsigned int); if (list.size() <= 10){ } else if (list.size() <= (11 + block_per_num)){ int cnt = 0, i; unsigned int once_no = list[10]; fileDisk.seekg((once_no-1)*s_block.blockSize); for (i = 11; cnt< block_per_num&&i<list.size(); i++, cnt++){ fileDisk.write((char*)&list[i], sizeof(unsigned int)); } list.resize(11); } else if (list.size() <= (12 + 2*block_per_num + block_per_num*block_per_num)){ int cnt=0,i; unsigned int once_no = list[10]; unsigned int twice_no = list[11]; fileDisk.seekg((once_no - 1)*s_block.blockSize); for (i = 12; cnt <block_per_num ; i++,cnt++){ fileDisk.write((char*)&list[i], sizeof(unsigned int)); } vector<unsigned int> once_in_twice; fileDisk.seekg((twice_no - 1)*s_block.blockSize); cnt = 0; for (; cnt<block_per_num; i++,cnt++){ once_in_twice.push_back(list[i]); fileDisk.write((char*)&list[i], sizeof(unsigned int)); } for (auto item : once_in_twice){ fileDisk.seekg((item - 1)*s_block.blockSize); cnt = 0; for (; cnt<block_per_num&&i<list.size(); i++, cnt++){ once_in_twice.push_back(list[i]); fileDisk.write((char*)&list[i], sizeof(unsigned int)); } } list.resize(12); } else if (list.size() <= (13 + 3*block_per_num + 2*block_per_num*block_per_num + block_per_num*block_per_num*block_per_num)){ int cnt = 0, i; unsigned int once_no = list[10]; unsigned int twice_no = list[11]; unsigned int third_no = list[12]; fileDisk.seekg((once_no - 1)*s_block.blockSize); for (i = 13; cnt <block_per_num; i++, cnt++){ fileDisk.write((char*)&list[i], sizeof(unsigned int)); } vector<unsigned int> once_in_twice; fileDisk.seekg((twice_no - 1)*s_block.blockSize); cnt = 0; for (; cnt<block_per_num; i++, cnt++){ once_in_twice.push_back(list[i]); fileDisk.write((char*)&list[i], sizeof(unsigned int)); } for (auto item : once_in_twice){ fileDisk.seekg((item - 1)*s_block.blockSize); cnt = 0; for (; cnt<block_per_num; i++, cnt++){ once_in_twice.push_back(list[i]); fileDisk.write((char*)&list[i], sizeof(unsigned int)); } } vector<unsigned int> twice_in_third; fileDisk.seekg((third_no - 1)*s_block.blockSize); cnt = 0; for (; cnt<block_per_num; i++, cnt++){ twice_in_third.push_back(list[i]); fileDisk.write((char*)&list[i], sizeof(unsigned int)); } once_in_twice.clear(); for (auto item : twice_in_third){ fileDisk.seekg((item - 1)*s_block.blockSize); cnt = 0; for (; cnt<block_per_num; i++, cnt++){ once_in_twice.push_back(list[i]); fileDisk.write((char*)&list[i], sizeof(unsigned int)); } } for (auto item : once_in_twice){ fileDisk.seekg((item - 1)*s_block.blockSize); cnt = 0; for (; cnt<block_per_num&&i<list.size(); i++, cnt++){ once_in_twice.push_back(list[i]); fileDisk.write((char*)&list[i], sizeof(unsigned int)); } } list.resize(13); } return 1; }
|
目录搜索
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| int FileSystem::findDentry(vector<string> list,dentry *&p_dentry,char firstChar,int type) { int ret = 0; p_dentry = curr_dentry; if (firstChar == '/'){ p_dentry = &root_dentry; list.erase(list.begin()); } if (list.size() == 0){ return 1; } for (auto item : list){ ret = 0; if (item == ".."){ p_dentry = p_dentry->parent; ret = 1; } else if (item == "."){ ret = 1; } else{ for (auto child_dentry : p_dentry->child_list){ if (child_dentry->fileName == item){ if (child_dentry->is_dir()){ p_dentry = child_dentry; if (p_dentry->child_list.size() == 0){ InitDentry(*p_dentry); } for (auto item : p_dentry->child_list){ InitDentry(*item); } if (type == FOLDER_TYPE || item != list[list.size() - 1]){ ret = FOLDER_TYPE; break; } } else{ p_dentry = child_dentry; if (type == FILE_TYPE && item == list[list.size() - 1]){ ret = FILE_TYPE; break; } } } } } if (ret == 0){ return ret; } } return ret; }
|
小结
此处只说明了比较难缕清思路的几个函数,其他函数没有作过多的说明,项目地址在GitHub,代码中都有注释,在多进程间同步的方法采用的是:
单SimDisk,多Shell的方式,Shell与SimDisk之间通讯首先要加锁,进程间通讯用的是共享内存的方式。
流程大致如下:
至于如何鉴定Shell对应的用户,采用的是登录后保存token,每次执行名利带上token的方式来校验,校验流程如下: