Skip to content
Open

ch5 #10

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions char_replace.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#!/bin/bash
#!/usr/bin/bash # 如果 which bash 返回 /usr/bin/bash

# 定义要替换的字符映射(中文全角 → 英文半角)
declare -A replace_map=(
['(']='('
[')']=')'
[',']=','
['。']='.'
[';']=';'
[':']=':'
)

# 初始化计数器
declare -A count_stats=(
['( → (' ]=0
[') → )' ]=0
[', → ,' ]=0
['。 → .' ]=0
['; → ;' ]=0
[': → :' ]=0
)

# 获取当前脚本名称
current_script_name=$(basename "$0")

# 递归查找所有文本文件(排除二进制文件和指定文件)
while IFS= read -r -d '' file; do
# 获取文件名(不含路径)
filename=$(basename "$file")

# 检查是否为需要排除的文件
if [[ "$filename" == "$current_script_name" || "$filename" == "char_replace.ps1" ]]; then
echo "跳过排除文件: $file"
continue
fi

# 检查是否为文本文件(避免修改二进制文件)
if file "$file" | grep -q 'text'; then
echo "处理文件: $file"
temp_file=$(mktemp)
cp "$file" "$temp_file"

# 逐个替换字符并统计次数
for key in "${!replace_map[@]}"; do
value="${replace_map[$key]}"
# 统计替换前的出现次数
old_count=$(grep -o "$key" "$temp_file" | wc -l)
# 执行替换
sed -i "s/$key/$value/g" "$temp_file"
# 统计替换后的出现次数
new_count=$(grep -o "$key" "$temp_file" | wc -l)
# 计算实际替换次数
replaced_count=$((old_count - new_count))
# 更新统计
count_stats["$key → $value"]=$((count_stats["$key → $value"] + replaced_count))
done

# 替换原文件
mv "$temp_file" "$file"
else
echo "跳过非文本文件: $file"
fi
done < <(find . -type f -print0)

# 输出替换统计
echo -e "\n替换统计:"
for key in "${!count_stats[@]}"; do
echo "$key: ${count_stats[$key]} 次"
done

echo -e "\n所有文件处理完成!"
17 changes: 12 additions & 5 deletions os/src/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,29 @@ use alloc::vec::Vec;
use lazy_static::*;
///get app number
pub fn get_num_app() -> usize {
//获取链接到内核内的应用的数目
extern "C" {
fn _num_app();
}
unsafe { (_num_app as usize as *const usize).read_volatile() }
}
/// get applications data
pub fn get_app_data(app_id: usize) -> &'static [u8] {
//返回第 app_id 个应用程序的二进制数据(
extern "C" {
fn _num_app();
}
let num_app_ptr = _num_app as usize as *const usize;
let num_app = get_num_app();
let app_start = unsafe { core::slice::from_raw_parts(num_app_ptr.add(1), num_app + 1) };
assert!(app_id < num_app);
let num_app = get_num_app(); //获取应用总数
let app_start = unsafe {
core::slice::from_raw_parts(num_app_ptr.add(1), num_app + 1)
//raed应用的所有地址范围
};
assert!(app_id < num_app); //检查合法
unsafe {
core::slice::from_raw_parts(
app_start[app_id] as *const u8,
app_start[app_id + 1] - app_start[app_id],
app_start[app_id] as *const u8, //目标应用的起始地址
app_start[app_id + 1] - app_start[app_id], //计算长度
)
}
}
Expand Down Expand Up @@ -55,13 +60,15 @@ lazy_static! {
#[allow(unused)]
///get app data from name
pub fn get_app_data_by_name(name: &str) -> Option<&'static [u8]> {
// 三查找获得应用的 ELF 数据
let num_app = get_num_app();
(0..num_app)
.find(|&i| APP_NAMES[i] == name)
.map(get_app_data)
}
///list all apps
pub fn list_apps() {
// 打印出所有可用应用的名字
println!("/**** APPS ****");
for app in APP_NAMES.iter() {
println!("{}", app);
Expand Down
10 changes: 9 additions & 1 deletion os/src/mm/address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const VA_WIDTH_SV39: usize = 39;
const PPN_WIDTH_SV39: usize = PA_WIDTH_SV39 - PAGE_SIZE_BITS;
const VPN_WIDTH_SV39: usize = VA_WIDTH_SV39 - PAGE_SIZE_BITS;

///以下的四中类型都是usize
/// physical address
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
pub struct PhysAddr(pub usize);
Expand Down Expand Up @@ -97,6 +98,7 @@ impl VirtAddr {
/// Get the (floor) virtual page number
pub fn floor(&self) -> VirtPageNum {
VirtPageNum(self.0 / PAGE_SIZE)
//PAGE_SIZE是4KB
}

/// Get the (ceil) virtual page number
Expand Down Expand Up @@ -157,6 +159,8 @@ impl From<PhysPageNum> for PhysAddr {

impl VirtPageNum {
/// Get the indexes of the page table entry
/// 将虚拟页号(VPN)拆解为 3个9位索引,用于三级页表查询
/// VPN = 0x123456 得到 [0x12,0x34,0x56]
pub fn indexes(&self) -> [usize; 3] {
let mut vpn = self.0;
let mut idx = [0usize; 3];
Expand All @@ -178,16 +182,19 @@ impl PhysAddr {
impl PhysPageNum {
/// Get the reference of page table(array of ptes)
pub fn get_pte_array(&self) -> &'static mut [PageTableEntry] {
//物理页号转换为 物理地址 PhysAddr 返回页表项数组
let pa: PhysAddr = (*self).into();
unsafe { core::slice::from_raw_parts_mut(pa.0 as *mut PageTableEntry, 512) }
}
/// Get the reference of page(array of bytes)
pub fn get_bytes_array(&self) -> &'static mut [u8] {
//物理页号转换为 物理地址 PhysAddr 返回字节数组
let pa: PhysAddr = (*self).into();
unsafe { core::slice::from_raw_parts_mut(pa.0 as *mut u8, 4096) }
}
/// Get the mutable reference of physical address
pub fn get_mut<T>(&self) -> &'static mut T {
//范形
let pa: PhysAddr = (*self).into();
pa.get_mut()
}
Expand Down Expand Up @@ -270,4 +277,5 @@ where
}
}
/// a simple range structure for virtual page number
pub type VPNRange = SimpleRange<VirtPageNum>;
/// VPNRange 描述一段虚拟页号的连续区间,表示该逻辑段在地址区间中的位置和长度
pub type VPNRange = SimpleRange<VirtPageNum>; //
41 changes: 26 additions & 15 deletions os/src/mm/frame_allocator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,22 @@ use super::{PhysAddr, PhysPageNum};
use crate::config::MEMORY_END;
use crate::sync::UPSafeCell;
use alloc::vec::Vec;
use core::fmt::{self, Debug, Formatter};
use core::fmt::{ self, Debug, Formatter };
use lazy_static::*;

/// tracker for physical page frame allocation and deallocation
/// 物理帧的智能指针
pub struct FrameTracker {
/// physical page number
pub ppn: PhysPageNum,
}

impl FrameTracker {
/// Create a new FrameTracker
pub fn new(ppn: PhysPageNum) -> Self {
// page cleaning
let bytes_array = ppn.get_bytes_array();
let bytes_array = ppn.get_bytes_array(); //返回一个4KB的可变切片
for i in bytes_array {
*i = 0;
*i = 0; //所有字节清零
}
Self { ppn }
}
Expand All @@ -44,9 +44,9 @@ trait FrameAllocator {
}
/// an implementation for frame allocator
pub struct StackFrameAllocator {
current: usize,
end: usize,
recycled: Vec<usize>,
current: usize, // 当前分配游标
end: usize, // 内存结束边界
recycled: Vec<usize>, // 回收的页号栈
}

impl StackFrameAllocator {
Expand All @@ -65,18 +65,25 @@ impl FrameAllocator for StackFrameAllocator {
}
}
fn alloc(&mut self) -> Option<PhysPageNum> {
//检查recycle是否有元素
if let Some(ppn) = self.recycled.pop() {
Some(ppn.into())
} else if self.current == self.end {
// 步骤3:空间耗尽
//从之前从未分配过的物理页号区间 上进行分配 并且[current,end) 要存在
None
} else {
// 步骤2:分配新页
//增加元素
self.current += 1;
Some((self.current - 1).into())
}
}
fn dealloc(&mut self, ppn: PhysPageNum) {
let ppn = ppn.0;
// validity check
// 1.被分配过的元素一定 <current
// 2.如果在recycled里面 说明已经被回收了 不能二次回收
if ppn >= self.current || self.recycled.iter().any(|&v| v == ppn) {
panic!("Frame ppn={:#x} has not been allocated!", ppn);
}
Expand All @@ -89,31 +96,35 @@ type FrameAllocatorImpl = StackFrameAllocator;

lazy_static! {
/// frame allocator instance through lazy_static!
pub static ref FRAME_ALLOCATOR: UPSafeCell<FrameAllocatorImpl> =
unsafe { UPSafeCell::new(FrameAllocatorImpl::new()) };
pub static ref FRAME_ALLOCATOR: UPSafeCell<FrameAllocatorImpl> = unsafe {
UPSafeCell::new(FrameAllocatorImpl::new())
};
}
/// initiate the frame allocator using `ekernel` and `MEMORY_END`
pub fn init_frame_allocator() {
extern "C" {
fn ekernel();
}
//
FRAME_ALLOCATOR.exclusive_access().init(
PhysAddr::from(ekernel as usize).ceil(),
PhysAddr::from(MEMORY_END).floor(),
PhysAddr::from(ekernel as usize).ceil(), //内核结束地址 ekernel向上取整
PhysAddr::from(MEMORY_END).floor() //内存结束地址向下取整
);
}

/// Allocate a physical page frame in FrameTracker style
pub fn frame_alloc() -> Option<FrameTracker> {
FRAME_ALLOCATOR
.exclusive_access()
.alloc()
.map(FrameTracker::new)
FRAME_ALLOCATOR.exclusive_access().alloc().map(FrameTracker::new)
}

/// Deallocate a physical page frame with a given ppn
pub fn frame_dealloc(ppn: PhysPageNum) {
FRAME_ALLOCATOR.exclusive_access().dealloc(ppn);
/*
map 自动处理Option的两种情况:
1.Some(ppn) => Some(FrameTracker::new(ppn))
2.None => None
*/
}

#[allow(unused)]
Expand Down
Loading