//--------------------------------------------------------------------------------------------------*/ // 文件系统初始化 void init_fs(void) { File_Desc* p_fd; Inode* p_inode; no_answer = 0; for(p_fd = file_table;p_fd < file_table + MAX_ALL_FILE;p_fd++) p_fd->fd_inode = 0; for(p_inode = inode_table;p_inode < inode_table + MAX_ALL_INODE;p_inode++) p_inode->i_cnt = 0; hd_open(ROOT_DEV); hd_read(ROOT_DEV,fsbuf,512,1); DEV_Super_Block* p_sb = (DEV_Super_Block*)fsbuf; if(p_sb->magic != MAGIC) fs_make(); // 只在建立文件系统的时候调用,调用之后会覆盖之前的文件系统 hd_read(ROOT_DEV,fsbuf,SECTOR_SIZE * INODE_1ST_SECTS,1); // 获取目录inode DEV_Inode* p_devinode = (DEV_Inode*)fsbuf; inode_table[0] = *(Inode*)(p_devinode + 1); // inode_table第0个元素用于存放目录inode inode_table[0].i_dev = ROOT_DEV; inode_table[0].i_cnt = 1; inode_table[0].i_num = 1; p_inode_de = inode_table; }
void main() { hd_writeonechar(0xa4); lcd_writecd(0,0x0c); lcd_writecd(0,0x01); delay_1ms(5); lcd_string(0x96,"0."); while(1) { if(!hd_key) { key_process(hd_keyconvert(hd_read(0x15))); }while(!hd_key); delay_1ms(5); } }
/* 函数功能:删除普通文件 输入参数:文件名 pathname 删除方式 flags 输出参数:成功返回0,失败返回-1 */ int fs_delete(char * pathname,int flags) { DEV_Inode* p_devinode; int inode_nr; Inode* p_inode; Dir_Entry* p_de; int i,j,k; // 读目录文件,获取Dir_Entry 和 inode_nr int file_offset = 0; int de_nr = 0; for(i = 0,inode_nr = 0;i < ROOT_SECTS;i++,file_offset += SECTOR_SIZE) { file_buff_read(fsbuf,p_inode_de,file_offset,SECTOR_SIZE); for(j = 0,p_de = (Dir_Entry*)fsbuf;j < DIR_ENT_PER_SECT;j++,p_de++) { if(strcmp(p_de->name,pathname) == 0) { inode_nr = p_de->inode_nr; de_nr += j; break; } } if(inode_nr != 0) break; de_nr += DIR_ENT_PER_SECT; } // 目录中寻找结束 if(inode_nr == 0) { printk("can not find the file for delete ! %s\n",pathname); return -1; // 待删除的文件不存在 } if(inode_nr < 5) { printk("can not delete this file! %s\n",pathname); return -1; // 前4个文件不能删除。1:"." 2-4:tty0-tty2 } // 检测inode_table中是否有inode_nr,如果没有,则表示没有进程在使用该文件,可以删除 for(p_inode = inode_table;p_inode < inode_table + MAX_ALL_INODE;p_inode++) { if(p_inode->i_num == inode_nr && p_inode->i_cnt != 0) { printk("can not delete the file ! %s\n",pathname); return -1; // 当前有进程在使用该文件,所以不能删除 } } // 设备中释放imap,smap,Dir_Entry // imap int sect = IMAP_1ST_SECTS + inode_nr / 8 / SECTOR_SIZE; hd_read(ROOT_DEV,fsbuf,SECTOR_SIZE * sect,1); fsbuf[inode_nr / 8 % SECTOR_SIZE] &= (U8)~(1 << (inode_nr % 8) ); hd_write(ROOT_DEV,fsbuf,SECTOR_SIZE * sect,1); // smap sect = INODE_1ST_SECTS + inode_nr / INODE_PER_SECT; // 获取devinode hd_read(ROOT_DEV,fsbuf,SECTOR_SIZE * sect,1); p_devinode = (DEV_Inode*)fsbuf; p_devinode += inode_nr % INODE_PER_SECT; int start_sect = p_devinode->i_start_sect; int nr_sects = p_devinode->i_nr_sects; i = start_sect / 8 / SECTOR_SIZE; // 所在扇区号 j = start_sect / 8 % SECTOR_SIZE; // 扇区内字节号 k = start_sect % 8; // 字内位号 //printk("start_sect:%d,i:%d,j:%d,k:%d\n",start_sect + DAT_1ST_SECT,i,j,k); while(nr_sects > 0) // 释放smap { hd_read(ROOT_DEV,fsbuf,SECTOR_SIZE * (i + SMAP_1ST_SECTS),1); while(j < SECTOR_SIZE && nr_sects >0) { if(8 - k >= nr_sects) // 该字节内解决问题 { while(nr_sects-- > 0) { fsbuf[j] &= (char)~(1 << k++); } break; } else // 该字节内解决不了问题 { if(k == 0) // 全0 { fsbuf[j] = 0; nr_sects -= 8; } else // 非全0 { while(k < 8) { fsbuf[j] &= (char)~(1 << k++); nr_sects--; } } j++; k = 0; } } //printk("i:%d,j:%d,k:%d\n",i,j,k); hd_write(ROOT_DEV,fsbuf,SECTOR_SIZE * (i + SMAP_1ST_SECTS),1); i++; j = 0; } // Dir_Entry Dir_Entry de; de.inode_nr = 0; //printk("de_nr:%d ",de_nr); file_buff_write(&de,p_inode_de,de_nr * sizeof(Dir_Entry),sizeof(Dir_Entry)); sync_buff(p_inode_de,0); // 0:不释放缓冲 1:同步之后释放缓冲 // 成功返回0 return 0; }
/* 函数功能:打开文件 输入参数:文件名 pathname 打开方式 flags 进程指针 p_tcb 输出参数:成功返回进程filp中的fd下标,失败返回-1 */ int fs_open(char * pathname,int flags,TCB* p_tcb) { pathname = va2pa(p_tcb->pdb,pathname); DEV_Inode* p_devinode; int inode_nr; File_Desc* p_fd; Inode* p_inode; Dir_Entry* p_de; int i,j; // 读目录文件,寻找pathname,获得其inode_nr int file_offset = 0; for(i = 0,inode_nr = 0;i < ROOT_SECTS;i++,file_offset += SECTOR_SIZE) { file_buff_read(fsbuf,p_inode_de,file_offset,SECTOR_SIZE); for(j = 0,p_de = (Dir_Entry*)fsbuf;j < DIR_ENT_PER_SECT;j++,p_de++) { if(strcmp(p_de->name,pathname) == 0) { inode_nr = p_de->inode_nr; break; } } if(inode_nr != 0) break; } // 目录中寻找结束 if(inode_nr == 0) // 没找到dev_inode { if(flags == O_CREATE) { // 这里应该判断待创建打开的是否是普通文件 inode_nr = create_file(pathname); if(inode_nr == 0) { printk("create_file error! %s\n",pathname); return -1; // 创建文件失败 } } else { printk("no file : %s\n",pathname); return -1; // 没有找到,也没有创建文件 } } //printk("file : %s inode_nr : %d\n",pathname,inode_nr); // 找到了dev_inode编号inode_nr // 查看内存里的inode_table中是否存在该inode int i_dev = ROOT_DEV; Inode* p_inode_empty = 0; Inode* p_inode_empty1 = 0; for(p_inode = inode_table;p_inode < inode_table + MAX_ALL_INODE;p_inode++) { if(p_inode->i_cnt == 0) { if(p_inode_empty == 0) p_inode_empty = p_inode; // 第一个空位 if(p_inode_empty1 == 0 && p_inode->i_dev == 0 && p_inode->i_num == 0) p_inode_empty1 = p_inode; // 第一个从未被使用过的空位 } if(p_inode->i_dev != i_dev) continue; if(p_inode->i_num != inode_nr) continue; break; } int new_inode = 0; if(p_inode >= inode_table + MAX_ALL_INODE) // 不在inode_table里,需要手动添加 { // 在inode_table中寻找一个空位 if(p_inode_empty1 != 0) { p_inode = p_inode_empty1; } else { if(p_inode_empty == 0) { printk("inode_table full : %s----",pathname); return -1; // inode_table无空位 } p_inode = p_inode_empty; } new_inode = 1; // 用于判断该inode是否是新添加的 } // 此时p_inode的i_dev i_num正确,但是i_cnt可能是0。即:现在找到的inode可能是正在被其他进程共享的,也可能是被其他进程废弃的 // 在file_table中寻找一个空位 for(p_fd = file_table;p_fd < file_table + MAX_ALL_FILE;p_fd++) { if(p_fd->fd_inode == 0) break; } //printk(" p_fd : %d \n",p_fd - file_table); if(p_fd >= file_table + MAX_ALL_FILE) { printk("file_table full : %s----",pathname); return -1; // file_table无空位 } // 在进程filp数组中寻找一个空位 for(i = 0;i < MAX_TASK_FILE;i++) { if(p_tcb->filp[i] == 0) break; } if(i >= MAX_TASK_FILE) { printk("filp full : %s----",pathname); return -1; // filp无空位 } // 填充空位信息 p_tcb->filp[i] = p_fd; p_fd->fd_mode = RD_WR; p_fd->fd_pos = 0; p_fd->fd_inode = p_inode; p_inode->i_cnt++; if(new_inode == 1) // 新添加的inode,需要赋值 { //printk("new inode : %d\n",inode_nr); // 获取dev_inode指针 hd_read(ROOT_DEV,fsbuf,SECTOR_SIZE * (INODE_1ST_SECTS + inode_nr / INODE_PER_SECT),1); p_devinode = (DEV_Inode*)fsbuf; p_devinode += inode_nr % INODE_PER_SECT; // 赋值 p_inode->i_mode = p_devinode->i_mode; p_inode->i_size = p_devinode->i_size; p_inode->i_start_sect = p_devinode->i_start_sect; p_inode->i_nr_sects = p_devinode->i_nr_sects; p_inode->i_dev = ROOT_DEV; p_inode->i_num = inode_nr; } // 返回filp中的下标 //printk("file open : %s ----",pathname); if(p_inode->i_mode == I_MODE_CHAR) // 字符设备文件 { MSG msg; msg.type = TTY_MSG_UNION; msg.msg_union.tty_msg.para = DEV_OPEN; msg.msg_union.tty_msg.sub_device = MINOR(p_inode->i_start_sect); // 字符设备的i_start_sect即设备号 //printk("sub_device : %d ",msg.msg_union.tty_msg.sub_device); disable_int(); if(tty_has_msg_tmp == 0) { assert(sendrecv(BOTH,dd_map[MAJAR(p_inode->i_start_sect)],&msg) == 0); } enable_int(); } //printk(" i : %d----",i); return i; }
/* 函数功能:创建普通文件 输入参数:文件名 pathname 输出参数:0 创建失败,非0 新文件在设备中的inode_nr */ int create_file(char * pathname) { int inode_nr = 0; int start_sect = 0; int i,j,k; // 在imap中找一个空位 for(i = 0;i < NR_IMAP_SECTS ;i++) { hd_read(ROOT_DEV,fsbuf,SECTOR_SIZE * (IMAP_1ST_SECTS + i),1); for(j = 0;j < SECTOR_SIZE;j++) { if(fsbuf[j] == (char)0xff) continue; for(k = 0;k < 8;k++) { if(( fsbuf[j] & (1<<k) ) == 0) { // 此时第i扇区,第j字节,第k位为待找的空位 //printk("imap find3\n"); inode_nr = SECTOR_SIZE * i * 8 + j * 8 + k; if(inode_nr == 0) continue; //printk("imap find4,inode_nr: %d\n",inode_nr); fsbuf[j] |= (1 << k); hd_write(ROOT_DEV,fsbuf,SECTOR_SIZE * (IMAP_1ST_SECTS + i),1); break; } } if(inode_nr != 0) break; } if(inode_nr != 0) break; } if(inode_nr == 0) { printk("imap full----"); return 0; // 没有空位 } // 在smap中找 inode_nr对应的 SECTS_PER_FILE 个连续空位,然后全部置1 for(i = 0;i < NR_SMAP_SECTS;i++) // { hd_read(ROOT_DEV,fsbuf,SECTOR_SIZE * (SMAP_1ST_SECTS + i),1); for(j = 0;j < SECTOR_SIZE;j++) { if(fsbuf[j] == (char)0xff) continue; for(k = 0;k < 8;k++) { if((fsbuf[j] & (1 << k)) == 0) { // 此时第i扇区,第j字节,第k位为待找的空位 //printk("i:%d j:%d k:%d\n",i,j,k); start_sect = SECTOR_SIZE * i * 8 + j * 8 + k; int nr_sects = SECTS_PER_FILE; while(nr_sects > 0) // 填充smap { hd_read(ROOT_DEV,fsbuf,SECTOR_SIZE * (i + SMAP_1ST_SECTS),1); while(j < SECTOR_SIZE && nr_sects >0) { if(8 - k >= nr_sects) // 该字节内解决问题 { while(nr_sects-- > 0) { if(fsbuf[j] & (char)(1 << k)) { printk("i:%d j:%d k:%d\n",i,j,k); printk("OMG retry1!\n"); goto repeat; } fsbuf[j] |= (char)(1 << k++); } hd_write(ROOT_DEV,fsbuf,SECTOR_SIZE * (i + SMAP_1ST_SECTS),1); goto smapOK; } else // 该字节内解决不了问题 { if(k == 0) // 全1 { if(fsbuf[j] != 0) { printk("i:%d j:%d k:%d\n",i,j,k); printk("OMG retry2!\n"); goto repeat; } fsbuf[j] = 0xff; nr_sects -= 8; } else // 非全1 { while(k < 8) { if(fsbuf[j] & (char)(1 << k)) { printk("i:%d j:%d k:%d\n",i,j,k); printk("OMG retry3!\n"); goto repeat; } fsbuf[j] |= (char)(1 << k++); nr_sects--; } } j++; k = 0; } } hd_write(ROOT_DEV,fsbuf,SECTOR_SIZE * (i + SMAP_1ST_SECTS),1); i++; j = 0; } } repeat: ; } } } smapOK: if(start_sect == 0) { printk("smap full2----"); return 0; // 没有空位 } // devinode赋值 int offset = (SECTOR_SIZE * INODE_1ST_SECTS + inode_nr * INODE_SIZE) & ~0x1ff; hd_read(ROOT_DEV,fsbuf,offset,1); DEV_Inode* p_devinode = (DEV_Inode*)fsbuf; p_devinode += inode_nr % INODE_PER_SECT; p_devinode->i_mode = I_MODE_FILE; p_devinode->i_size = FILE_MAX_SIZE; p_devinode->i_start_sect = start_sect; p_devinode->i_nr_sects = SECTS_PER_FILE; printk("new file %s start_sect :%d sects: %d\n",pathname,start_sect,SECTS_PER_FILE); hd_write(ROOT_DEV,fsbuf,offset,1); // Dir_Entry // 在root中找一个空位 Dir_Entry* p_de; int file_offset = 0; int de_nr = 0; for(i = 0;i < ROOT_SECTS;i++,file_offset += SECTOR_SIZE) { file_buff_read(fsbuf,p_inode_de,file_offset,SECTOR_SIZE); for(j = 0,p_de = (Dir_Entry*)fsbuf;j < DIR_ENT_PER_SECT;j++,p_de++) { if(p_de->inode_nr == 0 && (i !=0 || j != 0)) // 第0号位置保留 { de_nr += j; //printk("de_nr:%d ",de_nr); Dir_Entry de; de.inode_nr = inode_nr; memcopy(de.name,pathname,MAX_FILENAME_LEN); file_buff_write(&de,p_inode_de,de_nr * sizeof(Dir_Entry),sizeof(Dir_Entry)); sync_buff(p_inode_de,0); // 0:不释放缓冲 1:同步之后释放缓冲 // 返回inode_nr printk("create file success: %s\n",pathname); return inode_nr; // 返回inode_nr 0:失败,非0:成功 } } de_nr += DIR_ENT_PER_SECT; } printk("Dir_Entry empty\n"); return 0; // 没有找到Dir_Entry }