Commit 856cfbf7 authored by Jeremy Soller's avatar Jeremy Soller
Browse files

Merge branch 'master' of https://github.com/redox-os/book

parents b95cf560 f0adf40a
......@@ -8,7 +8,7 @@
* The commit hash of the code you used
* `git rev-parse HEAD`
* The environment you are running Redox in (the "target")
* `qemu-i386 -version` or your actual hardware specs, if applicable
* `qemu-system-x86_64 -version` or your actual hardware specs, if applicable
* The operating system you used to build Redox
* `uname -a` or an alternative format
4. Make sure that your bug doesn't already have an issue on Github. If you submit a duplicate, you should accept that you may be ridiculed for it, though you'll still be helped. Feel free to ask in the Redox [chat](./contributing/communication/chat.html) if you're uncertain as to whether your issue is new
......
......@@ -15,7 +15,7 @@ The steps given below are for the main Redox project - submodules and other proj
5. Alternatively, if you already have a fork and copy of the repo, you can simply check to make sure you're up-to-date
* Fetch the upstream:`git fetch upstream master`
* Rebase with local commits:`git rebase upstream/master`
* Update the submodules:`git submodule update --init`
* Update the submodules:`git submodule update --recursive --init`
6. Optionally create a separate branch (recommended if you're making multiple changes simultaneously) (`git checkout -b my-branch`)
7. Make changes
8. Commit (`git add . --all; git commit -m "my commit"`)
......
Microkernels
============
Redox's kernel is a microkernel. Microkernels stands out in their design by providing minimal abstractions in kernel-space. Microkernels have an emphasis on user space, unlike Monolithic kernels which have an emphasis on kernel space.
Redox's kernel is a microkernel. Microkernels stand out in their design by providing minimal abstractions in kernel-space. Microkernels have an emphasis on user space, unlike Monolithic kernels which have an emphasis on kernel space.
The basic philosophy of microkernels is that any component which *can* run in user space *should* run in user space. Kernel-space should only be utilized for the most essential components (e.g., system calls, process separation, resource management, IPC, thread management, etc).
......@@ -25,7 +25,7 @@ The above illustration ([from Wikimedia], by Wooptoo, License: Public domain) sh
A note on the current state
---------------------------
Redox has ~16,000 lines of kernel code. For comparison the Minix has ~6,000 lines of kernel code.
Redox has less then 9,000 lines of kernel code. For comparison Minix has ~6,000 lines of kernel code.
We would like to move parts of Redox to user space to get an even smaller kernel.
......
......@@ -13,12 +13,15 @@ The code
So first of all we need to import the things, we need:
```rust
use system::scheme::Scheme;
use system::error::{Error, Result, ENOENT, EBADF, EINVAL};
extern crate syscall; // add "redox_syscall: "*" to your cargo dependencies
use syscall::scheme::SchemeMut;
use syscall::error::{Error, Result, ENOENT, EBADF, EINVAL};
use std::cmp::min;
```
We start by defining our scheme struct, which will implement the `Scheme` trait and hold the state of the scheme.
We start by defining our mutable scheme struct, which will implement the `SchemeMut` trait and hold the state of the scheme.
```rust
struct VecScheme {
......@@ -36,20 +39,20 @@ impl VecScheme {
First of all we implement, `open()`. Let it accept a reference, which will be the initial content of the vector.
Note that we do ignore `flags` and `mode`.
Note that we do ignore `flags`, `uid` and `gid`.
```rust
impl Scheme for VecScheme {
fn open(&mut self, path: &str, _flags: usize, _mode: usize) -> Result<usize> {
self.vec = path.as_bytes().to_owned();
Result::Ok(path.len())
impl SchemeMut for VecScheme {
fn open(&mut self, path: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result<usize> {
self.vec.extend_from_slice(path);
Ok(path.len())
}
```
So, now we implement read
So, now we implement read:
```rust
fn read(&mut self, _: usize, buf: &mut [u8]) -> Result<usize> {
fn read(&mut self, _id: usize, buf: &mut [u8]) -> Result<usize> {
let res = min(buf.len(), self.vec.len());
for b in buf {
......@@ -67,7 +70,7 @@ So, now we implement read
Now, we will add `write`, which will simply push to the vector:
```rust
fn write(&mut self, _: usize, buf: &[u8]) -> Result<usize> {
fn write(&mut self, _id: usize, buf: &[u8]) -> Result<usize> {
for &i in buf {
self.vec.push(i);
}
......@@ -77,30 +80,50 @@ Now, we will add `write`, which will simply push to the vector:
}
```
Note that leaving out the missing methods results in errors, when calling them.
In both our read and write implementation we ignored the `id` parameter for simplicity sake.
Note that leaving out the missing methods results in errors, when calling them, because of its default implementation.
Last, we need the `main` function:
```rust
fn main() {
use system::scheme::Packet;
let mut scheme = VecScheme::new();
// Create the handler
let mut socket = File::create(":vec").unwrap();
loop {
let mut packet = Packet::default();
while socket.read(&mut packet).unwrap() == size_of::<Packet>() {
scheme.handle(&mut packet);
socket.write(&packet).unwrap();
}
}
use syscall::data::Packet;
use std::fs::File;
use std::io::{Read, Write};
use std::mem::size_of;
let mut scheme = VecScheme::new();
// Create the handler
let mut socket = File::create(":vec").unwrap();
loop {
let mut packet = Packet::default();
while socket.read(&mut packet).unwrap() == size_of::<Packet>() {
scheme.handle(&mut packet);
socket.write(&packet).unwrap();
}
}
}
```
Now, go ahead and test it!
How to compile and run this example
-----------------------------------
For the time being there is no easy way to compile and deploy binaries for/on the redox platform.
There is however a way and it goes as follows:
1. Add your folder (as a soft link) into your local Redox repository (e.g. schemes/);
2. Add your binary to the root Makefile (e.g. under the schemes target);
3. Compile Redox via `make`;
Note: Do **not** add your folder to the git history, this 3-step process is only meant for local testing purposes. Also make sure to name your folder and binary as specified in your binary's `cargo.toml`;
Now, go ahead and test it by running `make qemu` (or a variant)!
Exercise for the reader
Exercises for the reader
------------------------
Write a scheme that can run `Brainfuck` code.
+ Compile and run the `VecScheme` example on the Redox platform;
+ There is also a Scheme trait, which is immutable. Come up with some use cases for this one;
+ Write a scheme that can run `Brainfuck` code;
......@@ -26,6 +26,12 @@ If it does not work, try:
$ make qemu kvm=no # we disable KVM
```
or:
```sh
$ make qemu iommu=no
```
If this doesn't work either, you should go open an issue.
Note
......
Exploring Redox
===============
To launch Redox's graphical interface launch `orbital` from the commandline.
Use F2 or F3 keys to get to a login shell. User `user` can login without password. For `root`, the password is `password` for now. `help` lists builtin commands for your shell (ion). `ls /bin` will show a list of applications you can execute.
```sh
$ orbital
```
Use F4 key to switch to a graphical user interface (orbital). Log in with the same username/password combinations as above.
This should put you into the orbital GUI if you got into a terminal by running
`make qemu` or `make virtualbox`.
Use the F1 key to get back to kernel output.
Sodium
------
......
......@@ -13,13 +13,14 @@ Oh, you're not lazy? Well, then the next section is for you!
Cloning the repository
----------------------
```sh
$ git clone https://github.com/redox-os/redox.git && cd redox && git submodule update init
$ git clone https://github.com/redox-os/redox.git --origin upstream --recursive && \
cd redox && git submodule update --recursive --init
```
Give it a while. Redox is big.
Installing the build dependencies manually
------------------------------------------
......@@ -27,8 +28,24 @@ Installing the build dependencies manually
I assume you have a package manager, which you know how to use (if not, you have to install the build dependencies manually). We need the following deps: `make` (probably already installed), `nasm` (the assembler, we use in the build process), `qemu` (the hardware emulator, we will use. If you want to run Redox on real hardware, you should read the `fun` chapter):)
Linux Users:
```
$ [your package manager] install make nasm qemu pkg-config libfuse-dev
```
MacOS Users using MacPorts:
```
$ sudo port install make nasm qemu gcc49 pkg-config osxfuse x86_64-elf-gcc
```
MacOS Users using Homebrew:
```
$ [your package manager] install make nasm qemu libfuse-dev pkg-config
$ brew install make nasm qemu gcc49 pkg-config Caskroom/cask/osxfuse
$ brew tap glendc/gcc_cross_compilers
$ brew install glendc/gcc_cross_compilers/x64-elf-binutils glendc/gcc_cross_compilers/x64-elf-gcc
```
While the following step is not _required_, it is recommended. If you already have a functioning Rust nightly installation, you can skip this step:
......
# Syntax
> [TODO: How to describe it, formally or using examples?]
```
if a == a
echo true a == a
if b != b
echo true b != b
else
echo false b != b
if 3 > 2
echo "true 3 > 2"
else
echo "false 3 > 2"
end
end
# Simple hello world example:
echo Hello world! # End of line comments are ignored
# `echo` is a command that allows you to print something in the stdout.
# Each command starts on a new line, or after semicolon:
echo 'This is the first line'; echo 'This is the second line'
# Declaring a variable looks like this:
let identifier = "Some string"
# Note that spaces between the identifier and value are optional:
let identifier = "Some string"
# Using the variable:
echo $identifier # stdout: `Some string`
echo b$identifier # stdout: `bSome string`
echo $identifiere # an empty string will be printed
# as no value can be found for $identifiere
# note that this does not count as an error ($?=0)
echo "$identifier" # stdout: `Some string`
echo '$identifier' # stdout: `Some string`
# When you use the variable itself
# If you want to use the variable's value, you should use $.
# Note that ' (single quote) won't expand the variables!
echo identifier # stdout: `identifier`
# the dollar sign `$` can be escaped with a backslash `\` to echo $identifier:
echo \$identifier #stdout: ``\$identifier`
# You can also remove a variable:
drop $foo # no value will be available anymore for the identifier `$foo`
# All variables can be listed as follows:
let
# Parameter expansion ${ }:
echo ${Variable}
# This is useful when you for example
# you want to have a character right after your variable:
let Name=John; echo Hello, ${Name}!
# Bracket expansion:
echo h{i,aa,ooo} # stdout: `hi, haa, hooo`
echo n{i,u,o}l # stdout: `nil nul nol`
# Note that spaces in between the commas (`,`) and brackets (`{`, `}`)
# aren't allowed and will make the expansion not work:
echo n{i, u}l # stdout: `n{i, u}l`
# Builtin variables:
# There are some useful builtin variables, like
echo "Last program's return value: $?"
echo "The Shell Prompt: $PROMPT"
echo "Username controlling the current shell environment: $USER"
echo "The current working directory: $PWD" # also available as command pwd
echo "The previous working directory: $OLDPWD"
echo "The the maximum size of the internal history buffer: $HISTORY_SIZE"
echo "The maximum amount of commands to retain in the log: $HISTORY_FILE_SIZE"
echo "Path of the log file: $HISTORY_FILE"
# Now that we know how to echo and use variables,
# let's learn some of the other basics of bash!
# Our current directory is available through the command `pwd`.
# `pwd` stands for "print working directory".
# We can also use the builtin variable `$PWD`.
# Observe that the following are equivalent:
echo "I'm in $PWD" # interpolates the variable
echo "I'm in ${PWD}" # execs `pwd` and interpolates output
# If you get too much output in your terminal, or from a script, the command
# `clear` clears your screen
clear
# Ctrl-L also works for clearing output
# Reading a value from input:
echo "What's your name?"
read Name # Note that we didn't need to declare a new variable
echo Hello, ${Name}!
# We have the usual if structure:
# use 'man test' for more info about conditionals
if $Name != $USER
echo "Your name isn't your username"
else
echo false a == a
echo "Your name is your username"
end
# NOTE: if $Name is empty, ion sees the above condition as:
if "" != $USER # ...
# which works as expected
# Unlike other programming languages, bash is a shell so it works in the context
# of a current directory. You can list files and directories in the current
# directory with the ls command:
ls
# These commands have options that control their execution:
ls -l # Lists every file and directory on a separate line
# Results of the previous command can be passed to the next command as input.
# grep command filters the input with provided patterns. That's how we can list
# rust source files in the src directory:
ls -l src | grep "\.rs"
# Use `cat` to print files to stdout:
cat src/main.rs
# Use `cp` to copy files or directories from one place to another.
# `cp` creates NEW versions of the sources,
# so editing the copy won't affect the original (and vice versa).
# Note that it will overwrite the destination if it already exists.
cp srcFile.txt clone.txt
cp -r srcDirectory/ dst/ # recursively copy
# Use `mv` to move files or directories from one place to another.
# `mv` is similar to `cp`, but it deletes the source.
# `mv` is also useful for renaming files!
mv s0urc3.txt dst.txt # sorry, l33t hackers...
# Since bash works in the context of a current directory, you might want to
# run your command in some other directory. We have cd for changing location:
cd ~ # change to home directory, also available as `$HOME`
cd .. # go up one directory
# (^^say, from /home/username/Downloads to /home/username)
cd /home/username/Documents # change to specified directory
cd ~/Documents/.. # still in home directory..isn't it??
# Use `mkdir` to create new directories.
mkdir myNewDir
# You can redirect output of one command to another command
echo "Hello" > hello.txt # will overwrite file if already exists
echo "Another line" >> hello.txt # will append to an existing file,
# this command will fail if the file does not exist yet
# You can use a file as input for a command
cat < hello.txt
# Last redirection example:
cat < foo > bar
# will write the contents of a file named "foo" to a file named "bar"
# for loops iterate for as many arguments given:
for i in 1 2 3 4 5
echo $i
end
# You can also define functions
# a function with no parameters
fn ask_name_and_say_hello
read name
echo "Hello, ${name}!"
end
# a function with parameters
fn test a b c
echo $a
echo $b
echo $c
end
# Calling your functions
ask_name_and_say_hello
test hello world goodbye
# not passing the correct amount of parameters will result in an error ($?=127)
# Read Ion shell builtins documentation with the ion 'help' builtin command:
help # displays available builtin commands
help cd # displays help information available for builtin cd command
```
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment