mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-08 18:26:48 +00:00
parent
06560afa2a
commit
eb49bb993a
@ -1,14 +1,17 @@
|
|||||||
/// 引入Module
|
/// 引入Module
|
||||||
use crate::{
|
use crate::{
|
||||||
driver::base::{
|
driver::{
|
||||||
device::{
|
base::{
|
||||||
device_number::{DeviceNumber, Major},
|
device::{
|
||||||
Device, DeviceError, IdTable, BLOCKDEVS,
|
device_number::{DeviceNumber, Major},
|
||||||
},
|
Device, DeviceError, IdTable, BLOCKDEVS,
|
||||||
map::{
|
},
|
||||||
DeviceStruct, DEV_MAJOR_DYN_END, DEV_MAJOR_DYN_EXT_END, DEV_MAJOR_DYN_EXT_START,
|
map::{
|
||||||
DEV_MAJOR_HASH_SIZE, DEV_MAJOR_MAX,
|
DeviceStruct, DEV_MAJOR_DYN_END, DEV_MAJOR_DYN_EXT_END, DEV_MAJOR_DYN_EXT_START,
|
||||||
|
DEV_MAJOR_HASH_SIZE, DEV_MAJOR_MAX,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
block::cache::{cached_block_device::BlockCache, BlockCacheError, BLOCK_SIZE},
|
||||||
},
|
},
|
||||||
kerror,
|
kerror,
|
||||||
};
|
};
|
||||||
@ -195,7 +198,7 @@ pub trait BlockDevice: Device {
|
|||||||
/// @return: 如果操作成功,返回 Ok(操作的长度) 其中单位是字节;
|
/// @return: 如果操作成功,返回 Ok(操作的长度) 其中单位是字节;
|
||||||
/// 否则返回Err(错误码),其中错误码为负数;
|
/// 否则返回Err(错误码),其中错误码为负数;
|
||||||
/// 如果操作异常,但是并没有检查出什么错误,将返回Err(已操作的长度)
|
/// 如果操作异常,但是并没有检查出什么错误,将返回Err(已操作的长度)
|
||||||
fn read_at(
|
fn read_at_sync(
|
||||||
&self,
|
&self,
|
||||||
lba_id_start: BlockId,
|
lba_id_start: BlockId,
|
||||||
count: usize,
|
count: usize,
|
||||||
@ -209,7 +212,7 @@ pub trait BlockDevice: Device {
|
|||||||
/// @return: 如果操作成功,返回 Ok(操作的长度) 其中单位是字节;
|
/// @return: 如果操作成功,返回 Ok(操作的长度) 其中单位是字节;
|
||||||
/// 否则返回Err(错误码),其中错误码为负数;
|
/// 否则返回Err(错误码),其中错误码为负数;
|
||||||
/// 如果操作异常,但是并没有检查出什么错误,将返回Err(已操作的长度)
|
/// 如果操作异常,但是并没有检查出什么错误,将返回Err(已操作的长度)
|
||||||
fn write_at(
|
fn write_at_sync(
|
||||||
&self,
|
&self,
|
||||||
lba_id_start: BlockId,
|
lba_id_start: BlockId,
|
||||||
count: usize,
|
count: usize,
|
||||||
@ -240,8 +243,72 @@ pub trait BlockDevice: Device {
|
|||||||
/// @brief 返回当前磁盘上的所有分区的Arc指针数组
|
/// @brief 返回当前磁盘上的所有分区的Arc指针数组
|
||||||
fn partitions(&self) -> Vec<Arc<Partition>>;
|
fn partitions(&self) -> Vec<Arc<Partition>>;
|
||||||
|
|
||||||
|
/// # 函数的功能
|
||||||
|
/// 经由Cache对块设备的读操作
|
||||||
|
fn read_at(
|
||||||
|
&self,
|
||||||
|
lba_id_start: BlockId,
|
||||||
|
count: usize,
|
||||||
|
buf: &mut [u8],
|
||||||
|
) -> Result<usize, SystemError> {
|
||||||
|
self.cache_read(lba_id_start, count, buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// # 函数的功能
|
||||||
|
/// 经由Cache对块设备的写操作
|
||||||
|
fn write_at(
|
||||||
|
&self,
|
||||||
|
lba_id_start: BlockId,
|
||||||
|
count: usize,
|
||||||
|
buf: &[u8],
|
||||||
|
) -> Result<usize, SystemError> {
|
||||||
|
self.cache_write(lba_id_start, count, buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// # 函数的功能
|
||||||
|
/// 其功能对外而言和read_at函数完全一致,但是加入blockcache的功能
|
||||||
|
fn cache_read(
|
||||||
|
&self,
|
||||||
|
lba_id_start: BlockId,
|
||||||
|
count: usize,
|
||||||
|
buf: &mut [u8],
|
||||||
|
) -> Result<usize, SystemError> {
|
||||||
|
let cache_response = BlockCache::read(lba_id_start, count, buf);
|
||||||
|
if let Err(e) = cache_response {
|
||||||
|
match e {
|
||||||
|
BlockCacheError::StaticParameterError => {
|
||||||
|
BlockCache::init();
|
||||||
|
let ans = self.read_at_sync(lba_id_start, count, buf)?;
|
||||||
|
return Ok(ans);
|
||||||
|
}
|
||||||
|
BlockCacheError::BlockFaultError(fail_vec) => {
|
||||||
|
let ans = self.read_at_sync(lba_id_start, count, buf)?;
|
||||||
|
let _ = BlockCache::insert(fail_vec, buf);
|
||||||
|
return Ok(ans);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
let ans = self.read_at_sync(lba_id_start, count, buf)?;
|
||||||
|
return Ok(ans);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Ok(count * BLOCK_SIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// # 函数功能
|
||||||
|
/// 其功能对外而言和write_at函数完全一致,但是加入blockcache的功能
|
||||||
|
fn cache_write(
|
||||||
|
&self,
|
||||||
|
lba_id_start: BlockId,
|
||||||
|
count: usize,
|
||||||
|
buf: &[u8],
|
||||||
|
) -> Result<usize, SystemError> {
|
||||||
|
let _cache_response = BlockCache::immediate_write(lba_id_start, count, buf);
|
||||||
|
self.write_at_sync(lba_id_start, count, buf)
|
||||||
|
}
|
||||||
|
|
||||||
fn write_at_bytes(&self, offset: usize, len: usize, buf: &[u8]) -> Result<usize, SystemError> {
|
fn write_at_bytes(&self, offset: usize, len: usize, buf: &[u8]) -> Result<usize, SystemError> {
|
||||||
// assert!(len <= buf.len());
|
|
||||||
if len > buf.len() {
|
if len > buf.len() {
|
||||||
return Err(SystemError::E2BIG);
|
return Err(SystemError::E2BIG);
|
||||||
}
|
}
|
||||||
@ -272,7 +339,6 @@ pub trait BlockDevice: Device {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Ok(len);
|
return Ok(len);
|
||||||
//self.0.lock().write_at(lba_id_start, count, buf)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_at_bytes(
|
fn read_at_bytes(
|
||||||
@ -314,11 +380,6 @@ pub trait BlockDevice: Device {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Ok(len);
|
return Ok(len);
|
||||||
|
|
||||||
// kdebug!(
|
|
||||||
// "ahci read at {lba_id_start}, count={count}, lock={:?}",
|
|
||||||
// self.0
|
|
||||||
// );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
pub mod block_device;
|
pub mod block_device;
|
||||||
pub mod disk_info;
|
pub mod disk_info;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub enum SeekFrom {
|
pub enum SeekFrom {
|
||||||
|
54
kernel/src/driver/block/cache/cache_block.rs
vendored
Normal file
54
kernel/src/driver/block/cache/cache_block.rs
vendored
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
use alloc::{boxed::Box, vec::Vec};
|
||||||
|
|
||||||
|
use crate::driver::base::block::block_device::BlockId;
|
||||||
|
|
||||||
|
use super::{BlockCacheError, BLOCK_SIZE};
|
||||||
|
|
||||||
|
/// # 枚举功能
|
||||||
|
/// 该枚举设计来是用于实现回写法的,但是目前并未使用
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub enum CacheBlockFlag {
|
||||||
|
Unused,
|
||||||
|
Unwrited,
|
||||||
|
Writed,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type CacheBlockAddr = usize;
|
||||||
|
|
||||||
|
/// # 结构功能
|
||||||
|
/// 存储数据的最小单位
|
||||||
|
pub struct CacheBlock {
|
||||||
|
data: Box<[u8]>,
|
||||||
|
_flag: CacheBlockFlag,
|
||||||
|
lba_id: BlockId,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CacheBlock {
|
||||||
|
pub fn new(data: Box<[u8]>, flag: CacheBlockFlag, lba_id: BlockId) -> Self {
|
||||||
|
CacheBlock {
|
||||||
|
data,
|
||||||
|
_flag: flag,
|
||||||
|
lba_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_data(lba_id: BlockId, data: Vec<u8>) -> Self {
|
||||||
|
let space_box = data.into_boxed_slice();
|
||||||
|
CacheBlock::new(space_box, CacheBlockFlag::Unwrited, lba_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn _set_flag(&mut self, _flag: CacheBlockFlag) -> Option<()> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
pub fn data(&self, buf: &mut [u8]) -> Result<usize, BlockCacheError> {
|
||||||
|
if buf.len() != BLOCK_SIZE {
|
||||||
|
return Err(BlockCacheError::BlockSizeError);
|
||||||
|
}
|
||||||
|
buf.copy_from_slice(&self.data);
|
||||||
|
return Ok(BLOCK_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lba_id(&self) -> BlockId {
|
||||||
|
self.lba_id
|
||||||
|
}
|
||||||
|
}
|
102
kernel/src/driver/block/cache/cache_iter.rs
vendored
Normal file
102
kernel/src/driver/block/cache/cache_iter.rs
vendored
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
use crate::driver::base::block::block_device::BlockId;
|
||||||
|
|
||||||
|
/// # 结构功能
|
||||||
|
/// 一个简单的结构体,是BlockIter的输出
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct BlockData {
|
||||||
|
/// 表示单个块对应的lba_id
|
||||||
|
lba_id: BlockId,
|
||||||
|
/// 表示该块在buf中的起始地址,目前并没有作用(例如:若该块是第2个块,那么该数据成员值为2*BLOCK_SIZE)
|
||||||
|
_data_start_addr: BlockId,
|
||||||
|
/// 表示该块的大小
|
||||||
|
_block_size: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BlockData {
|
||||||
|
pub fn new(lba_id: BlockId, data_start_addr: BlockId, block_size: usize) -> Self {
|
||||||
|
Self {
|
||||||
|
lba_id,
|
||||||
|
_data_start_addr: data_start_addr,
|
||||||
|
_block_size: block_size,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
pub fn lba_id(&self) -> BlockId {
|
||||||
|
self.lba_id
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
pub fn _data_start_addr(&self) -> BlockId {
|
||||||
|
self._data_start_addr
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
pub fn _block_size(&self) -> usize {
|
||||||
|
self._block_size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// # 结构功能
|
||||||
|
/// 块迭代器,它获取需求(起始块,连续块的个数),并将连续的块输出为单一的块(如你需要读取lba_id为10~20的连续块,它就可以输出10,11...,20的BlockData)
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct BlockIter {
|
||||||
|
/// 表示起始块的lba_id
|
||||||
|
lba_id_start: BlockId,
|
||||||
|
/// 表示从起始块开始你需要读多少个块
|
||||||
|
count: usize,
|
||||||
|
/// 表示当前遍历到第几个块了
|
||||||
|
current: usize,
|
||||||
|
/// 规定块的大小
|
||||||
|
block_size: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BlockIter {
|
||||||
|
pub fn new(lba_id_start: BlockId, count: usize, block_size: usize) -> Self {
|
||||||
|
Self {
|
||||||
|
lba_id_start,
|
||||||
|
count,
|
||||||
|
block_size,
|
||||||
|
current: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for BlockIter {
|
||||||
|
type Item = BlockData;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
if self.current < self.count {
|
||||||
|
let ans = BlockData::new(
|
||||||
|
self.lba_id_start + self.current,
|
||||||
|
self.current * self.block_size,
|
||||||
|
self.block_size,
|
||||||
|
);
|
||||||
|
self.current += 1;
|
||||||
|
Some(ans)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// # 结构功能
|
||||||
|
/// 表示缺块信息的数据结构,往往在读取的时候发现缺块并产生FailData,在插入的时候使用FailData
|
||||||
|
pub struct FailData {
|
||||||
|
/// 表示缺块的lba_id
|
||||||
|
lba_id: BlockId,
|
||||||
|
/// 表示缺块在buf中的位置,用于在insert的时候定位缺块数据的位置
|
||||||
|
index: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FailData {
|
||||||
|
pub fn new(lba_id: BlockId, index: usize) -> Self {
|
||||||
|
FailData { lba_id, index }
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
pub fn lba_id(&self) -> BlockId {
|
||||||
|
self.lba_id
|
||||||
|
}
|
||||||
|
/// # 函数的功能
|
||||||
|
/// 该函数返回的是缺块在buf中的位置,比如:index=1,那么我们就应该取buf\[512..1024\]
|
||||||
|
pub fn index(&self) -> usize {
|
||||||
|
self.index
|
||||||
|
}
|
||||||
|
}
|
422
kernel/src/driver/block/cache/cached_block_device.rs
vendored
Normal file
422
kernel/src/driver/block/cache/cached_block_device.rs
vendored
Normal file
@ -0,0 +1,422 @@
|
|||||||
|
use alloc::{boxed::Box, vec::Vec};
|
||||||
|
use hashbrown::HashMap;
|
||||||
|
|
||||||
|
use crate::{driver::base::block::block_device::BlockId, libs::rwlock::RwLock};
|
||||||
|
|
||||||
|
use super::{
|
||||||
|
cache_block::{CacheBlock, CacheBlockAddr},
|
||||||
|
cache_iter::{BlockIter, FailData},
|
||||||
|
BlockCacheError, BLOCK_SIZE, BLOCK_SIZE_LOG, CACHE_THRESHOLD,
|
||||||
|
};
|
||||||
|
|
||||||
|
static mut CSPACE: Option<LockedCacheSpace> = None;
|
||||||
|
static mut CMAPPER: Option<LockedCacheMapper> = None;
|
||||||
|
/// # 结构功能
|
||||||
|
/// 该结构体向外提供BlockCache服务
|
||||||
|
pub struct BlockCache;
|
||||||
|
|
||||||
|
unsafe fn mapper() -> Result<&'static mut LockedCacheMapper, BlockCacheError> {
|
||||||
|
unsafe {
|
||||||
|
match &mut CMAPPER {
|
||||||
|
Some(x) => return Ok(x),
|
||||||
|
None => return Err(BlockCacheError::StaticParameterError),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn space() -> Result<&'static mut LockedCacheSpace, BlockCacheError> {
|
||||||
|
unsafe {
|
||||||
|
match &mut CSPACE {
|
||||||
|
Some(x) => return Ok(x),
|
||||||
|
None => return Err(BlockCacheError::StaticParameterError),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BlockCache {
|
||||||
|
/// # 函数的功能
|
||||||
|
/// 初始化BlockCache需要的结构体
|
||||||
|
pub fn init() {
|
||||||
|
unsafe {
|
||||||
|
CSPACE = Some(LockedCacheSpace::new(CacheSpace::new()));
|
||||||
|
CMAPPER = Some(LockedCacheMapper::new(CacheMapper::new()));
|
||||||
|
}
|
||||||
|
kdebug!("BlockCache Initialized!");
|
||||||
|
}
|
||||||
|
/// # 函数的功能
|
||||||
|
/// 使用blockcache进行对块设备进行连续块的读操作
|
||||||
|
///
|
||||||
|
/// ## 参数:
|
||||||
|
/// - 'lba_id_start' :连续块的起始块的lba_id
|
||||||
|
/// - 'count' :从连续块算起需要读多少块
|
||||||
|
/// - 'buf' :读取出来的数据存放在buf中
|
||||||
|
///
|
||||||
|
/// ## 返回值:
|
||||||
|
/// - Ok(usize) :表示读取块的个数
|
||||||
|
/// - Err(BlockCacheError::BlockFaultError) :缺块的情况下,返回读取失败的块的数据,利用该返回值可以帮助blockcache插入读取失败的块值(见insert函数)
|
||||||
|
/// - Err(BlockCacheError::____) :不缺块的情况往往是初始化或者其他问题,这种异常会在block_device中得到处理
|
||||||
|
pub fn read(
|
||||||
|
lba_id_start: BlockId,
|
||||||
|
count: usize,
|
||||||
|
buf: &mut [u8],
|
||||||
|
) -> Result<usize, BlockCacheError> {
|
||||||
|
// 生成一个块迭代器(BlockIter),它可以迭代地给出所有需要块的数据,其中就包括lba_id
|
||||||
|
let block_iter = BlockIter::new(lba_id_start, count, BLOCK_SIZE);
|
||||||
|
// 调用检查函数,检查有无缺块,如果没有就可以获得所有块的Cache地址。如果失败了就直接返回FailData向量
|
||||||
|
let cache_block_addr = Self::check_able_to_read(block_iter)?;
|
||||||
|
// 块地址vec的长度应当等于块迭代器的大小
|
||||||
|
assert!(cache_block_addr.len() == block_iter.count());
|
||||||
|
// 迭代地读取cache并写入到buf中
|
||||||
|
for (index, _) in block_iter.enumerate() {
|
||||||
|
Self::read_one_block(cache_block_addr[index], index, buf)?;
|
||||||
|
}
|
||||||
|
return Ok(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// # 函数的功能
|
||||||
|
/// 检查cache中是否有缺块的函数
|
||||||
|
///
|
||||||
|
/// ## 参数:
|
||||||
|
/// - 'block_iter' :需要检查的块迭代器(因为块迭代器包含了需要读块的信息,所以传入块迭代器)
|
||||||
|
///
|
||||||
|
/// ## 返回值:
|
||||||
|
/// - Ok(Vec<CacheBlockAddr>) :如果成功了,那么函数会返回每个块的Cache地址,利用Cache地址就可以访问Cache了
|
||||||
|
/// - Err(BlockCacheError::BlockFaultError) :如果发现了缺块,那么我们会返回所有缺块的信息(即FailData)
|
||||||
|
/// - Err(BlockCacheError::____) :不缺块的情况往往是初始化或者其他问题
|
||||||
|
fn check_able_to_read(block_iter: BlockIter) -> Result<Vec<CacheBlockAddr>, BlockCacheError> {
|
||||||
|
// 存放缺块信息的向量
|
||||||
|
let mut fail_ans = vec![];
|
||||||
|
// 存放命中块地址的向量
|
||||||
|
let mut success_ans = vec![];
|
||||||
|
// 获取mapper
|
||||||
|
let mapper = unsafe { mapper()? };
|
||||||
|
for (index, i) in block_iter.enumerate() {
|
||||||
|
// 在mapper中寻找块的lba_id,判断是否命中
|
||||||
|
match mapper.find(i.lba_id()) {
|
||||||
|
Some(x) => {
|
||||||
|
success_ans.push(x);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 缺块就放入fail_ans
|
||||||
|
None => fail_ans.push(FailData::new(i.lba_id(), index)),
|
||||||
|
// 缺块不break的原因是,我们需要把所有缺块都找出来,这样才能补上缺块
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 只要有缺块就认为cache失败,因为需要补块就需要进行io操作
|
||||||
|
if !fail_ans.is_empty() {
|
||||||
|
return Err(BlockCacheError::BlockFaultError(fail_ans));
|
||||||
|
} else {
|
||||||
|
return Ok(success_ans);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// # 函数的功能
|
||||||
|
/// 在cache中读取一个块的数据并放置于缓存的指定位置
|
||||||
|
///
|
||||||
|
/// ## 参数:
|
||||||
|
/// - 'cache_block_addr' :表示需要读取的cache块的地址
|
||||||
|
/// - 'position' :表示该块的数据需要放置在buf的哪个位置,比如position为2,那么读出的数据将放置在buf\[1024..1536\](这里假设块大小是512)
|
||||||
|
/// - 'buf' :块数据的缓存
|
||||||
|
///
|
||||||
|
/// ## 返回值:
|
||||||
|
/// - Ok(usize) :表示读取了多少个字节
|
||||||
|
/// - Err(BlockCacheError) :如果输入的cache_block_addr超过了cache的容量,那么将返回Err(由于目前的cache不支持动态变化上限,所以可能出现这种错误;而实际上,由于Cache的地址是由frame_selector给出的,所以正确实现的frame_selector理论上不会出现这种错误)
|
||||||
|
fn read_one_block(
|
||||||
|
cache_block_addr: CacheBlockAddr,
|
||||||
|
position: usize,
|
||||||
|
buf: &mut [u8],
|
||||||
|
) -> Result<usize, BlockCacheError> {
|
||||||
|
let space = unsafe { space()? };
|
||||||
|
space.read(cache_block_addr, position, buf)
|
||||||
|
}
|
||||||
|
/// # 函数的功能
|
||||||
|
/// 根据缺块的数据和io获得的数据,向cache中补充块数据
|
||||||
|
///
|
||||||
|
/// ## 参数:
|
||||||
|
/// - 'f_data_vec' :这里输入的一般是从read函数中返回的缺块数据
|
||||||
|
/// - 'data' :经过一次io后获得的数据
|
||||||
|
///
|
||||||
|
/// ## 返回值:
|
||||||
|
/// Ok(usize) :表示补上缺页的个数
|
||||||
|
/// Err(BlockCacheError) :一般来说不会产生错误,这里产生错误的原因只有插入时还没有初始化(一般也很难发生)
|
||||||
|
pub fn insert(f_data_vec: Vec<FailData>, data: &[u8]) -> Result<usize, BlockCacheError> {
|
||||||
|
let count = f_data_vec.len();
|
||||||
|
for i in f_data_vec {
|
||||||
|
let index = i.index();
|
||||||
|
Self::insert_one_block(
|
||||||
|
i.lba_id(),
|
||||||
|
data[index * BLOCK_SIZE..(index + 1) * BLOCK_SIZE].to_vec(),
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
Ok(count)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// # 函数的功能
|
||||||
|
/// 将一个块数据插入到cache中
|
||||||
|
///
|
||||||
|
/// ## 参数:
|
||||||
|
/// - 'lba_id' :表明该块对应的lba_id,用于建立映射
|
||||||
|
/// - 'data' :传入的数据
|
||||||
|
///
|
||||||
|
/// ## 返回值:
|
||||||
|
/// Ok(()):表示插入成功
|
||||||
|
/// Err(BlockCacheError) :一般来说不会产生错误,这里产生错误的原因只有插入时还没有初始化(一般也很难发生)
|
||||||
|
fn insert_one_block(lba_id: BlockId, data: Vec<u8>) -> Result<(), BlockCacheError> {
|
||||||
|
let space = unsafe { space()? };
|
||||||
|
space.insert(lba_id, data)
|
||||||
|
}
|
||||||
|
/// # 函数的功能
|
||||||
|
/// 立即回写,这里仅仅作为取消映射的方法,并没有真正写入到cache的功能
|
||||||
|
///
|
||||||
|
/// ## 参数:
|
||||||
|
/// - 'lba_id_start' :需要读取的连续块的起始块
|
||||||
|
/// - 'count' :需要读取块的个数
|
||||||
|
/// - '_data' :目前没有写入功能,该参数暂时无用
|
||||||
|
///
|
||||||
|
/// ## 返回值:
|
||||||
|
/// Ok(usize) :表示写入了多少个块
|
||||||
|
/// Err(BlockCacheError) :这里产生错误的原因只有插入时还没有初始化
|
||||||
|
pub fn immediate_write(
|
||||||
|
lba_id_start: BlockId,
|
||||||
|
count: usize,
|
||||||
|
_data: &[u8],
|
||||||
|
) -> Result<usize, BlockCacheError> {
|
||||||
|
let mapper = unsafe { mapper()? };
|
||||||
|
let block_iter = BlockIter::new(lba_id_start, count, BLOCK_SIZE);
|
||||||
|
for i in block_iter {
|
||||||
|
mapper.remove(i.lba_id());
|
||||||
|
}
|
||||||
|
Ok(count)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LockedCacheSpace(RwLock<CacheSpace>);
|
||||||
|
|
||||||
|
impl LockedCacheSpace {
|
||||||
|
pub fn new(space: CacheSpace) -> Self {
|
||||||
|
LockedCacheSpace(RwLock::new(space))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read(
|
||||||
|
&self,
|
||||||
|
addr: CacheBlockAddr,
|
||||||
|
position: usize,
|
||||||
|
buf: &mut [u8],
|
||||||
|
) -> Result<usize, BlockCacheError> {
|
||||||
|
self.0.read().read(addr, position, buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn _write(&mut self, _addr: CacheBlockAddr, _data: CacheBlock) -> Option<()> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insert(&mut self, lba_id: BlockId, data: Vec<u8>) -> Result<(), BlockCacheError> {
|
||||||
|
unsafe { self.0.get_mut().insert(lba_id, data) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// # 结构功能
|
||||||
|
/// 管理Cache空间的结构体
|
||||||
|
struct CacheSpace {
|
||||||
|
/// 用于存放CacheBlock,是Cache数据的实际存储空间的向量
|
||||||
|
root: Vec<CacheBlock>,
|
||||||
|
/// 在块换出换入时,用于选择替换块的结构体
|
||||||
|
frame_selector: Box<dyn FrameSelector>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CacheSpace {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
root: Vec::new(),
|
||||||
|
// 如果要修改替换算法,可以设计一个结构体实现FrameSelector trait,再在这里替换掉SimpleFrameSelector
|
||||||
|
frame_selector: Box::new(SimpleFrameSelector::new()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// # 函数的功能
|
||||||
|
/// 将一个块的数据写入到buf的指定位置
|
||||||
|
///
|
||||||
|
/// ## 参数:
|
||||||
|
/// - 'addr' :请求块在Cache中的地址
|
||||||
|
/// - 'position' :表示需要将Cache放入buf中的位置,例如:若position为1,则块的数据放入buf\[512..1024\]
|
||||||
|
/// - 'buf' :存放数据的buf
|
||||||
|
///
|
||||||
|
/// ## 返回值:
|
||||||
|
/// Some(usize):表示读取的字节数(这里默认固定为BLOCK_SIZE)
|
||||||
|
/// Err(BlockCacheError):如果你输入地址大于cache的最大上限,那么就返回InsufficientCacheSpace
|
||||||
|
pub fn read(
|
||||||
|
&self,
|
||||||
|
addr: CacheBlockAddr,
|
||||||
|
position: usize,
|
||||||
|
buf: &mut [u8],
|
||||||
|
) -> Result<usize, BlockCacheError> {
|
||||||
|
if addr > self.frame_selector.size() {
|
||||||
|
return Err(BlockCacheError::InsufficientCacheSpace);
|
||||||
|
} else {
|
||||||
|
// CacheBlockAddr就是用于给root寻址的
|
||||||
|
return self.root[addr]
|
||||||
|
.data(&mut buf[position * BLOCK_SIZE..(position + 1) * BLOCK_SIZE]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// # 函数的功能
|
||||||
|
/// 向cache空间中写入的函数,目前尚未实现
|
||||||
|
pub fn _write(&mut self, _addr: CacheBlockAddr, _data: CacheBlock) -> Option<()> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
/// # 函数的功能
|
||||||
|
/// 向cache中插入一个块并建立lba_id到块之间的映射
|
||||||
|
///
|
||||||
|
/// ## 参数:
|
||||||
|
/// - 'lba_id' :表明你插入的块的lba_id,用于建立映射
|
||||||
|
/// - 'data' :要插入块的数据
|
||||||
|
///
|
||||||
|
/// ## 返回值:
|
||||||
|
/// Ok(())
|
||||||
|
pub fn insert(&mut self, lba_id: BlockId, data: Vec<u8>) -> Result<(), BlockCacheError> {
|
||||||
|
// CacheBlock是cached block的基本单位,这里使用data生成一个CacheBlock用于向Cache空间中插入块
|
||||||
|
let data_block = CacheBlock::from_data(lba_id, data);
|
||||||
|
let mapper = unsafe { mapper()? };
|
||||||
|
// 这里我设计了cache的一个threshold,如果不超过阈值就可以append,否则只能替换
|
||||||
|
if self.frame_selector.can_append() {
|
||||||
|
// 这是append的操作逻辑:
|
||||||
|
// 从frame_selector获得一个CacheBlockAddr
|
||||||
|
let index = self.frame_selector.index_append();
|
||||||
|
// 直接将块push进去就可以,因为现在是append操作
|
||||||
|
self.root.push(data_block);
|
||||||
|
assert!(index == self.root.len() - 1);
|
||||||
|
// 建立mapper的映射
|
||||||
|
mapper.insert(lba_id, index);
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
// 这是replace的操作逻辑
|
||||||
|
// 从frame_selector获得一个CacheBlockAddr,这次是它替换出来的
|
||||||
|
let index = self.frame_selector.index_replace();
|
||||||
|
// 获取被替换的块的lba_id,待会用于取消映射
|
||||||
|
let removed_id = self.root[index].lba_id();
|
||||||
|
// 直接替换原本的块,由于被替换的块没有引用了,所以会被drop
|
||||||
|
self.root[index] = data_block;
|
||||||
|
// 建立映射插入块的映射
|
||||||
|
mapper.insert(lba_id, index);
|
||||||
|
// 取消被替换块的映射
|
||||||
|
mapper.remove(removed_id);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LockedCacheMapper {
|
||||||
|
lock: RwLock<CacheMapper>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LockedCacheMapper {
|
||||||
|
pub fn new(inner: CacheMapper) -> Self {
|
||||||
|
Self {
|
||||||
|
lock: RwLock::new(inner),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insert(&mut self, lba_id: BlockId, caddr: CacheBlockAddr) -> Option<()> {
|
||||||
|
unsafe { self.lock.get_mut().insert(lba_id, caddr) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn find(&self, lba_id: BlockId) -> Option<CacheBlockAddr> {
|
||||||
|
self.lock.read().find(lba_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remove(&mut self, lba_id: BlockId) {
|
||||||
|
unsafe { self.lock.get_mut().remove(lba_id) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// # 结构功能
|
||||||
|
/// 该结构体用于建立lba_id到cached块的映射
|
||||||
|
struct CacheMapper {
|
||||||
|
// 执行键值对操作的map
|
||||||
|
map: HashMap<BlockId, CacheBlockAddr>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CacheMapper {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
map: HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// # 函数的功能
|
||||||
|
/// 插入操作
|
||||||
|
pub fn insert(&mut self, lba_id: BlockId, caddr: CacheBlockAddr) -> Option<()> {
|
||||||
|
self.map.insert(lba_id, caddr)?;
|
||||||
|
Some(())
|
||||||
|
}
|
||||||
|
/// # 函数的功能
|
||||||
|
/// 查找操作
|
||||||
|
#[inline]
|
||||||
|
pub fn find(&self, lba_id: BlockId) -> Option<CacheBlockAddr> {
|
||||||
|
Some(*self.map.get(&lba_id)?)
|
||||||
|
}
|
||||||
|
/// # 函数的功能
|
||||||
|
/// 去除操作
|
||||||
|
pub fn remove(&mut self, lba_id: BlockId) {
|
||||||
|
self.map.remove(&lba_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// # 结构功能
|
||||||
|
/// 该trait用于实现块的换入换出算法,需要设计替换算法只需要实现该trait即可
|
||||||
|
trait FrameSelector {
|
||||||
|
/// # 函数的功能
|
||||||
|
/// 给出append操作的index(理论上,如果cache没满,就不需要换出块,就可以使用append操作)
|
||||||
|
fn index_append(&mut self) -> CacheBlockAddr;
|
||||||
|
/// # 函数的功能
|
||||||
|
/// 给出replace操作后的index
|
||||||
|
fn index_replace(&mut self) -> CacheBlockAddr;
|
||||||
|
/// # 函数的功能
|
||||||
|
/// 判断是否可以append
|
||||||
|
fn can_append(&self) -> bool;
|
||||||
|
/// # 函数的功能
|
||||||
|
/// 获取size
|
||||||
|
fn size(&self) -> usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// # 结构功能
|
||||||
|
/// 该结构体用于管理块的换入换出过程中,CacheBlockAddr的选择,替换算法在这里实现
|
||||||
|
struct SimpleFrameSelector {
|
||||||
|
// 表示BlockCache的阈值,即最大可以存放多少块,这里目前还不支持动态变化
|
||||||
|
threshold: usize,
|
||||||
|
// 表示使用过的块帧的数量
|
||||||
|
size: usize,
|
||||||
|
// 这里使用从头至尾的替换算法,其替换策略为0,1,2,...,threshold,0,1...以此类推(该算法比FIFO还要简陋,后面可以再实现别的:)
|
||||||
|
current: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SimpleFrameSelector {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
threshold: CACHE_THRESHOLD * (1 << (20 - BLOCK_SIZE_LOG)),
|
||||||
|
size: 0,
|
||||||
|
current: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FrameSelector for SimpleFrameSelector {
|
||||||
|
fn index_append(&mut self) -> CacheBlockAddr {
|
||||||
|
let ans = self.current;
|
||||||
|
self.size += 1;
|
||||||
|
self.current += 1;
|
||||||
|
self.current %= self.threshold;
|
||||||
|
return ans;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn index_replace(&mut self) -> CacheBlockAddr {
|
||||||
|
let ans = self.current;
|
||||||
|
self.current += 1;
|
||||||
|
self.current %= self.threshold;
|
||||||
|
return ans;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn can_append(&self) -> bool {
|
||||||
|
self.size < self.threshold
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size(&self) -> usize {
|
||||||
|
self.size
|
||||||
|
}
|
||||||
|
}
|
19
kernel/src/driver/block/cache/mod.rs
vendored
Normal file
19
kernel/src/driver/block/cache/mod.rs
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
|
use self::cache_iter::FailData;
|
||||||
|
|
||||||
|
mod cache_block;
|
||||||
|
mod cache_iter;
|
||||||
|
pub mod cached_block_device;
|
||||||
|
pub const BLOCK_SIZE_LOG: usize = 9;
|
||||||
|
///块大小这里固定为512
|
||||||
|
pub const BLOCK_SIZE: usize = 1 << BLOCK_SIZE_LOG;
|
||||||
|
///这里规定Cache的threshold大小,单位为:MB
|
||||||
|
pub const CACHE_THRESHOLD: usize = 64;
|
||||||
|
|
||||||
|
pub enum BlockCacheError {
|
||||||
|
BlockSizeError,
|
||||||
|
InsufficientCacheSpace,
|
||||||
|
StaticParameterError,
|
||||||
|
BlockFaultError(Vec<FailData>),
|
||||||
|
}
|
1
kernel/src/driver/block/mod.rs
Normal file
1
kernel/src/driver/block/mod.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
pub mod cache;
|
@ -401,7 +401,7 @@ impl LockedAhciDisk {
|
|||||||
let mut buf: Vec<u8> = vec![0; size_of::<MbrDiskPartionTable>()];
|
let mut buf: Vec<u8> = vec![0; size_of::<MbrDiskPartionTable>()];
|
||||||
buf.resize(size_of::<MbrDiskPartionTable>(), 0);
|
buf.resize(size_of::<MbrDiskPartionTable>(), 0);
|
||||||
|
|
||||||
self.read_at(0, 1, &mut buf)?;
|
self.read_at_sync(0, 1, &mut buf)?;
|
||||||
// 创建 Cursor 用于按字节读取
|
// 创建 Cursor 用于按字节读取
|
||||||
let mut cursor = VecCursor::new(buf);
|
let mut cursor = VecCursor::new(buf);
|
||||||
cursor.seek(SeekFrom::SeekCurrent(446))?;
|
cursor.seek(SeekFrom::SeekCurrent(446))?;
|
||||||
@ -562,7 +562,7 @@ impl BlockDevice for LockedAhciDisk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn read_at(
|
fn read_at_sync(
|
||||||
&self,
|
&self,
|
||||||
lba_id_start: BlockId, // 起始lba编号
|
lba_id_start: BlockId, // 起始lba编号
|
||||||
count: usize, // 读取lba的数量
|
count: usize, // 读取lba的数量
|
||||||
@ -572,7 +572,7 @@ impl BlockDevice for LockedAhciDisk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn write_at(
|
fn write_at_sync(
|
||||||
&self,
|
&self,
|
||||||
lba_id_start: BlockId,
|
lba_id_start: BlockId,
|
||||||
count: usize,
|
count: usize,
|
||||||
|
@ -4,6 +4,7 @@ pub mod ahcidisk;
|
|||||||
pub mod hba;
|
pub mod hba;
|
||||||
|
|
||||||
use crate::driver::base::block::disk_info::BLK_GF_AHCI;
|
use crate::driver::base::block::disk_info::BLK_GF_AHCI;
|
||||||
|
use crate::driver::block::cache::cached_block_device::BlockCache;
|
||||||
// 依赖的rust工具包
|
// 依赖的rust工具包
|
||||||
use crate::driver::pci::pci::{
|
use crate::driver::pci::pci::{
|
||||||
get_pci_device_structure_mut, PciDeviceStructure, PCI_DEVICE_LINKEDLIST,
|
get_pci_device_structure_mut, PciDeviceStructure, PCI_DEVICE_LINKEDLIST,
|
||||||
@ -141,6 +142,7 @@ pub fn ahci_init() -> Result<(), SystemError> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
BlockCache::init();
|
||||||
}
|
}
|
||||||
|
|
||||||
compiler_fence(core::sync::atomic::Ordering::SeqCst);
|
compiler_fence(core::sync::atomic::Ordering::SeqCst);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
pub mod acpi;
|
pub mod acpi;
|
||||||
pub mod base;
|
pub mod base;
|
||||||
|
pub mod block;
|
||||||
pub mod disk;
|
pub mod disk;
|
||||||
pub mod firmware;
|
pub mod firmware;
|
||||||
pub mod input;
|
pub mod input;
|
||||||
|
@ -225,7 +225,7 @@ impl BiosParameterBlock {
|
|||||||
// 读取分区的引导扇区
|
// 读取分区的引导扇区
|
||||||
partition
|
partition
|
||||||
.disk()
|
.disk()
|
||||||
.read_at(partition.lba_start as usize, 1, &mut v)?;
|
.read_at_sync(partition.lba_start as usize, 1, &mut v)?;
|
||||||
|
|
||||||
// 获取指针对象
|
// 获取指针对象
|
||||||
let mut cursor = VecCursor::new(v);
|
let mut cursor = VecCursor::new(v);
|
||||||
|
@ -1001,7 +1001,7 @@ impl FATFileSystem {
|
|||||||
let mut v: Vec<u8> = vec![0; self.lba_per_sector() * LBA_SIZE];
|
let mut v: Vec<u8> = vec![0; self.lba_per_sector() * LBA_SIZE];
|
||||||
self.partition
|
self.partition
|
||||||
.disk()
|
.disk()
|
||||||
.read_at(lba, self.lba_per_sector(), &mut v)?;
|
.read_at_sync(lba, self.lba_per_sector(), &mut v)?;
|
||||||
|
|
||||||
let mut cursor: VecCursor = VecCursor::new(v);
|
let mut cursor: VecCursor = VecCursor::new(v);
|
||||||
cursor.seek(SeekFrom::SeekSet(in_block_offset as i64))?;
|
cursor.seek(SeekFrom::SeekSet(in_block_offset as i64))?;
|
||||||
@ -1032,7 +1032,7 @@ impl FATFileSystem {
|
|||||||
let mut v: Vec<u8> = vec![0; self.lba_per_sector() * LBA_SIZE];
|
let mut v: Vec<u8> = vec![0; self.lba_per_sector() * LBA_SIZE];
|
||||||
self.partition
|
self.partition
|
||||||
.disk()
|
.disk()
|
||||||
.read_at(lba, self.lba_per_sector(), &mut v)?;
|
.read_at_sync(lba, self.lba_per_sector(), &mut v)?;
|
||||||
|
|
||||||
let mut cursor: VecCursor = VecCursor::new(v);
|
let mut cursor: VecCursor = VecCursor::new(v);
|
||||||
cursor.seek(SeekFrom::SeekSet(in_block_offset as i64))?;
|
cursor.seek(SeekFrom::SeekSet(in_block_offset as i64))?;
|
||||||
@ -1078,7 +1078,7 @@ impl FATFileSystem {
|
|||||||
let lba = self.get_lba_from_offset(self.bytes_to_sector(fat_part_bytes_offset));
|
let lba = self.get_lba_from_offset(self.bytes_to_sector(fat_part_bytes_offset));
|
||||||
|
|
||||||
let mut v: Vec<u8> = vec![0; LBA_SIZE];
|
let mut v: Vec<u8> = vec![0; LBA_SIZE];
|
||||||
self.partition.disk().read_at(lba, 1, &mut v)?;
|
self.partition.disk().read_at_sync(lba, 1, &mut v)?;
|
||||||
|
|
||||||
let mut cursor: VecCursor = VecCursor::new(v);
|
let mut cursor: VecCursor = VecCursor::new(v);
|
||||||
cursor.seek(SeekFrom::SeekSet(in_block_offset as i64))?;
|
cursor.seek(SeekFrom::SeekSet(in_block_offset as i64))?;
|
||||||
@ -1227,7 +1227,7 @@ impl FATFsInfo {
|
|||||||
// 计算fs_info扇区在磁盘上的字节偏移量,从磁盘读取数据
|
// 计算fs_info扇区在磁盘上的字节偏移量,从磁盘读取数据
|
||||||
partition
|
partition
|
||||||
.disk()
|
.disk()
|
||||||
.read_at(in_disk_fs_info_offset as usize / LBA_SIZE, 1, &mut v)?;
|
.read_at_sync(in_disk_fs_info_offset as usize / LBA_SIZE, 1, &mut v)?;
|
||||||
let mut cursor = VecCursor::new(v);
|
let mut cursor = VecCursor::new(v);
|
||||||
|
|
||||||
let mut fsinfo = FATFsInfo {
|
let mut fsinfo = FATFsInfo {
|
||||||
|
2
user/apps/test-blockcache/.cargo/config.toml
Normal file
2
user/apps/test-blockcache/.cargo/config.toml
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
[build]
|
||||||
|
target = "x86_64-unknown-linux-musl"
|
3
user/apps/test-blockcache/.gitignore
vendored
Normal file
3
user/apps/test-blockcache/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
/target
|
||||||
|
Cargo.lock
|
||||||
|
/install/
|
10
user/apps/test-blockcache/Cargo.toml
Normal file
10
user/apps/test-blockcache/Cargo.toml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
[package]
|
||||||
|
name = "test-blockcache"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
description = "用于测试blockcac小程序"
|
||||||
|
authors = [ "ZZJJWarth <2678328250@qq.com>" ]
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
41
user/apps/test-blockcache/Makefile
Normal file
41
user/apps/test-blockcache/Makefile
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
# The toolchain we use.
|
||||||
|
# You can get it by running DragonOS' `tools/bootstrap.sh`
|
||||||
|
TOOLCHAIN="+nightly-2023-08-15-x86_64-unknown-linux_dragonos-gnu"
|
||||||
|
RUSTFLAGS+="-C target-feature=+crt-static -C link-arg=-no-pie"
|
||||||
|
|
||||||
|
# 如果是在dadk中编译,那么安装到dadk的安装目录中
|
||||||
|
INSTALL_DIR?=$(DADK_CURRENT_BUILD_DIR)
|
||||||
|
# 如果是在本地编译,那么安装到当前目录下的install目录中
|
||||||
|
INSTALL_DIR?=./install
|
||||||
|
|
||||||
|
|
||||||
|
run:
|
||||||
|
RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) run
|
||||||
|
|
||||||
|
build:
|
||||||
|
RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) build
|
||||||
|
|
||||||
|
clean:
|
||||||
|
RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) clean
|
||||||
|
|
||||||
|
test:
|
||||||
|
RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) test
|
||||||
|
|
||||||
|
doc:
|
||||||
|
RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) doc
|
||||||
|
|
||||||
|
run-release:
|
||||||
|
RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) run --release
|
||||||
|
|
||||||
|
build-release:
|
||||||
|
RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) build --release
|
||||||
|
|
||||||
|
clean-release:
|
||||||
|
RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) clean --release
|
||||||
|
|
||||||
|
test-release:
|
||||||
|
RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) test --release
|
||||||
|
|
||||||
|
.PHONY: install
|
||||||
|
install:
|
||||||
|
RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) install --path . --no-track --root $(INSTALL_DIR) --force
|
8
user/apps/test-blockcache/README.md
Normal file
8
user/apps/test-blockcache/README.md
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
## 程序说明
|
||||||
|
用于测试BlockCache的测试程序
|
||||||
|
本程序生成一个文件,并开始对这个文件进行单纯的读操作(共读10000次)
|
||||||
|
|
||||||
|
## 使用方法
|
||||||
|
|
||||||
|
1. 打开系统的/bin目录
|
||||||
|
2. 输入指令exec test-blockcache即可开始测试
|
22
user/apps/test-blockcache/src/main.rs
Normal file
22
user/apps/test-blockcache/src/main.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
use std::fs::File;
|
||||||
|
use std::io::{BufReader, Read, Seek, SeekFrom, Write};
|
||||||
|
|
||||||
|
fn main() -> std::io::Result<()> {
|
||||||
|
let file_size_bytes: u64 = 512;
|
||||||
|
let mut file = File::create("large_file")?;
|
||||||
|
file.seek(std::io::SeekFrom::Start(file_size_bytes - 1))?;
|
||||||
|
file.write_all(&[0])?;
|
||||||
|
let mut file = File::open("large_file")?;
|
||||||
|
// let mut reader = BufReader::new(file);
|
||||||
|
let mut buffer = [0; 512];
|
||||||
|
let mut count = 0;
|
||||||
|
loop {
|
||||||
|
count += 1;
|
||||||
|
file.seek(SeekFrom::Start(0))?;
|
||||||
|
let bytes_read = file.read_exact(&mut buffer)?;
|
||||||
|
if count > 10000 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
24
user/dadk/config/test_blockcache_0_1_0.dadk
Normal file
24
user/dadk/config/test_blockcache_0_1_0.dadk
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"name": "test-blockcache",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description": "用于测试blockcach小程序",
|
||||||
|
"rust_target": "x86_64-unknown-dragonos",
|
||||||
|
"task_type": {
|
||||||
|
"BuildFromSource": {
|
||||||
|
"Local": {
|
||||||
|
"path": "apps/test-blockcache"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"depends": [],
|
||||||
|
"build": {
|
||||||
|
"build_command": "make install"
|
||||||
|
},
|
||||||
|
"install": {
|
||||||
|
"in_dragonos_path": "/"
|
||||||
|
},
|
||||||
|
"clean": {
|
||||||
|
"clean_command": "make clean"
|
||||||
|
},
|
||||||
|
"envs": []
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user