Obsidian is a simulated OS written in ruby that supports process and resource managemen. It's easy to write your own tasks and scheduling algorithms
In case of not having ruby installed in your system refer to ruby install.
Clone this repository:
git clone https://github.com/pablo-co/obsidian
And then execute:
Running the CLI
Obsidian comes bundled with a CLI. To run this CLI:
Assuming you are on the root of the project
A prompt should be shown.
obsidian >> |
Using the CLI
You can run many commands on the CLI with the following format:
command argument1 argument2 .... To see all valid commands and their usage run
obsidian >> help Usage: command argument1 argument2 ... Options: help Display this message load_task_from_file [file] Load a task from a given YAML file load_task_from_std_in Load a task from standard input load_module [file] Load a Ruby file into memory remove_task [pid] Remove a task from the ready queue get_task_stats [pid] List all information of a task set_scheduler [scheduler class] Sets the scheduling algorithm set_running_time [time] Set Q in for scheduling policies set_output_delay [delay] Set a delay for writing to the output device set_automatic_scheduling [true|false] Schedule jobs automatically step Run the scheduler and dispatcher once steps [times] Run the scheduler and dispatcher n times queues Prints the contents of all queues set_memory_strategy [strategy class] Sets the memory strategy algorithm process_memory_trace [input] [output] Processes a memory trace and outputs the result to a file Bug reports, suggestions, updates: https://github.com/pablo-co/obsidian/issues
Load a task
You can load tasks from a file and from standard input. In both cases the user defined attributes are:
- priority: The task scheduling priority, it's importance depends on the scheduling algorithm.
- task: The file with the code that will be executed.
Loading a task from a file
obsidian >> load_task_from_file example_file.yml
The file format is exclusively YAML. The keys in the file are the task attributes while it's values are well... it's values.
priority: 1 task: examples/sum.rb
Loading a task from standard input
Example user input:
obsidian >> load_task_from_std_in priority: 1 task: examples/sum.rb
Remove a task
You can remove a task by specifying it's pid. Note: For consistency purposes you can only remove tasks that are in the ready queue.
obsidian >> remove_task [pid]
Print task stats
You can print all the attributes for a given task to the console.
obsidian >> get_task_stats [pid]
Print the scheduling queues
You can print all the scheduling queues with their corresponding tasks.
obsidian >> queues
Change the scheduling algorithm
You can change and even write your own scheduling algorithm. To change the algorithm you need to specify the class of this algorithm.
The built-in classes are:
- Obsidian::RoundRobinScheduler (Default)
- Obsidian::SJFScheduler (Schedules according to estimated burst time)
- Obsidian::PrioritySJFScheduler (Schedules according to priority)
obsidian >> set_scheduler Obsidian::SJFScheduler
To write your own algorithm see Scheduler
Change burst time
You can change the maximum time for which a task can run (the default is 10). To remove the burst time limit write
infinity, this will effectively make all scheduling non-preemptive.
To set Q to 10 milliseconds.
obsidian >> set_running_time 10
Remove the maximum burst time. Make all schedulers non-preemptive.
obsidian >> set_running_time infinity
Change output delay
To write to the standard output all programs need to call
sys.out which will write to stdout. This system call takes the task out of the running state and into the waiting queue. The delay is the amount of simulated time it takes to write to this device (the default is 1000).
obsidian >> set_output_delay 1000
Change automatic scheduling
You can change whether Obsidian should automatically schedule and dispatch a task or have the user do it manually (by defaults it's true).
To enable it.
obsidian >> set_automatic_scheduling true
To disabled it.
obsidian >> set_automatic_scheduling false
Run the scheduler manually
You can also run the scheduler and dispatcher manually. But first you have to disable automatic scheduling.
First make sure you disable automatic scheduling.
obsidian >> set_automatic_scheduling false
Run the scheduler and dispatcher once
obsidian >> step
Run the scheduler and dispatcher
obsidian >> steps n
Change the memory management strategy
You can change the memory management strategy used when processing memory traces.
obsidian >> set_memory_strategy Obisidian::Memory::FirstFitStrategy
There are 3 built-in strategies:
Write your own memory management strategy
To write your own strategy all you have to do is write a class that is a
Obsidian::Memory::Strategy and that implements
next_space_available. See any of the built-in strategies for reference.
You first have to load your custom strategy to memory:
obsidian >> load_module your_custom_strategy.rb
And then you just set it as the current memory strategy:
obsidian >> set_memory_strategy YourCustomStrategy
Simulate a memory trace
You can simulate the memory management process with a memory trace file. This file has the following format:
size_of_memory number_of_available_spaces starting_address_1, available_space_1 starting_address_2, available_space_2 ... starting_address_N, available_space_N number_of_processes pid, arrival_time, duration, size_of_memory pid, arrival_time, duration, size_of_memory ... pid, arrival_time, duration, size_of_memory
examples/memory_trace.txt for an example memory trace.
To simulate the memory trace:
obsidian >> process_memory_trace examples/memory_trace.txt output.txt
This will parse the memory trace in the first file and output the result of doing memory management with the tasks and memory state given to the output file.
The output given by the example command:
Algorithm: FirstFitStrategy Assigned processes: 1, 200, 115; 2, 600, 500; 3, 1100, 358; 4, 1458, 200; 5, 1658, 375 Blocked processes: Memory utilization: 1548 / 4000 = 38.7% Blocking probability: 5 / 0 = 0.0%
Writing your own programs
You can run almost any type of ruby code in Obsidian. This code runs in a sandbox thus has some limitations regarding system calls in general. This means you can't make use of files, threads and any other type of operation that interfaces with the operating system.
The only system call currently supported by Obsidian is writing to stdout.
sys.out 'Hello world!'
The are several examples of programs in the examples folder.
Running the example files
You can load the example programs through the CLI to see them in action.
Currently the example programs are:
obsidian >> load_task_from_file examples/calculate_pi.yml obsidian >> [Output (0)]: PI ~= 4.0 [Output (0)]: PI ~= 2.666666666666667 [Output (0)]: PI ~= 3.466666666666667 [Output (0)]: PI ~= 2.8952380952380956 [Output (0)]: PI ~= 3.3396825396825403
obsidian >> set_scheduler Obsidian::RoundRobinScheduler obsidian >> set_running_time 20 obsidian >> queues Waiting: Ready: Running: obsidian >> load_task_from_file examples/sum.yml obsidian >> queues Waiting: Ready: (0 | 1 | 220.64876556396484 | 2016-03-30 21:30:37 -0600) Running: obsidian >> load_task_from_file examples/calculate_pi.yml obsidian >> [Output (1)]: Estimating the value of PI... [Output (1)]: PI ~= 4.0 obsidian >> queues Waiting: (1 | 2 | 6.8798065185546875 | 2016-03-30 21:30:42 -0600) Ready: Running: (0 | 1 | 1151.9584655761719 | 2016-03-30 21:30:37 -0600) obsidian >> [Output (1)]: PI ~= 2.666666666666667 [Output (1)]: PI ~= 3.466666666666667 [Output (1)]: PI ~= 2.8952380952380956 [Output (1)]: PI ~= 3.3396825396825403 obsidian >> remove_task 0 obsidian >> queues Waiting: (1 | 2 | 6.8798065185546875 | 2016-03-30 21:30:42 -0600) Ready: Running:
All documentation is available online at RubyDoc
After checking out the repo, run
bin/setup to install dependencies. Then, run
rake test to run the tests. You can also run
bin/console for an interactive prompt that will allow you to experiment.
Bug reports and pull requests are welcome on GitHub at https://github.com/pablo-co/obsidian. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.
The gem is available as open source under the terms of the MIT License.