实验 26.文件的打开和关闭
总结
文件描述符与 inode 的转换:
int fd = 3; // 假设fd = 3
int file_index = pcb.fd_table[fd]; // 从线程pcb的文件描述符数组拿到文件索引
file* file = file_table[file_index]; // 拿到全局文件表的file结构体
inode* inode = file.inode; // 拿到文件描述符对应的inode
主要代码
main.c
fs.c
file.c
/// @brief 打开文件
/// 打开编号为inode_no的inode对应的文件
/// @param inode_no inode号
/// @param flag 打开文件的选项
/// @return 若成功则返回文件描述符,否则返回-1
int32_t file_open(uint32_t inode_no, uint8_t flag) {
// 1 找出空闲的文件结构
int fd_idx = get_free_slot_in_global();
if (fd_idx == -1) {
printk("exceed max open files\n");
return -1;
}
// 2 初始化这个文件结构
file_table[fd_idx].fd_inode = inode_open(cur_part, inode_no); // 写入inode
file_table[fd_idx].fd_pos = 0; // 打开文件,将fd_pos还原为0,让文件内的指针指向开头
file_table[fd_idx].fd_flag = flag; // 保存打开的选项
// 3 如果是要写文件,那么判断是否有别的进程在写
// 注意这里拿的是地址
// 如果这里拿值,那么在后面做判断时,可能他的值已经变化
bool* write_deny = &file_table[fd_idx].fd_inode->write_deny;
if (flag == O_WRONLY || flag == O_RDWR) { // 如果要写文件
enum intr_status old_status = intr_disable();
if (!(*write_deny)) { // 若当前没有其它进程写该文件,将其占用.
*write_deny = true; // 置为true,避免多个进程同时写此文件
intr_set_status(old_status); // 恢复中断
} else { // 直接失败返回
intr_set_status(old_status);
printk("file can`t be write now, try again later\n");
return -1;
}
}
return pcb_fd_install(fd_idx);
}
/// @brief 关闭文件
/// @param file
/// @return 成功返回0,否则返回-1
int32_t file_close(struct file* file) {
if (file == NULL) { return -1; }
file->fd_inode->write_deny = false;
inode_close(file->fd_inode);
file->fd_inode = NULL; // 使文件结构可用
return 0;
}