Octox
Unix-like OS in Rust inspired by xv6-riscv
Install / Use
/learn @o8vm/OctoxREADME
#+title: octox #+author: Hayato Ohhashi #+email: o8@vmm.dev
octox is a Unix-like operating system inspired by xv6-riscv. octox loosely follows the structure and style of xv6, but is implemented in pure Rust.
[[https://vhs.charm.sh/vhs-6MQBIyAo3DpBrARBxHxL35.gif]]
- Everything from kernel, userland, mkfs, to build system is written in safe Rust as much as possible.
- There are no dependencies on external crates.
- The userland has a library similar to Rust’s std with K&R malloc.
- Multi-core support, buddy allocator as kernel-side memory allocator, file system with logging support, etc.
- Getting Started
** Requirements
- Install the rust toolchain to have cargo installed by following [[https://www.rust-lang.org/tools/install][this]] guide.
- Install ~qemu-system-riscv~
- (option) Install ~gdb-multiarch~
** Build and Run
- Clone this project & enter: ~git clone ... && cd octox~
- Build: ~cargo build --target riscv64gc-unknown-none-elf~.
- Run: ~cargo run --target riscv64gc-unknown-none-elf~, then qemu will boot octox. To exit, press ~Ctrl+a~ and ~x~.
** Play with the Shell
A very simple shell is implemented. In addition to executing commands, you can only do the following things.
- Pipe: ~cat file | head | grep test~
- Dump processes: ~Ctrl + P~
- End of line: ~Ctrl + D~
- Redirect output: ~>~, ~>>~
- Development
** Userland Application
The userland comes with a user library called ulib (located at src/user/lib) that is similar to Rust’s std, so you can use it to develop your favorite commands. If you create a bin crate named ~_command~ in src/user/bin, the build.rs and mkfs.rs will place a file named ~command~ in the file system and make it available for use.
-
In src/user/Cargo.toml, define a bin crate with the name of the command you want to create with a ~_~ prefix #+begin_src toml [[bin]] name = "_rm" path = "bin/rm.rs" #+end_src
-
userland is also no_std, so don’t forget to add ~#[no_std]~. Use ulib to develop any command you like. Here is an example of the rm command. #+begin_src rust #![no_std] use ulib::{env, fs};
fn main() { let mut args = env::args().skip(1).peekable();
if args.peek().is_none() { panic!("Usage: rm files...") } for arg in args { fs::remove_file(arg).unwrap() }} #+end_src
-
Then, ~cargo run --target riscv64gc-unknown-none-elf~ in the root of octox.
-
To use ~Vec~ and ~String~, etc, do the following: #+begin_src rust extern crate alloc; use alloc::{string::String, vec::Vec}; #+end_src
** Kernel
Developing in src/kernel. Here is an example of adding a system call. If you want to add a new system call, you only need to add a definition to the system call table in libkernel, and the userland library will be automatically generated by build.rs.
- Add a variant and Syscall Number to ~enum SysCalls~ in src/kernel/syscall.rs. Here is ~Dup2~ as an example: #+begin_src rust pub enum SysCalls { Fork = 1, ..., Dup2 = 23, Invalid = 0, } #+end_src
- Define the function signature of the system call in the ~TABLE~ of ~SysCalls~. Use the enum type ~Fn~ to describe the return type(~U~ (Unit), ~I~ (Integer), ~N~ (never)) and use ~&str~ to represent arguments. then, define kernel-side implementation as a method on ~SysCalls~. ~cfg~ flag is used to control the compilation target for kernel and the rest. Here is an example of ~dup2~: #+begin_src rust impl SysCalls { pub const TABLE: [(fn, &'static str); variant_count::<Self>()] = [ (Fn::N(Self::Invalid), ""), (Fn::I(Self::fork), "()"), (Fn::N(Self::exit), "(xstatus: i32)"), ..., (Fn::I(Self::dup2), "(src: usize, dst: usize)"), ]; pub fn dup2() -> Result<usize> { #[cfg(not(all(target_os = "none", feature = "kernel")))] return Ok(0); #[cfg(all(target_os = "none", feature = "kernel"))] { let p = Cpus::myproc().unwrap().data_mut(); let src_fd = argraw(0); let dst_fd = argraw(1); if src_fd != dst_fd { let mut src = p.ofile.get_mut(src_fd).unwrap() .take().unwrap(); src.clear_cloexec(); p.ofile.get_mut(dst_fd) .ok_or(FileDescriptorTooLarge)?.replace(src); } Ok(dst_fd) } } #+end_src
- With just these steps, the dup2 system call is implemented in both kernel and userland.
- License
Licensed under either of
- [[http://www.apache.org/licenses/LICENSE-2.0][Apache License, Version 2.0]]
- [[http://opensource.org/licenses/MIT][MIT license]]
at your option.
- Acknowledgments
octox is inspired by [[https://github.com/mit-pdos/xv6-riscv][xv6-riscv]].
I'm also grateful for the bug reports and discussion about the implementation contributed by Takahiro Itazuri and Kuniyuki Iwashima.
- Contribution
This is a hobby learning project, but contributions are welcome! However, please note that reviews may take considerable time. Discussions and advice are always appreciated.
Related Skills
himalaya
341.6kCLI to manage emails via IMAP/SMTP. Use `himalaya` to list, read, write, reply, forward, search, and organize emails from the terminal. Supports multiple accounts and message composition with MML (MIME Meta Language).
node-connect
341.6kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
84.6kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
coding-agent
341.6kDelegate coding tasks to Codex, Claude Code, or Pi agents via background process
