Integrate Blog OS with CrossBus VGA Text
The Blog OS is a great series of source to create a small operating system in rust language.
And CrossBus is a lower level actor computing model compatible with bare metal, can efficiently and asynchronously transmit / share data between components which may make a difference in OS development.
Integration Target
Only the first 3 posts (by Vga-text) will be touched in the section. So if you don't familiar with post-1 or post-2 you'd better take a look beforehand.
Pre-Requisites
Since crossbus use rust alloc crate,
- we must add
alloc
to thebuild-std
field of.cargo/config.toml
:
build-std = ["core", "compiler_builtins", "alloc"]
- mark the global allocator
- add
emballoc
to your dependencies - specified the global_allocator: ``
#![allow(unused)] fn main() { #[global_allocator] static ALLOCATOR: emballoc::Allocator<4096> = emballoc::Allocator::new(); }
- add
Overview of Actor's Life Cycle
Here represents a simple illustration :
actor::create --> ActorRegister --> push to global static Register --> dropped when closed
Changes
- Switch to static Register instead of lazy_static / spinlocks
recall that the blog os defines a glocal Writer
with lazy_static
and guarded with spin::Mutex
#![allow(unused)] fn main() { lazy_static! { pub static ref WRITER: Mutex<Writer> = Mutex::new(Writer { column_position: 0, color_code: ColorCode::new(Color::Yellow, Color::Black), buffer: unsafe { &mut *(0xb8000 as *mut Buffer) }, }); } }
with crossbus, you
-
don't have to worry about static / lock, or some stuff like that;
-
access any type implemented trait
Actor
with global static mutable/sharing reference;
Details
So the dependencies spin
or lazy_static
is not necessary here:
#![allow(unused)] fn main() { // define the message pub struct Msg(String); // impl the Message trait impl message::Message for Msg {} impl Actor for Writer { type Message = Msg; // normally create the Writer fn create(_: &mut Context<Self>) -> Self { Writer { column_position: 0, color_code: ColorCode::new(Color::Yellow, Color::Black), buffer: unsafe { &mut *(0xb8000 as *mut Buffer) }, } } // this line is not necessary though // a syntax must // // since we dont use an writer instance then // call this method fn action(&mut self, _: Self::Message, _: &mut Context<Self>) {} } }
According to the illustration above,
once the actor is created, you can access it as glocal static item,
and downcast it to the original type Writer
, and you don't
manually lock the Writer
( crossbus has assure its exclusively access)
#![allow(unused)] fn main() { // mark the writer's actor id // used to get writer from `crossbus::Register` static WRITERID: AtomicUsize = AtomicUsize::new(0); // if Writer is not created // then create one if WRITERID.load(Ordering::Acquire) == 0 { let (_, id) = Writer::start(); WRITERID.store(id, Ordering::Release); } // find the actor by id and Register::get(WRITERID.load(Ordering::Acquire)) .unwrap() // downcast the actor as mutable reference of Writer .downcast_mut::<Writer, _>( // here pass a closure, // writer is a mutable reference |writer: &mut Writer| { // and use it write string to display writer.write_fmt(args).unwrap(); Ok(()) }, ); }
Results
go the project directory and use cargo run
, you will see:
Code
this is the a section of integrating blog os with crossbus, the full code is at here