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

操作系统Lab6

git checkout master

解释一下lab6的代码原理

在lab6中主要是去实现文件的读写操作,其中最重要的就是文件描述符和缓冲区的使用。在这个实验中,如何快速的、标准的实现sys_read()等操作呢?

首先观察一下fs.rs中的sys_fstat文件会发现一些固定的操作

kernel/src/syscall/fs.rs
pub fn sys_fstat(fd: usize, st: *mut Stat) -> isize {debug!("kernel:pid[{}] sys_fstat(fd: {}, st: 0x{:x?})",current_task().unwrap().pid.0, fd, st);let task = current_task().unwrap();let inner = task.inner_exclusive_access();if fd >= inner.fd_table.len() {return -1;}if let Some(file) = &inner.fd_table[fd] {let file = file.clone();// release current task TCB manually to avoid multi-borrowdrop(inner);let stat = file.state().unwrap();copy_to_virt(&stat, st);return 0}-1
}

阅读文档也会提取出一些操作有

    let task = current_task().unwrap();let inner = task.inner_exclusive_access();if fd >= inner.fd_table.len() {return -1;}if let Some(file) = &inner.fd_table[fd] {let file = file.clone();drop(inner);return 0}-1

那么接下来就可以快速的去写各种操作了

sys_write

阅读文档里面

对于 sys_write 和 sys_read,获取当前任务的 inner 之后,各自检查是否可写、可读. 然后将用户态缓冲区翻译成 UserBuffer 后调用文件的 write 和 read 方法.

首先判断一下文件是否可写

if !file.writable() {return -1 ;}

然后就是需要将用户态下的虚拟地址翻译成内核可写的地址。

//把用户传入的虚拟地址区间 [buf, buf + len) 翻译成内核可以访问的物理内存切片。
/* buffers = [第一个物理页里的一段,第二个物理页里的一段,第三个物理页里的一段,
] */
let buffers = translated_byte_buffer((current_user_token()), buf, len) ;// 把刚才的各段包装成一个UserBuffer
let userbuf = UserBuffer::new(buffers) ; 
return  file.write(userbuf) as isize ;

完整代码

let task = current_task().unwrap() ; 
let inner = task.inner_exclusive_access() ; 
if fd >= inner.fd_table.len() {return -1 ;} 
if let Some(file) = &inner.fd_table[fd] {let file = file.clone() ; if !file.writable() {return -1 ;}drop(inner);let buffers = translated_byte_buffer((current_user_token()), buf, len) ;let userbuf = UserBuffer::new(buffers) ; return  file.write(userbuf) as isize ;
}
-1 

sys_read()

如果能自己理解同时加以Ai能理解了sys_write,仿照上面就能写出来sys_read()

pub fn sys_read(fd: usize, buf: *const u8, len: usize) -> isize {let task =current_task().unwrap() ; let inner = task.inner_exclusive_access()  ;if fd >= inner.fd_table.len()  {return -1 ; }if let Some(file) = &inner.fd_table[fd] {let file = file.clone()  ; if !file.readable() {return -1 ;}drop(inner);let buffers = translated_byte_buffer(current_user_token(), buf, len); let userbuf = UserBuffer::new(buffers) ; return file.read(userbuf) as isize ; }-1 
}

接下来就需要理解一下打开和删除文件的情况,打开和关闭文件实际上是对fd文件描述符指向对象(lab2介绍了是什么)的操作。

用户程序:int fd = open("a.txt", 0);
read(fd, buf, 100);内核中:当前进程
┌──────────────────────┐
│ fd_table              │
│ 0 -> stdin            │
│ 1 -> stdout           │
│ 2 -> stderr           │
│ 3 -> file object ─────┼─────┐
└──────────────────────┘     │↓┌──────────────┐│ file object  ││ offset = 0   ││ readable = 1 ││ writable = 0 ││ inode ptr ───┼─────┐└──────────────┘     │↓┌────────────────┐│ inode 12        ││ type = file     ││ size = 1024     ││ addrs=[100...]  │└────────────────┘↓┌────────────────┐│ 磁盘数据块       ││ 文件真正内容     │└────────────────┘

sys_close

这个好写,先写这个 , 大部分都是板子,最后把文件描述对应的对象置空就行了

pub fn sys_close(fd: usize) -> isize {let task = current_task().unwrap(); let mut inner = task.inner_exclusive_access()  ;if fd >= inner.fd_table.len()  { return -1;} if inner.fd_table[fd].is_none() {return -1; }inner.fd_table[fd] = None ; 0 
}

sys_open

文档说:

sys_open 把路径从用户态翻译成 &str后,打开文件. 如果返回 Some(inode),再分配描述符并存入 fd_table,返回 fd;失败返回 -1.
  1. 根据描述把路径从用户态翻译成&str,有一个函数
let path = translated_str(current_user_token(), path) ; 

其实就是实现了

用户虚拟地址 VA↓
根据当前进程页表翻译↓
物理地址 PA   //对应页表↓
逐字节读取↓
组成 String // 对应什么from_raw_slice ? 好像是? 哥们我好像在前面实验见过你

那flags同理,这些函数确实很难找.

let flags = OpenFlags::from_bits(flags).unwrap() ; 

然后根据其描述,open_file找到inode,分配一个文件描述符指向inode,之后返回fd

if let Some(inode) = open_file(&path, flags) 
{let task = current_task().unwrap() ; let mut inner = task.inner_exclusive_access() ; // 分配一个fd let fd = inner.alloc_fd() ; inner.fd_table[fd] = Some(inode) ; fd as isize 
}else {-1}

那么实验六的这些操作,就实现了补充。

http://www.jsqmd.com/news/714629/

相关文章:

  • TCGA突变数据下载踩坑实录:当read.table遇到3‘UTR时,我手动合并MAF文件翻车了
  • 培洋机械设备:青岛专业的起重设备回收公司 - LYL仔仔
  • 2026年乌鲁木齐与昌吉一体化污水处理设备深度横评:5大品牌选购指南 - 年度推荐企业名录
  • 常州永九安吊装搬运:常州吊装搬运哪家专业推荐 - LYL仔仔
  • 内存诊断工具Memtest86+:专业级系统稳定性检测技术指南
  • 2026柔性抓取技术演进:柔触的差异化创新逻辑 - 品牌2026
  • 3步解决电视直播混乱:Kodi PVR IPTV Simple终极解决方案
  • 2026届毕业生推荐的五大降AI率工具实测分析
  • 2026点胶机厂家推荐排行 电动工具专用+半导体高效适配 稳定耐用 - 极欧测评
  • 如何快速批量打开网页:Open Multiple URLs 浏览器扩展终极指南
  • 计科毕业设计简单的题目怎么选
  • 2026年新疆一体化污水处理设备与乌鲁木齐养殖污水处理解决方案完全指南 - 年度推荐企业名录
  • 南京梓如旅行社客服服务富通天下:打造数字化私域平台,赋能中国外贸 - 速递信息
  • 2026年全国沼气储气柜/储气柜生产厂家甄选 配畜禽养殖污水处理等工程 - 深度智识库
  • 广州金烨再生资源回收:宝安专业的废铝回收厂家 - LYL仔仔
  • 宽温小型化电源模块在无人机飞控与任务载荷中的应用研究
  • 3步掌握OpenRAM:开源SRAM编译器如何重塑内存设计流程
  • 2026年新疆一体化污水处理设备与乡镇污水处理设备深度横评指南 - 年度推荐企业名录
  • 免费在线生成专业法线贴图:NormalMap-Online完整指南
  • GoLang 学习(一)
  • 2026年新疆乌鲁木齐、昌吉一体化污水处理设备本地化采购指南:天辉环境源头直供方案 - 年度推荐企业名录
  • 2026年喇叭零部件抓取方案解析 助力产线精细化作业 - 品牌2026
  • 2026届必备的五大降AI率工具解析与推荐
  • CPPM 考试内容及科目全解析|2026 采购供应链黄金证书,中供国培张老师精讲 - 中供国培
  • 成都市蜀宏吊装工程:成都市无尘室气垫搬运哪家好 - LYL仔仔
  • 终极指南:如何在iPhone和Mac上免费运行Windows和Linux系统
  • 昆明银行变更、工商变更、代理记账全流程对标|2026财税合规避坑方案 - 优质企业观察收录
  • 闲置百联OK卡怎么处理?最全回收平台对比推荐! - 团团收购物卡回收
  • 2025届必备的五大降重复率方案横评
  • 重庆轩亿镁办公家具:黔江区单双玻百叶隔断安装哪家好 - LYL仔仔