添加 IPC 服务
本指南介绍如何为 OpenOS 添加新的 IPC 服务。
IPC 服务开发步骤
Section titled “IPC 服务开发步骤”1. 定义消息类型
Section titled “1. 定义消息类型”#[derive(Debug, Clone)]pub enum Request { Read { offset: u64, length: u64 }, Write { offset: u64, data: Vec<u8> }, GetStatus,}
#[derive(Debug, Clone)]pub enum Response { ReadResult { data: Vec<u8> }, WriteResult { bytes_written: u64 }, Status { ready: bool, error: Option<String> }, Error { code: i64, message: String },}2. 实现服务逻辑
Section titled “2. 实现服务逻辑”use alloc::collections::VecDeque;use spin::Mutex;
pub struct MyService { port_id: u64, buffer: Vec<u8>,}
impl MyService { pub fn new(port_id: u64) -> Self { MyService { port_id, buffer: Vec::new(), } }
pub fn handle_request(&mut self, request: Request) -> Response { match request { Request::Read { offset, length } => self.handle_read(offset, length), Request::Write { offset, data } => self.handle_write(offset, &data), Request::GetStatus => self.handle_get_status(), } }
fn handle_read(&self, offset: u64, length: u64) -> Response { let offset = offset as usize; let length = length as usize;
if offset >= self.buffer.len() { return Response::Error { code: -1, message: "Offset out of bounds".to_string(), }; }
let end = core::cmp::min(offset + length, self.buffer.len()); let data = self.buffer[offset..end].to_vec(); Response::ReadResult { data } }
fn handle_write(&mut self, offset: u64, data: &[u8]) -> Response { let offset = offset as usize; if offset + data.len() > self.buffer.len() { self.buffer.resize(offset + data.len(), 0); } self.buffer[offset..offset + data.len()].copy_from_slice(data); Response::WriteResult { bytes_written: data.len() as u64 } }
fn handle_get_status(&self) -> Response { Response::Status { ready: true, error: None } }}3. 创建服务主循环
Section titled “3. 创建服务主循环”pub fn service_main(port_id: u64) -> ! { let mut service = MyService::new(port_id);
loop { let mut buffer = [0u8; 4096]; let received = sys_receive(port_id, &mut buffer).unwrap();
let request = match Request::from_bytes(&buffer[..received]) { Ok(req) => req, Err(e) => { serial_println!("[MY_SERVICE] Failed to parse request: {:?}", e); continue; } };
let response = service.handle_request(request); let response_bytes = response.to_bytes(); if let Err(e) = sys_send(port_id, &response_bytes) { serial_println!("[MY_SERVICE] Failed to send response: {:?}", e); } }}4. 注册服务
Section titled “4. 注册服务”pub mod my_service;
pub fn init_all() { let port_id = sys_port_create().unwrap(); register_service("my_service", port_id); spawn_service_thread(port_id, my_service::service_main);}5. 创建客户端库
Section titled “5. 创建客户端库”pub struct MyServiceClient { port_id: u64,}
impl MyServiceClient { pub fn new(port_id: u64) -> Self { MyServiceClient { port_id } }
pub fn read(&self, offset: u64, length: u64) -> Result<Vec<u8>, Error> { let request = Request::Read { offset, length }; let response = self.send_request(request)?;
match response { Response::ReadResult { data } => Ok(data), Response::Error { code, message } => Err(Error::ServiceError(code, message)), _ => Err(Error::InvalidResponse), } }
pub fn write(&self, offset: u64, data: &[u8]) -> Result<u64, Error> { let request = Request::Write { offset, data: data.to_vec(), }; let response = self.send_request(request)?;
match response { Response::WriteResult { bytes_written } => Ok(bytes_written), Response::Error { code, message } => Err(Error::ServiceError(code, message)), _ => Err(Error::InvalidResponse), } }
fn send_request(&self, request: Request) -> Result<Response, Error> { let request_bytes = request.to_bytes(); let mut response_bytes = [0u8; 4096];
let received = sys::channel_call( self.port_id, &request_bytes, &mut response_bytes, )?;
Response::from_bytes(&response_bytes[..received]) .map_err(|_| Error::InvalidResponse) }}服务设计模式
Section titled “服务设计模式”请求-响应模式
Section titled “请求-响应模式”最常见的模式,客户端发送请求,服务器返回响应。
发布-订阅模式
Section titled “发布-订阅模式”服务发布事件,客户端订阅感兴趣的消息。
流式传输模式
Section titled “流式传输模式”服务发送流式数据,客户端逐步接收。
#[derive(Debug, Clone)]pub enum ServiceError { InvalidRequest(String), ResourceExhausted, PermissionDenied, ServiceUnavailable, Timeout, InternalError(String),}// 推荐:批量处理client.process_batch(items)?;let shared_mem = sys_memory_create(data.len(), MEMORY_SHARED)?;unsafe { core::ptr::copy_nonoverlapping( data.as_ptr(), shared_mem.as_mut_ptr(), data.len(), );}- IPC 协议 - IPC 协议规范
- Channel IPC - Channel 通信机制
- 代码质量 - 代码质量标准