请求处理器

在之前的内核线程中,我们看到所有内核服务线程结构都是统一的,但其中包含一个processor成员用于处理具体的请求:

/// 解析请求类型并进行具体地处理
pub trait Processor: Send + Sync {
    /// 处理当前请求,完毕后唤醒相应的等待协程
    fn process_request(&self, request: Request);
}

process_request方法完成给定请求的整个处理过程,并唤醒这个请求的等待协程。下面我们以文件系统请求处理器为例来说明:

/// 文件系统请求处理器
pub struct FsProcessor;

impl FsProcessor {
    pub fn new() -> Arc<Self> {
        Arc::new(FsProcessor {})
    }
}

文件系统请求处理器不含任何成员,只为他实现Processor trait

impl Processor for FsProcessor {
    /// 处理一个文件系统请求,并不响应请求(在内核入口函数中响应)
    fn process_request(&self, request: Request) {
        let fs_req = FsReqDescription::from_bytes(&request);
        match fs_req {
            // Read请求,进程Pid读文件表中fd对应的文件到buf中
            FsReqDescription::Read(pid, fd, buf_ptr, buf_len, result_ptr) => {
                // 解析buf
                ...
                // 获取磁盘文件
                ...
                // 读文件
                let read_size = if !file.readable() {
                    println!("[Fs server] Error reading file, not readable!");
                    usize::MAX
                } else {
                    file.read(buf)
                };
                // 将read_size写入到用户态中
                ....
            }
            // Write请求,进程Pid将buf中的数据写入文件表中fd对应的文件
            FsReqDescription::Write(pid, fd, buf_ptr, buf_len, result_ptr) => {
                // 解析buf
                ....
                // 获取磁盘文件
                ...
                // 写文件
                let write_size = if !file.writable() {
                    println!("[Fs server] Error writing file, not readable!");
                    usize::MAX
                } else {
                    file.write(buf)
                };
                // 将write_size写入到用户态中
                ....
            }
            // 处理Open请求,打开一个磁盘文件并加入pid进程的文件表中
            FsReqDescription::Open(pid, path_ptr, flags, fd_ptr) => {
                // 解析路径
                .....
                // 可以创建文件
                let file = if flags.contains(OpenFlags::CREATE) {
                    // 文件已存在
                    ....
                    // 不存在,创建文件
                    } else {
                        ROOT_INODE
                            .create(path)
                            .map(|inode| Arc::new(OSInode::new(readable, writable, inode)))
                    }
                // 不能创建文件,打开文件
                } else {
                    ROOT_INODE.find(path).map(|inode| {
                        if flags.contains(OpenFlags::TRUNC) {
                            inode.clear();
                        }
                        Arc::new(OSInode::new(readable, writable, inode))
                    })
                };
                // 结果写回用户态
                ....
            }
        }
    }
}

处理器首先调用之前提到过的from_bytes方法将字节解析为文件系统请求,再根据请求的不同类型进行不同的处理。

在实际的处理过程中,调用了文件系统的相关接口,这些接口都会最终调用底层的块设备驱动,因此我们认为这些操作并不是完全可靠的。