Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Patch refactor scm and textui #289

Merged
merged 37 commits into from
Aug 19, 2023

Conversation

hanjiezhou
Copy link
Contributor

重构了屏幕管理器和textui框架

SCM_FRAMEWORK_LIST.lock().push_back(framework.clone());
// 调用ui框架的回调函数以安装ui框架,并将其激活
framework.install()?;
framework.enable()?;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

为啥这里要调用enable,然后里面又调用1次

pub extern "C" fn scm_enable_double_buffer() -> i32 {
let r = ture_scm_enable_double_buffer()
.map_err(|e| e.to_posix_errno())
.unwrap();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里产生err的时候,直接unwrap会产生错误

*/
#[no_mangle]
pub extern "C" fn scm_enable_double_buffer() -> i32 {
let r = ture_scm_enable_double_buffer()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

true打错字啦,类似的地方还有好几处

}
/**
* @brief 销毁双缓冲区
*
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

类似这样的代码需要删掉

}
}

pub fn get_vaddr(&self) -> usize {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这种函数命名不符合规范,不需要get_前缀。

pub extern "C" fn scm_disable_put_to_window() {
// unsafe{kfree(*TEXTUI_BUF_VADDR.read() as *mut c_void)};

unsafe { ENABLE_PUT_TO_WINDOW = false };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

原子变量

* @return int
*/
#[no_mangle]
pub extern "C" fn rs_textui_init() -> i32 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

导出到C的函数,都把他们丢到一个新的文件“c_adapter.rs"吧


drop(private_info);

unsafe { TEST_IS_INIT = true };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个干啥用的

pub static CHAR_PER_LINE: RwLock<i32> = RwLock::new(0);
//textui 未初始化时直接向缓冲区写,不使用虚拟行
pub static NO_INIT_OPERATIONS_LINE: RwLock<i32> = RwLock::new(0);
pub static NO_INIT_OPERATIONS_INDEX: RwLock<i32> = RwLock::new(0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个变量我看的很迷惑,这个干啥用的?是未初始化内存管理的时候,用于记录下标的吗?

还有就是,我建议把内存管理未初始化的时候,相关的textui代码独立到一个新的文件"textui_mm_no_init.rs“,这样看的清楚一点。

还有就是,不要用rwlock去保护i32,直接原子变量就行了

@@ -0,0 +1,44 @@
// use crate::include::bindings::bindings::PAGE_PCD;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

删掉这个文件

@hanjiezhou hanjiezhou closed this Jul 21, 2023
@hanjiezhou hanjiezhou reopened this Jul 21, 2023
&emsp;&emsp;用于储存scm中的ui框架中的帧缓冲区中的信息,定义如下:
```rust
#[derive(Debug, Clone)]
pub struct ScmBufferInfo {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

具体数据结构的内容我感觉可以不用放上文档,因为很难保持同步。只要说说是哪个结构就好,我觉得。然后文档主要讲实现思路(架构上面的),不用过于细节。因为细节的去看代码就能看的明白,因此我感觉把更高一个层次的视角的框架设计,写出来会更有用,下面那个文档也是一样的。

}
/// 允许往窗口打印信息
#[no_mangle]
pub extern "C" fn scm_enable_put_to_window() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个函数和下面的disable都不需要extern C

kernel/src/libs/spinlock.rs Outdated Show resolved Hide resolved
}

#[derive(Debug, Clone)]
pub struct ScmBufferInfo {
Copy link
Member

@fslongjin fslongjin Aug 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

命名问题

这个结构体命名为ScmBuffer更合适

存在内存泄露问题

要为这个结构体实现Drop trait,在它被drop的时候释放缓冲区(如果是动态申请来的),否则将会造成内存泄露。

并且,由于在很多地方都直接clone这个结构体,然后把vaddr指向的内存当作缓冲区来使用,因此本身就存在大量的“越界访问”的隐患。上面derive的Clone需要删掉。

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个结构体命名为ScmBuffer更合适


frame_buffer_info.flags = buf_type;

frame_buffer_info.vaddr = VirtAddr::new(unsafe { kzalloc(video_frame_buffer_info.size as usize, 0) });
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

不要使用kzalloc申请内存,请使用allocate_frames,并且映射到指定的位置。

pub fn vaddr(&self) -> usize {
self.vaddr.data()
}
pub fn buf_size_about_u8(&self) -> u32 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个命名很有迷惑性,而且没有注释。需要更改。下面那个buf_size_about_u32同理

}
pub trait ScmUiFramework: Sync + Send + Debug {
// 安装ui框架的回调函数
fn install(&self) -> Result<i32, SystemError> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这些函数全部都不需要默认实现吧,我感觉都是必须的?


let metadata = framework.metadata()?;

if metadata.buf_info.vaddr.data() == 0 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

调用vaddr的is_null方法,而不是这样写

@@ -1,7 +1,14 @@
#pragma once
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个文件我感觉可以删掉了

Comment on lines 39 to 48
Arc::new(SpinLock::new(TextuiWindow::new(
WindowFlag::TEXTUI_IS_CHROMATIC,
0,
0,
))),
Arc::new(SpinLock::new(TextuiWindow::new(
WindowFlag::TEXTUI_IS_CHROMATIC,
0,
0,
))),
Copy link
Member

@fslongjin fslongjin Aug 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

current window为啥要和default的是不同的2个实例呀。。。
而且不应该先初始化line数量为0的window对象,然后再在外面的函数进行初始化赋值。这样不满足“资源获取即初始化”


// 遍历当前所有使用帧缓冲区的框架,更新地址
for framework in SCM_FRAMEWORK_LIST.lock().iter_mut() {
framework.change(unsafe { ScmBufferInfo::from(&video_frame_buffer_info) })?;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

为什么要把所有的框架的缓冲区都设置成相同的???

// 遍历当前所有使用帧缓冲区的框架,更新地址
drop(scm_list);
for framework in SCM_FRAMEWORK_LIST.lock().iter_mut() {
(*framework).change(buf_info.clone())?;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里也是,为什么要把所有框架的缓冲区设置成相同的?

pub static SCM_DOUBLE_BUFFER_ENABLED: AtomicBool = AtomicBool::new(false);

bitflags! {
pub struct ScmBfFlag:u8{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个命名也需要改,很有迷惑性。一般不用bf来代指buffer的,这不是常用缩写

}

#[derive(Debug, Clone)]
pub struct ScmBufferInfo {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个结构体命名为ScmBuffer更合适

}
}

#[derive(Debug, Clone)]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

由于buffer的内存安全问题,这个不应该继承clone

@fslongjin
Copy link
Member

还有,textui.h里面有很多的无用的函数导出、无用的数据结构,这些都要删除

Comment on lines 849 to 860
/// 将窗口的帧缓冲区内容清零
pub fn _renew_buf(&self) {
// let mut addr: *mut u32 = fb as *mut u32;
let mut addr: *mut u32 = self.metadata.buf_info.vaddr() as *mut u32;

for _i in 0..self.metadata.buf_info.buf_size_about_u8() {
unsafe { *addr = 0 };
unsafe {
addr = (addr.offset(1)) as *mut u32;
}
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

感觉这个函数可以删掉

fn change(&self, buf: ScmBufferInfo) -> Result<i32, SystemError> {
let src = self.metadata.buf_info.vaddr() as *const u8;
let dst = buf.vaddr() as *mut u8;
let count = self.metadata.buf_info.buf_size_about_u8() as usize;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里有内存安全问题,没有检查src和dst是否同样大小。建议把拷贝缓冲区内容的工作,写成buffer的成员函数。

/// -失败:Err(错误码)
fn metadata(&self) -> Result<ScmUiFrameworkMetadata, SystemError> {
// let framework_guard = self.0.lock();
let metadata = self.metadata.clone();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个函数会把buffer的vaddr给拷贝出去,这是有问题的,可能会导致难以定位的内存越界访问

}
}

impl Deref for TextUiFramework {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个deref和derefMut我建议删掉,因为他们允许外界对Metadata结构体的直接操作,破坏了封装性

@fslongjin fslongjin merged commit abe3a6e into DragonOS-Community:master Aug 19, 2023
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants