Git Product home page Git Product logo

mentos's Introduction

MentOS (Mentoring Operating System)

forthebadge forthebadge forthebadge

Ubuntu

Table of Contents

What is MentOS

MentOS (Mentoring Operating System) is an open source educational operating system. The goal of MentOS is to provide a project environment that is realistic enough to show how a real Operating System work, yet simple enough that students can understand and modify it in significant ways.

There are so many operating systems, why did we write MentOS? It is true, there are a lot of education operating system, BUT how many of them follow the guideline de fined by Linux?

MentOS aims to have the same Linux's data structures and algorithms. It has a well-documented source code, and you can compile it on your laptop in a few seconds!

If you are a beginner in Operating-System developing, perhaps MentOS is the right operating system to start with.

Parts of MentOS are inherited or inspired by a similar educational operating system called DreamOs written by Ivan Gualandri.

Back to the Table of Contents

Implemented features

Follows the list of implemented features:

Processes and Events

  • Memory protection (User vs Kernel);
  • Processes;
  • Scheduler (synchronous and asynchronous);
  • Interrupts and Exceptions;
  • Signals;
  • Timers and RTC;
  • Wait-queues;
  • System Calls;
  • Multi-core;

Memory

  • Paging;
  • Buddy System;
  • Slab Allocation;
  • Zone Allocator;
  • Cache Allocator;
  • Heap;
  • Virtual Addressing;

Filesystem

  • Virtual Filesystem (VFS);
  • Initramfs;
  • EXT2;
  • Procfs;

Input/Output

  • Programmable Interrupt Controller (PIC) drivers;
  • Keyboard drivers (IT/ENG layouts);
  • Video drivers;
  • VGA drivers;

Inter-Process Communication (IPC)

  • Semaphore
  • Message queue
  • Shared memory
  • Named pipe

I will try to keep it updated...

Back to the Table of Contents

Prerequisites

MentOS is compatible with the main unix-based operating systems. It has been tested with Ubuntu, and under Windows with WSL1 and WSL2.

For compiling the system we need:

  • git
  • gcc
  • nasm
  • make
  • cmake
  • ccmake (suggested)
  • e2fsprogs (should be already installed)

Under MacOS, for compiling, you have additional dependencies:

  • i386-elf-binutils
  • i386-elf-gcc

For executing the operating system we need:

  • qemu-system-i386 (or qemu-system-x86)

For debugging we suggest using:

  • gdb or cgdb

Installing the prerequisites

Under Ubuntu, you can type the following commands:

sudo apt-get update && sudo apt-get upgrade -y
sudo apt-get install -y git build-essential nasm make cmake cmake-curses-gui e2fsprogs
sudo apt-get install -y qemu-system-x86
sudo apt-get install -y gdb cgdb

Note: Older versions might have qemu-system-i386 instead of qemu-system-x86.

Back to the Table of Contents

Compiling MentOS

Compile MentOS with:

cd <clone_directory>
mkdir build
cd build
cmake ..
make

Back to the Table of Contents

Generating the EXT2 filesystem

Generate the EXT2 filesystem with:

make filesystem

you just need to generate the filesystem once. If you change a program you need to re-generate the entire filesystem with make filesystem, but this will override any changes you made to the files inside the rootfs.img. In the future I will find a way to update just the /usr/bin directory and the programs.

Back to the Table of Contents

Running MentOS

Boot MentOS with qemu:

make qemu

To login, use one of the usernames listed in files/etc/passwd.

Back to the Table of Contents

Running MentOS from GRUB

For booting MentOS from GRUB in QEMU we need the following tools:

  • xorriso
  • grub-mkrescue (from grub-common)

We also need grub-pc-bin, otherwise GRUB won't start in QEMU.

Which can be installed in Ubuntu with the following command:

sudo apt-get update && sudo apt-get upgrade -y
sudo apt-get install -y grub-common grub-pc-bin xorriso

Boot MentOS with qemu through GRUB by calling:

make qemu-grub

Back to the Table of Contents

Running and adding new programs to MentOS

This section explains how to add a new program to MentOS, and also how to run programs in mentos. It also explains how to add new tests, which are located in the programs/tests folder.

Create a new program

Head to the programs (or the programs/tests) folder. Create and open a new program, for instance a file called hello_world.c, with your preferred editor, and add this content to the file:

#include <stdio.h>

int main(int argc, char *argv[])
{
    printf("Hello, World!\n\n");
    return 0;
}

Add the new program to the list of compiled sources

Now we can add the program to the list of files which are compiled and placed inside MentOS filesystem. The following procedure is the same for both programs and programs/tests, what changes is which CMakeLists.txt file we modify.

You need to modify the CMakeLists.txt file, either programs/CMakeLists.txt or programs/tests/CMakeLists.txt, and add your program to the list of files to be compiled:

# Add the executables (manually).
set(PROGRAMS
    init.c
    ...
    hello_world.c
)

or

# Add the executables (manually).
set(TESTS
    t_mem.c
    ...
    hello_world.c
)

That's it, the hello_world.c file will be compiled and will appear inside the /bin or /bin/tests folder of MentOS.

Running a program or a test

Once you login into MentOS, if you placed your source code in programs, you can execute the program by simply typing:

hello_world

because the file resides in /bin, and that folder is listed in the PATH environment variable.

Now, if you placed your source code inside the programs/tests folder, the executable will end up inside the /bin/tests folder. However, the /bin/tests folder is not listed in PATH, so, if you want to execute a test from that folder you need to specify the full path:

/bin/tests/hello_world

Back to the Table of Contents

Kernel logging

The kernel provides ways of printing logging messages from inside the kernel code to the bash where you executed the make qemu.

These logging functions are:

#define pr_emerg(...)
#define pr_alert(...)
#define pr_crit(...)
#define pr_err(...)
#define pr_warning(...)
#define pr_notice(...)
#define pr_info(...)
#define pr_debug(...)
#define pr_default(...)

You use them like you would use a printf:

    if (fd < 0) {
        pr_err("Failed to open file '%s', received file descriptor %d.\n", filename, fd);
        return 1;
    }

By default only message that goes from pr_notice included down to pr_emerg are displayed.

Each logging function (they are actually macros) is a wrapper that automatically sets the desired log level. Each log level is identified by a number, and declared as follows:

#define LOGLEVEL_DEFAULT (-1) ///< default-level messages.
#define LOGLEVEL_EMERG   0    ///< system is unusable.
#define LOGLEVEL_ALERT   1    ///< action must be taken immediately.
#define LOGLEVEL_CRIT    2    ///< critical conditions.
#define LOGLEVEL_ERR     3    ///< error conditions.
#define LOGLEVEL_WARNING 4    ///< warning conditions.
#define LOGLEVEL_NOTICE  5    ///< normal but significant condition.
#define LOGLEVEL_INFO    6    ///< informational.
#define LOGLEVEL_DEBUG   7    ///< debug-level messages.

You can change the logging level by including the following lines at the beginning of your source code:

// Include the kernel log levels.
#include "sys/kernel_levels.h"
/// Change the header.
#define __DEBUG_HEADER__ "[ATA   ]"
/// Set the log level.
#define __DEBUG_LEVEL__ LOGLEVEL_INFO
// Include the debuggin header.
#include "io/debug.h"

This example sets the __DEBUG_LEVEL__, so that all the messages from INFO and below are shown. While __DEBUG_HEADER__ is just a string that is automatically prepended to your message, helping you identifying from which code the message is coming from.

Back to the Table of Contents

Change the scheduling algorithm

MentOS supports scheduling algorithms for aperiodic:

  • Round-Robin (RR)
  • Highest Priority
  • Completely Fair Scheduling (CFS)
  • Aperiodic Earliest Deadline First (AEDF)

It also supports periodic algorithms:

  • Earliest Deadline First (EDF)
  • Rate Monotonic (RM)

If you want to change the scheduling algorithm, to Round-Robin (RR) for instance:

cd build
cmake -DSCHEDULER_TYPE=SCHEDULER_RR ..
make
make qemu

or you can activate one of the others:

# Highest Priority
cmake -DSCHEDULER_TYPE=SCHEDULER_PRIORITY ..
# Completely Fair Scheduling (CFS)
cmake -DSCHEDULER_TYPE=SCHEDULER_CFS      ..
# Earliest Deadline First (EDF)
cmake -DSCHEDULER_TYPE=SCHEDULER_EDF      ..
# Rate Monotonic (RM)
cmake -DSCHEDULER_TYPE=SCHEDULER_RM       ..
# Aperiodic Earliest Deadline First (AEDF)
cmake -DSCHEDULER_TYPE=SCHEDULER_AEDF     ..

Otherwise you can use ccmake:

cd build
cmake ..
ccmake ..

Now you should see something like this:

BUILD_DOCUMENTATION              ON
CMAKE_BUILD_TYPE
CMAKE_INSTALL_PREFIX             /usr/local
DEBUGGING_TYPE                   DEBUG_STDIO
ENABLE_BUDDY_SYSTEM              OFF
SCHEDULER_TYPE                   SCHEDULER_RR

Select SCHEDULER_TYPE, and type Enter to scroll the three available algorithms (SCHEDULER_RR, SCHEDULER_PRIORITY, SCHEDULER_CFS, SCHEDULER_EDF, SCHEDULER_RM, SCHEDULER_AEDF). Afterwards, you need to

<press c>
<press g>
make
make qemu

Back to the Table of Contents

Debugging the kernel

If you want to use GDB to debug MentOS, first you need to compile everything:

cd build
cmake ..
make

Then, you need to generate a file called .gdbinit placed inside the build directory, which will tell gdb which object file he needs to read in order to allow proper debugging. Basically, it provides for each binary file, the location of their .text section. To generate the file, just execute:

make gdbinit

Finally, you run qemu in debugging mode with:

make qemu-gdb

If you did everything correctly, you should see an empty QEMU window. Basically, QEMU is waiting for you to connect remotely with gdb. Anyway, running make qemu-gdb will make your current shell busy, you cannot call gdb in it. You need to open a new shell inside the build folder and do a:

gdb --quiet --command=gdb.run

or

cgdb --quiet --command=gdb.run

Now you should have in front of you:

  1. the QEMU window waiting for you;
  2. the first shell where you ran make qemu-gdb, which is also waiting for you;
  3. the second shell where gdb is runnign and, you guessed it, is waiting for you.

By default I placed a breakpoint at the begginning of (1) the bootloader and (2) the kernel itself.

So, when gdb starts you need to first give a continue:

(gdb) continue

This will make the kernel run, and stop at the first breakpoint which is inside the bootloader:

Breakpoint 1, boot_main (...) at .../mentos/src/boot.c:220
220     {

giving a second continue will get you to the start of the operating system:

This will make the kernel run, and stop at the second breakpoint which is inside the kernel:

Breakpoint 2, kmain (...) at .../mentos/src/kernel.c:95
95      {

There is also a launch configuration for vscode in .vscode/launch.json, called (gdb) Attach, which should allow you to connect to the running process.

Back to the Table of Contents

Contributors

Project Manager:

Developers:

  • Alessandro Danese, Luigi Capogrosso, Mirco De Marchi
    • Protection ring
    • libc
  • Andrea Cracco
    • Buddy System, Heap, Paging, Slab, Caching, Zone
    • Process Image, ELF
    • VFS: procfs
    • Bootloader
  • Linda Sacchetto, Marco Berti
    • Real time scheduler
  • Daniele Nicoletti, Filippo Ziche
    • Real time scheduler (Asynchronous EDF)
    • Soft IRQs
    • Timer
    • Signals
  • And many other valuable contributors

Back to the Table of Contents

mentos's People

Contributors

aldeit avatar emmekappaa avatar fischerling avatar galfurian avatar mircodemarchi avatar notbiji avatar rouseabout avatar seekbytes avatar tommyvilo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

mentos's Issues

Creating directories is not working properly

Since my attempts (f7e53f9 and 4d45044) to fix creation and appending to files, the creation of directories is not working anymore.

This can be easily verified using the new t_mkdir test introduced in #78 or by running the following commands in MentOS

$ mkdir outer
$ mkdir outer/inner
$ ls outer

Additionally, running fsck.ext2 -fn rootfs.img lists a bunch of errors.

I included the output of fsck.ext2 after running all the tests using the qemu-test target.

e2fsck 1.47.1 (20-May-2024)
Pass 1: Checking inodes, blocks, and sizes
Inode 680, i_size is 16384, should be 8192.  Fix? no

Inode 680, i_blocks is 16, should be 8.  Fix? no

Inode 681, i_size is 12288, should be 8192.  Fix? no

Inode 681, i_blocks is 16, should be 8.  Fix? no

Pass 2: Checking directory structure
Directory inode 680 has an unallocated block #0.  Allocate? no

Directory inode 681 has an unallocated block #0.  Allocate? no

Entry '..' in .../outer (681) is duplicate '..' entry.
Fix? no

Entry '..' in .../outer (681) is duplicate '..' entry.
Fix? no

Entry '..' in .../outer (681) is a link to directory /t_mkdir (680).
Clear? no

Pass 3: Checking directory connectivity
'..' in /t_mkdir (680) is <The NULL inode> (0), should be / (2).
Fix? no

'..' in .../outer (681) is <The NULL inode> (0), should be ... (680).
Fix? no

Pass 4: Checking reference counts
Inode 2 ref count is 11, should be 10.  Fix? no

Inode 680 ref count is 3, should be 2.  Fix? no

Inode 681 ref count is 2, should be 1.  Fix? no

Unattached inode 682
Connect to /lost+found? no

Pass 5: Checking group summary information
Block bitmap differences:  -(3960--3961) -3963 +3968
Fix? no

Inode bitmap differences:  +682
Fix? no


rootfs: ********** WARNING: Filesystem still has errors **********

rootfs: 681/8192 files (0.3% non-contiguous), 3968/8192 blocks

Mount points are not included in `getdents`

Mountpoints are not considered as directory entries.

The special character devices created and mounted in /dev during boot are not reported by getdents.

20240730_15h02m46s_grim

I expected /dev/hda/ mounted during ata_initialize and /dev/null mounted during mem_devs_initialize in kernel.c to show up in the directory listing of /dev.

Ext2 fail to read `t_alarm`, problem with inode blocks

The file has these statistics:

   Size :  86020 N. Blocks :  176
 Access : (33261/rwxr-xr-x ) Uid: (1000, None) Gid: (1000, None)
 Access : 2024-03-08 17:21:50 (1709918510)
 Modify : 2024-03-08 17:21:46 (1709918506)
 Change : 2024-03-08 17:21:46 (1709918506)
 Delete : 1970-01-01  0: 0: 0 (0)
  Links :  1 Flags : 0
 Blocks : [ 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 ]
IBlocks : 1357 [ 1358 1359 1360 1361 1362 1363 1364 1365 1366 ]
DBlocks : 0
TBlocks : 0

The file size is 86020 bytes, and it uses a total of 22 blocks. Where, 21 blocks are used to store data, while another block (1357) is used for indirect block addressing.

Now, 21 blocks with a block size of 4096 can accommodate only 86016 bytes. Where are those last 4 bytes stored?

Currently, it tries to read a 23rd block, which does not exist in the indirect block table. Thus, it fails to load the executable.

panic: Init not valid (%d)!

Ciao,
Installando il sistema come da readme, una volta lanciato make qemu, mentos si avvia ma da un errore quando tenta di lanciare il processo init.
Ho messo i livelli di debug dei possibili file sorgente interessati a loglevel debug, allego l'output
log.txt

Ho provato a riclonare, scaricare il progetto e anche la release 0.50 ma ottengo sempre lo stesso errore.

Sistema:

  • OS: Arch Linux x86_64
  • Kernel: 6.0.10-arch2-1
  • gcc: 12.2.0
  • qemu: 7.1.0

Fatemi sapere se devo scrivere la issue in inglese.
Grazie mille.

Function `__kmem_cache_alloc_slab` causes crash during boot.

The function __kmem_cache_alloc_slab is currently causing a crash during boot.

The problem seems to be related to managing the slab_freelist.

The full backtrace for the bug is:

#0  list_head_pop (head=0xc0530408)
    at libc/inc/sys/list_head.h:151
#1  0xc0027ec7 in __kmem_cache_alloc_slab (cachep=0xc12c0a20, slab_page=0xc05303e0)
    at mentos/src/mem/slab.c:134
#2  0xc0028331 in kmem_cache_alloc (cachep=0xc12c0a20, flags=3264)
    at mentos/src/mem/slab.c:261
#3  0xc000fcfe in ext2_alloc_cache (fs=0xc12d0800)
    at mentos/src/fs/ext2.c:674
#4  0xc0011890 in ext2_get_real_block_index (fs=0xc12d0800, inode=0xf791cdf8, block_index=1)
    at mentos/src/fs/ext2.c:1496
#5  0xc0011c16 in ext2_read_inode_block (fs=0xc12d0800, inode=0xf791cdf8, block_index=1, buffer=0xc13f6000 "...")
    at mentos/src/fs/ext2.c:1597
#6  0xc0011e23 in ext2_read_inode_data (fs=0xc12d0800, inode=0xf791cdf8, inode_index=25, offset=0, nbyte=114624, buffer=0xc1460000 "...")
    at mentos/src/fs/ext2.c:1662
#7  0xc001556a in ext2_read (file=0xc13ec540, buffer=0xc1460000 "...", offset=0, nbyte=114624)
    at mentos/src/fs/ext2.c:2870
#8  0xc000b139 in vfs_read (file=0xc13ec540, buf=0xc1460000, offset=0, nbytes=114624)
    at mentos/src/fs/vfs.c:188
#9  0xc0032fe0 in elf_load_file (task=0xc1408000, file=0xc13ec540, entry=0xc1408088)
    at mentos/src/elf/elf.c:308
#10 0xc002c5be in __load_executable (path=0xc0035a39 "/bin/init", task=0xc1408000, entry=0xc1408088)
    at mentos/src/process/process.c:206
#11 0xc002cc60 in process_create_init (path=0xc0035a39 "/bin/init")
    at mentos/src/process/process.c:373
#12 0xc0000faf in kmain (boot_informations=0x2e0000 <boot_info>)
    at mentos/src/kernel.c:423

Apparently, at some point, the slab_page->slab_freelist->next becomes NULL.
Consequently, when it tries to remove list_head_remove(head->next);, we have an error.

COMPILATION ERROR

ciao
installando il sistema ho creato una cartella build dopo di che ho lanciato '' cmake ..'' ed è andato a buon fine.E poi '' make '' dove mi da l'errore:

kizerbo@MBP-de-Koffi build % make
-- Could NOT find Doxygen (missing: DOXYGEN_EXECUTABLE)
-- Crosscompiling : FALSE
-- System name : Darwin
-- Kernel version : 23.1.0
-- Setting scheduler type to SCHEDULER_RR.
-- Setting vide type to VGA_TEXT_MODE.
-- Setting keyboard mapping to KEYMAP_US.
-- Setting emulator output type to OUTPUT_STDIO.
-- Configuring done (0.3s)
-- Generating done (0.2s)
-- Build files have been written to: /Users/kizerbo/documents/MentOS-master/build
[ 0%] Building C object libc/CMakeFiles/libc.dir/src/stdio.c.o
clang: error: unsupported argument 'i686' to option '-march='
make[2]: *** [libc/CMakeFiles/libc.dir/src/stdio.c.o] Error 1
make[1]: *** [libc/CMakeFiles/libc.dir/all] Error 2
make: *** [all] Error 2

grazie mille

`O_TRUNC` has no effect

The open(2) flag O_TRUNC is currently not implemented.

An existing file is not truncated and the blocks used by the file are not freed.

This results in files containing old content, if it is longer than the newly written content, after using O_TRUNC.

int fd = creat("foo", 660);
write(fd, "foobar", 6);
close(fd);

fd = open("foo", O_RDWR | O_TRUNC, 0); // File length should be set to 0.
write(fd, "baz", 3); // File should only contain "foo".
char buf[7] = {0};
read(fd, buf, 6); // This will read the six bytes "bazbar"

Directory entries are dropped when new ones are created

Directories are still buggy.

I introduced two seperate user alice and bob in commit 225bcda.
This is the first commit where I can reproduce the buggy behavior.
This behavior is independent of #82, because I could reproduce it after merging my modifications into the current master 4bc52fb.

What happens?

When I create a new file in alice' home directory using touch foo all other directory entries are lost.

However, if I delete the secrets.txt file from alice' home before creating a new file all expected entries are found.
But creating a second file results in the same behavior, of loosing all entries except the newly created one.

fsck.ext2 reports unatteched inodes after creating a file foo as described above.

$ fsck.ext2 -fn rootfs.img

e2fsck 1.47.1 (20-May-2024)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Unattached inode 105
Connect to /lost+found? no

Unattached inode 106
Connect to /lost+found? no

Unattached inode 107
Connect to /lost+found? no

Pass 5: Checking group summary information

rootfs: ********** WARNING: Filesystem still has errors **********

rootfs: 686/8192 files (0.0% non-contiguous), 3994/8192 blocks

I will attach a kernel and file system image if you want. Just let me know.

List of issues found in Develop

  • when accessing as root you get a kernel panic as it tries to open the root dir
  • ipcs and cpuid doesn't show any output
  • when using cgdb, a warni appears for a file to be added (add-auto-load-safe-path /home/user/MentOS/build/.gdbinit string in /home/user/.config/gdb/gdbinit)
  • modify and extend the documentation for the new update

Booting on Bare Metal

I recently figured out how to load the kernel and initramfs using GRUB. But, I ran into a few issues.
1.) When booting, GRUB complains about me not loading the kernel first, but I have the multiboot command before the initrd command.

2.) The username root and the password password do not work. It simply says, sorry, try again. This happens with user and computer as well.

Other than this, it works as I would expect. This is an amazing system! Thanks!

Panic on boot

I ran

cmake ..
make -j2
make qemu

I had to remove the -sdl option because of an error. However, on boot, I get:

Assertion `next && "No valid task selected. Have you implemented a scheduling algorithm?"` failed.

Fix ownership of file

The ownership of the files under / is not correct. Ideally, here is what we should see:

  • Everything inside \, should be owned by uid=0;
  • Everything inside the user folder should have the owner's uid.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.