Skip to content

Commit cabe618

Browse files
committed
finish
1 parent d56c75f commit cabe618

File tree

5 files changed

+128
-135
lines changed

5 files changed

+128
-135
lines changed

os/src/mm/memory_set.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,57 @@ impl MemorySet {
262262
false
263263
}
264264
}
265+
266+
// 新加的
267+
/// 公共方法:检查地址范围是否重叠
268+
pub fn check_overlap(&self, start: VirtAddr, end: VirtAddr) -> bool {
269+
for area in &self.areas {
270+
let area_start: VirtAddr = area.vpn_range.get_start().into();
271+
let area_end: VirtAddr = area.vpn_range.get_end().into();
272+
if !(end <= area_start || start >= area_end) {
273+
return true; // 有重叠
274+
}
275+
}
276+
false // 无重叠
277+
}
278+
279+
/// 公共方法:创建内存映射
280+
pub fn mmap(&mut self, start: VirtAddr, end: VirtAddr, map_type: MapType, perm: MapPermission) -> bool {
281+
// 检查重叠
282+
if self.check_overlap(start, end) {
283+
return false;
284+
}
285+
286+
// 创建映射区域
287+
let map_area = MapArea::new(start, end, map_type, perm);
288+
// 使用内部的 push 方法(保持 push 私有)
289+
self.push(map_area, None);
290+
true
291+
}
292+
293+
/// 公共方法:取消内存映射
294+
pub fn munmap(&mut self, start: VirtAddr, end: VirtAddr) -> bool {
295+
let start_vpn = start.floor();
296+
let end_vpn = end.ceil();
297+
298+
// 查找要移除的区域
299+
let mut found_index = None;
300+
for (i, area) in self.areas.iter().enumerate() {
301+
if area.vpn_range.get_start() == start_vpn && area.vpn_range.get_end() == end_vpn {
302+
found_index = Some(i);
303+
break;
304+
}
305+
}
306+
307+
// 移除并取消映射
308+
if let Some(index) = found_index {
309+
let mut area = self.areas.remove(index);
310+
area.unmap(&mut self.page_table);
311+
true
312+
} else {
313+
false
314+
}
315+
}
265316
}
266317
/// map area structure, controls a contiguous piece of virtual memory
267318
pub struct MapArea {
@@ -272,6 +323,7 @@ pub struct MapArea {
272323
}
273324

274325
impl MapArea {
326+
/// Create a new `MapArea`.
275327
pub fn new(
276328
start_va: VirtAddr,
277329
end_va: VirtAddr,
@@ -287,6 +339,7 @@ impl MapArea {
287339
map_perm,
288340
}
289341
}
342+
/// map one page
290343
pub fn map_one(&mut self, page_table: &mut PageTable, vpn: VirtPageNum) {
291344
let ppn: PhysPageNum;
292345
match self.map_type {
@@ -302,32 +355,38 @@ impl MapArea {
302355
let pte_flags = PTEFlags::from_bits(self.map_perm.bits).unwrap();
303356
page_table.map(vpn, ppn, pte_flags);
304357
}
358+
305359
#[allow(unused)]
360+
/// unmap one page
306361
pub fn unmap_one(&mut self, page_table: &mut PageTable, vpn: VirtPageNum) {
307362
if self.map_type == MapType::Framed {
308363
self.data_frames.remove(&vpn);
309364
}
310365
page_table.unmap(vpn);
311366
}
367+
/// map the area into the page table
312368
pub fn map(&mut self, page_table: &mut PageTable) {
313369
for vpn in self.vpn_range {
314370
self.map_one(page_table, vpn);
315371
}
316372
}
317373
#[allow(unused)]
374+
/// unmap the area from the page table
318375
pub fn unmap(&mut self, page_table: &mut PageTable) {
319376
for vpn in self.vpn_range {
320377
self.unmap_one(page_table, vpn);
321378
}
322379
}
323380
#[allow(unused)]
381+
/// shrink the area to new_end
324382
pub fn shrink_to(&mut self, page_table: &mut PageTable, new_end: VirtPageNum) {
325383
for vpn in VPNRange::new(new_end, self.vpn_range.get_end()) {
326384
self.unmap_one(page_table, vpn)
327385
}
328386
self.vpn_range = VPNRange::new(self.vpn_range.get_start(), new_end);
329387
}
330388
#[allow(unused)]
389+
/// append the area to new_end
331390
pub fn append_to(&mut self, page_table: &mut PageTable, new_end: VirtPageNum) {
332391
for vpn in VPNRange::new(self.vpn_range.get_end(), new_end) {
333392
self.map_one(page_table, vpn)
@@ -356,12 +415,15 @@ impl MapArea {
356415
current_vpn.step();
357416
}
358417
}
418+
359419
}
360420

361421
#[derive(Copy, Clone, PartialEq, Debug)]
362422
/// map type for memory set: identical or framed
363423
pub enum MapType {
424+
/// map virtual address to the identical physical address
364425
Identical,
426+
/// map virtual address to the allocated frame
365427
Framed,
366428
}
367429

os/src/mm/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,15 @@
99
mod address;
1010
mod frame_allocator;
1111
mod heap_allocator;
12-
mod memory_set;
12+
pub mod memory_set;
1313
mod page_table;
1414

1515
pub use address::{PhysAddr, PhysPageNum, VirtAddr, VirtPageNum};
1616
use address::{StepByOne, VPNRange};
1717
pub use frame_allocator::{frame_alloc, FrameTracker, frame_dealloc};
1818
pub use memory_set::remap_test;
1919
pub use memory_set::{kernel_stack_position, MapPermission, MemorySet, KERNEL_SPACE};
20+
pub use memory_set::{MapArea, MapType};
2021
pub use page_table::{translated_byte_buffer, PageTableEntry,translated_and_write};
2122
pub use page_table::{PTEFlags, PageTable};
2223

os/src/syscall/process.rs

Lines changed: 6 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
//! Process management syscalls
2-
use crate::task::{change_program_brk, exit_current_and_run_next, suspend_current_and_run_next,current_user_token,get_current_syscall_stats};
2+
use crate::task::{change_program_brk, exit_current_and_run_next, suspend_current_and_run_next,current_user_token,get_current_syscall_stats,sys_mmap_tcb,sys_munmap_tcb};
33
use crate::timer::get_time_us;
4-
use crate::mm::{PageTable,translated_and_write,VirtAddr,frame_alloc,PTEFlags,frame_dealloc};
4+
use crate::mm::{PageTable,translated_and_write,VirtAddr};
55
use crate::config::{PAGE_SIZE,USER_SPACE_END};
6-
use alloc::vec::Vec;
76

87
#[repr(C)]
98
#[derive(Debug)]
@@ -135,91 +134,8 @@ pub fn sys_mmap(start: usize, len: usize, prot: usize) -> isize {
135134
return 0;
136135
}
137136

138-
// 5. 获取当前进程的页表
139-
let page_table_token = current_user_token();
140-
let mut page_table = PageTable::from_token(page_table_token);
141-
142-
// 6. 设置权限标志
143-
let mut flags = PTEFlags::V | PTEFlags::U;
144-
if (prot & 0x1) != 0 { flags |= PTEFlags::R; }
145-
if (prot & 0x2) != 0 { flags |= PTEFlags::W; }
146-
if (prot & 0x4) != 0 { flags |= PTEFlags::X; }
147-
148-
// 7. 检查区间内是否已有映射
149-
let mut va = start;
150-
while va < end {
151-
let vpn = VirtAddr::from(va).floor();
152-
153-
if let Some(pte) = page_table.translate(vpn) {
154-
if pte.is_valid() {
155-
return -1; // 已存在有效映射
156-
}
157-
}
158-
va += PAGE_SIZE;
159-
}
160-
161-
// 8. 建立映射并验证
162-
let mut va = start;
163-
let mut mapped_pages = Vec::new();
164-
165-
while va < end {
166-
let vpn = VirtAddr::from(va).floor();
167-
168-
// 分配物理页
169-
if let Some(frame) = frame_alloc() {
170-
let ppn = frame.ppn;
171-
172-
// 建立映射
173-
page_table.map(vpn, ppn, flags);
174-
175-
// 验证映射是否成功
176-
if let Some(pte) = page_table.translate(vpn) {
177-
if pte.is_valid() && pte.ppn() == ppn {
178-
// 映射成功,检查标志位
179-
let actual_flags = pte.flags();
180-
if actual_flags.contains(flags) {
181-
mapped_pages.push(vpn);
182-
} else {
183-
// 标志位不匹配,回滚
184-
println!("标志位不匹配: 期望 {:?}, 实际 {:?}", flags, actual_flags);
185-
page_table.unmap(vpn);
186-
break;
187-
}
188-
} else {
189-
// 映射失败,回滚
190-
println!("映射失败: VPN {:#x}", vpn.0);
191-
page_table.unmap(vpn);
192-
break;
193-
}
194-
} else {
195-
// 无法翻译,映射失败
196-
println!("无法翻译 VPN: {:#x}", vpn.0);
197-
frame_dealloc(ppn);
198-
break;
199-
}
200-
} else {
201-
// 内存不足
202-
println!("内存不足,回滚已建立的映射");
203-
for mapped_vpn in mapped_pages {
204-
page_table.unmap(mapped_vpn);
205-
}
206-
return -1;
207-
}
208-
209-
va += PAGE_SIZE;
210-
}
211-
212-
// 9. 检查是否所有页面都成功映射
213-
if mapped_pages.len() * PAGE_SIZE < len {
214-
// 部分映射失败,回滚所有
215-
println!("部分映射失败,回滚所有");
216-
for mapped_vpn in mapped_pages {
217-
page_table.unmap(mapped_vpn);
218-
}
219-
return -1;
220-
}
221-
222-
0 // 成功返回0
137+
// 5. 建立映射并验证
138+
sys_mmap_tcb(start, len, prot)
223139
}
224140

225141
pub fn sys_munmap(start: usize, len: usize) -> isize {
@@ -241,51 +157,8 @@ pub fn sys_munmap(start: usize, len: usize) -> isize {
241157
return -1;
242158
}
243159

244-
// 4. 获取当前进程的页表
245-
let page_table_token = current_user_token();
246-
let mut page_table = PageTable::from_token(page_table_token);
247-
248-
let mut va = start;
249-
while va < end {
250-
let vpn = VirtAddr::from(va).floor();
251-
252-
// 检查页面是否存在有效映射
253-
if let Some(pte) = page_table.translate(vpn) {
254-
// 只检查页面是否有效,不检查用户可见性
255-
if !pte.is_valid() {
256-
return -1;
257-
}
258-
// 如果页面无效,静默跳过
259-
}
260-
// 如果页面没有映射(translate返回None),也静默跳过
261-
262-
va += PAGE_SIZE;
263-
}
264-
265-
// 5. 遍历区域,只取消已存在的有效映射
266-
let mut va = start;
267-
while va < end {
268-
let vpn = VirtAddr::from(va).floor();
269-
270-
// 检查页面是否存在有效映射
271-
if let Some(pte) = page_table.translate(vpn) {
272-
// 只检查页面是否有效,不检查用户可见性
273-
if pte.is_valid() {
274-
page_table.unmap(vpn);
275-
}
276-
// 如果页面无效,静默跳过
277-
}
278-
// 如果页面没有映射(translate返回None),也静默跳过
279-
280-
va += PAGE_SIZE;
281-
}
282-
283-
// 6. 刷新TLB
284-
unsafe {
285-
core::arch::asm!("sfence.vma");
286-
}
287-
288-
0 // 成功返回0
160+
// 4. 遍历区域,只取消已存在的有效映射
161+
sys_munmap_tcb(start, len)
289162
}
290163

291164
/// change data segment size

os/src/task/mod.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,20 @@ impl TaskManager {
174174
let task = &inner.tasks[current];
175175
task.syscall_stats.clone()
176176
}
177+
178+
fn sys_mmap_tcb(&self, start: usize, len: usize, prot: usize) -> isize {
179+
let mut inner = self.inner.exclusive_access();
180+
let current = inner.current_task;
181+
let task = &mut inner.tasks[current];
182+
task.sys_mmap_tcb(start, len, prot)
183+
}
184+
185+
fn sys_munmap_tcb(&self, start: usize, len: usize) -> isize {
186+
let mut inner = self.inner.exclusive_access();
187+
let current = inner.current_task;
188+
let task = &mut inner.tasks[current];
189+
task.sys_munmap_tcb(start, len)
190+
}
177191
}
178192

179193
/// Run the first task in task list.
@@ -233,4 +247,14 @@ pub fn record_syscall(syscall_id: usize) {
233247
/// 获取当前任务的系统调用统计
234248
pub fn get_current_syscall_stats() -> BTreeMap<usize, usize> {
235249
TASK_MANAGER.get_current_syscall_stats()
250+
}
251+
252+
/// 在当前任务的页表中映射一段虚拟地址区域
253+
pub fn sys_mmap_tcb(start: usize, len: usize, prot: usize) -> isize {
254+
TASK_MANAGER.sys_mmap_tcb(start, len, prot)
255+
}
256+
257+
/// 在当前任务的页表中取消映射一段虚拟地址区域
258+
pub fn sys_munmap_tcb(start: usize, len: usize) -> isize {
259+
TASK_MANAGER.sys_munmap_tcb(start, len)
236260
}

os/src/task/task.rs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@ use crate::config::TRAP_CONTEXT_BASE;
44
use crate::mm::{
55
kernel_stack_position, MapPermission, MemorySet, PhysPageNum, VirtAddr, KERNEL_SPACE,
66
};
7+
78
use crate::trap::{trap_handler, TrapContext};
89
// 本人添加
910
use alloc::collections::BTreeMap;
10-
11+
use crate::mm::MapType;
1112

1213
/// The task control block (TCB) of a task.
1314
pub struct TaskControlBlock {
@@ -104,6 +105,38 @@ impl TaskControlBlock {
104105
}
105106
}
106107

108+
/// 在当前任务的页表中映射一段虚拟地址区域
109+
pub fn sys_mmap_tcb(&mut self, start: usize, len: usize, prot: usize) -> isize {
110+
let va_start = VirtAddr::from(start);
111+
let va_end = VirtAddr::from(start + len);
112+
113+
// 设置权限标志
114+
let mut perm = MapPermission::empty();
115+
perm.insert(MapPermission::U); // User mode access
116+
if (prot & 0x1) != 0 { perm.insert(MapPermission::R); } // Read
117+
if (prot & 0x2) != 0 { perm.insert(MapPermission::W); } // Write
118+
if (prot & 0x4) != 0 { perm.insert(MapPermission::X); } // Execute
119+
120+
// 通过 MemorySet 的公共接口操作
121+
if self.memory_set.mmap(va_start, va_end, MapType::Framed, perm) {
122+
0 // 成功
123+
} else {
124+
-1 // 失败(通常是重叠)
125+
}
126+
}
127+
128+
/// 在当前任务的页表中取消映射一段虚拟地址区域
129+
pub fn sys_munmap_tcb(&mut self, start: usize, len: usize) -> isize {
130+
let va_start = VirtAddr::from(start);
131+
let va_end = VirtAddr::from(start + len);
132+
133+
// 通过 MemorySet 的公共接口操作
134+
if self.memory_set.munmap(va_start, va_end) {
135+
0 // 成功
136+
} else {
137+
-1 // 失败(区域不存在)
138+
}
139+
}
107140
}
108141

109142
#[derive(Copy, Clone, PartialEq)]

0 commit comments

Comments
 (0)