当前位置: 首页 > news >正文

10.Lab Nine —— file system-下

 Symbolic links

添加符号链接

1.添加有关symlink系统调用的定义声明,包括kernel/syscall.h, kernel/syscall.c, user/usys.pluser/user.h.

2.添加新的文件类型T_SYMLINK到kernel/stat.h中,添加新的文件标识位O_NOFOLLOW到kernel/fcntl.h中

3.在kenel/sysfile.c中实现sys_symlink()函数

该函数用于生成符号链接,该符号链接相当于一个特殊的独立文件,里面存储的是目标文件的路径

4.修改kernel/sysfile中的sys_open()函数

该函数可以用来打开文件,对于符号链接一般情况下需要打开的是其目标文件,因此需要额外处理

(此处需要注意避免成环问题的出现)

/* 系统调用open的实现 */
uint64
sys_open(void)
{/* 路径名缓冲区 */char path[MAXPATH];/* 文件描述符和打开模式 */int fd, omode;/* 文件结构指针 */struct file *f;/* i节点指针 */struct inode *ip;/* 临时变量,用于存储函数调用返回值 */int n;/* 获取路径名和打开模式,如果出错则返回-1 */if((n = argstr(0, path, MAXPATH)) < 0 || argint(1, &omode) < 0)return -1;/* 开始一个文件操作 */begin_op();/* 如果需要创建文件 */if(omode & O_CREATE){/* 调用create函数创建文件,如果失败则返回-1 */ip = create(path, T_FILE, 0, 0);if(ip == 0){end_op();return -1;}} else {int symlink_depth = 0;/* 查找已存在的文件,如果失败则返回-1 */while(1){if((ip = namei(path)) == 0){end_op();return -1;}/* 加锁i节点 */ilock(ip);if(ip->type == T_SYMLINK && (omode & O_NOFOLLOW) == 0){//在跟踪符号链接时需要额外考虑到符号链接的目标可能还是符号链接, 此时需要递归的去跟踪目标链接直至得到真正的文件. 而这其中需要解决两个问题: 一是符号链接可能成环, 这样会一直递归地跟踪下去, 因此需要进行成环的检测; 另一方面是需要对链接的深度进行限制, 以减轻系统负担,这里把最大深度设成10if(++symlink_depth > 10){// too many layer of symlinks, might be a loopiunlockput(ip);end_op();return -1;}if(readi(ip, 0, (uint64)path, 0, MAXPATH) < 0){iunlockput(ip);end_op();return -1;}iunlockput(ip);}else{break;}}/* 如果是目录文件且不是只读打开,返回-1 */if(ip->type == T_DIR && omode != O_RDONLY){// // 如果是目录,并且打开模式不是 O_RDONLY(只读),则不能打开iunlockput(ip);end_op();return -1;}}/* 如果是设备文件,检查设备号是否有效,否则返回-1 */if(ip->type == T_DEVICE && (ip->major < 0 || ip->major >= NDEV)){iunlockput(ip);end_op();return -1;}/* 分配文件结构,如果失败则返回-1 */if((f = filealloc()) == 0 || (fd = fdalloc(f)) < 0){if(f)fileclose(f);iunlockput(ip);end_op();return -1;}// //处理符号链接,即软连接,如果// if(ip->type == T_SYMLINK && !(omode & O_NOFOLLOW)){ //如果不是不可追踪//   //若符号链接指向的仍旧是符号链接,则递归跟随它,直到找到真正的指向文件//   //深度不能超过MAX_SYMLINK_DEPTH//   for(int i = 0; i < MAX_SYMLINK_DEPTH; i++){//     //读出符号链接指的路径//   }// }/* 根据文件类型设置文件结构的类型和主要设备号 */if(ip->type == T_DEVICE){f->type = FD_DEVICE;f->major = ip->major;} else {f->type = FD_INODE;f->off = 0;}/* 设置文件结构的i节点指针和读写权限 */f->ip = ip;f->readable = !(omode & O_WRONLY);f->writable = (omode & O_WRONLY) || (omode & O_RDWR);/* 如果要求截断文件,且文件类型是普通文件,则截断文件 */if((omode & O_TRUNC) && ip->type == T_FILE){itrunc(ip);}/* 解锁i节点 */iunlock(ip);/* 结束文件操作 */end_op();/* 返回文件描述符 */return fd;
}

这里也可以看一下硬链接的实现方式(kernel/sysfile)

// Create the path new as a link to the same inode as old.
//xv6硬链接实现方式
uint64 sys_link(void) {char name[DIRSIZ], new[MAXPATH], old[MAXPATH];struct inode *dp, *ip;// 从用户态获取参数 old 和 new,分别表示旧路径和新路径if(argstr(0, old, MAXPATH) < 0 || argstr(1, new, MAXPATH) < 0)return -1;// 开始文件系统操作事务begin_op();// 根据旧路径名找到 inodeif((ip = namei(old)) == 0){end_op();return -1;}// 对 inode 进行加锁ilock(ip);// 检查旧路径对应的 inode 是否为目录,如果是目录则不能创建硬链接if(ip->type == T_DIR){iunlockput(ip); // 解锁 inode 并释放引用end_op();return -1;}// 增加 inode 的链接数,因为即将创建一个新的硬链接指向该 inodeip->nlink++;iupdate(ip); // 更新 inode 的磁盘信息iunlock(ip); // 解锁 inode// 解析新路径中的目录名和文件名if((dp = nameiparent(new, name)) == 0)goto bad;// 对目录的 inode 进行加锁ilock(dp);// 检查新路径所在的目录的设备号与旧路径所在的设备号是否相同// 如果不相同,或者在新路径所在的目录中无法创建新的目录项,说明创建硬链接失败if(dp->dev != ip->dev || dirlink(dp, name, ip->inum) < 0){iunlockput(dp); // 解锁目录的 inode 并释放引用goto bad;}// 解锁目录的 inode 并释放引用iunlockput(dp);// 释放旧路径对应的 inode 的引用iput(ip);// 结束文件系统操作事务end_op();return 0;bad:// 创建硬链接失败时,需要回滚之前对旧路径 inode 的修改,即减少链接数ilock(ip);ip->nlink--;iupdate(ip);iunlockput(ip);end_op();return -1;
}

5.最后在Makefile中添加对测试文件symlinktest.c 的编译.

测试

http://www.lryc.cn/news/446432.html

相关文章:

  • 低代码中实现数据映射的必要性与方案
  • SpringBoot集成阿里easyexcel(一)基础导入导出
  • 四元组问题
  • 如何用Prometheus监控禁用了Actuator的SpringBoot?
  • 使用TensorFlow实现一个简单的神经网络:从入门到精通
  • 应用DFX能力介绍
  • 第三篇 第20章工程计价数字化与智能化
  • 成语700词(46~65组)
  • linux如何配置静态IP
  • Dependency Check:一款针对应用程序依赖组件的安全检测工具
  • Python 从入门到实战28(文件的读操作)
  • [leetcode刷题]面试经典150题之7同构字符串(简单)
  • 【Keil5教程及技巧】耗时一周精心整理万字全网最全Keil5(MDK-ARM)功能详细介绍【建议收藏-细细品尝】
  • 【rust】 基于rust编写wasm,实现markdown转换为html文本
  • Java中的反向代理与负载均衡:Nginx与Java服务的集成
  • 高级java每日一道面试题-2024年9月26日-运维篇[分布式篇]-如何保证每个服务器的时间都是同步的?
  • 探索MemGPT:AI界的新宠儿
  • 处理RabbitMQ连接和认证问题
  • FFmpeg中结构释放小函数
  • C语言中的一些小知识(三)
  • 编译win2k3中tools目录下i386mk.inc文件的作用
  • IPSec隧道协议学习(一)
  • 计网作业3
  • 什么是注入攻击???
  • 牛客小白月赛101(A~E)
  • MFC设置特定控件字体大小和背景颜色
  • 专题八_链表_算法专题详细总结
  • Vue3使用vue-quill富文本编辑器实现图片大小调整
  • 感知笔记1:ROS 视觉- 跟随红球
  • JAVA多线程机制