https://github.com/o8vm/octox
Unix-like OS in Rust inspired by xv6-riscv
https://github.com/o8vm/octox
osdev riscv rust xv6-riscv
Last synced: 9 months ago
JSON representation
Unix-like OS in Rust inspired by xv6-riscv
- Host: GitHub
- URL: https://github.com/o8vm/octox
- Owner: o8vm
- License: apache-2.0
- Created: 2021-04-21T04:57:46.000Z (almost 5 years ago)
- Default Branch: main
- Last Pushed: 2024-07-31T17:15:30.000Z (over 1 year ago)
- Last Synced: 2025-05-15T19:05:28.566Z (9 months ago)
- Topics: osdev, riscv, rust, xv6-riscv
- Language: Rust
- Homepage:
- Size: 181 KB
- Stars: 1,542
- Watchers: 24
- Forks: 62
- Open Issues: 4
-
Metadata Files:
- Readme: README.org
- License: LICENSE-APACHE
Awesome Lists containing this project
- awesome - octox - like operating system inspired (Active)
- StarryDivineSky - o8vm/octox - riscv 启发的 Rust 类 Unix 操作系统。octox 松散地遵循 xv6 的结构和风格,但在纯 Rust 中实现。从内核、用户空间、mkfs 到构建系统,一切都尽可能用安全的 Rust 编写。对外部没有依赖性。用户空间有一个类似于 Rust 的带有 K&R malloc 的 std 的库。多核支持、作为内核侧内存分配器的伙伴分配器、支持日志记录的文件系统等。 (Rust 程序设计 / 网络服务_其他)
- awesome-os - octox - Unix-like OS in Rust inspired by xv6-riscv (Open Source Operating Systems)
README
#+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::()] = [
(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 {
#[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 learning project for me, and I will not be accepting pull requests
until I consider the implementation complete. However, discussions and advice
are welcome.