mkfreeOS
mkfreeOS
The kernel is developed in c ++. It is designed to run on Intel x86 architecture.
Features it supports:
Multitask.
Multiple threads.
FAT32 and BFS file systems (proper for mkfree).
Virtual memory manager.
Controllers
Hierarchical protection domains. Kernel runs on ring 0 and usury applications on ring 3.
Multitask:
Each task runs every 1ms intervals. For now all tasks have the same priority. There is a main thread of execution and it can have these states: 1- suspended, 2- waiting and 3- executing.
Multiple threads:
Each task can have multiple execution threads and can have several states: 1- suspended, 2- waiting and 3- executing.
See bibliography in: https://github.com/ramonmayedo/mkfreeOS/wiki
See source code in: https://github.com/ramonmayedo/mkfreeOS
Features it supports:
Multitask.
Multiple threads.
FAT32 and BFS file systems (proper for mkfree).
Virtual memory manager.
Controllers
Hierarchical protection domains. Kernel runs on ring 0 and usury applications on ring 3.
Multitask:
Each task runs every 1ms intervals. For now all tasks have the same priority. There is a main thread of execution and it can have these states: 1- suspended, 2- waiting and 3- executing.
Multiple threads:
Each task can have multiple execution threads and can have several states: 1- suspended, 2- waiting and 3- executing.
See bibliography in: https://github.com/ramonmayedo/mkfreeOS/wiki
See source code in: https://github.com/ramonmayedo/mkfreeOS
Re: mkfreeOS
I would like to know suggestions and criticisms:
The objective of creating this kernel is educational, the idea is as follows:
-Achieve an internal structure in the kernel capable of being maintained throughout the source code to facilitate understanding.
-Make a monolithic kernel that is not the synonym of disorganized.
How is the code organization:
-Class declaration begins with C and words are capitalized, example class CadminProcess
-Declaration of structures begins with S and words are capitalized, example struct SmemoryPagination
-Also the declarations of variables also begin with lowercase and the words are separated using uppercase, example u32 * directoryPageKernel
How are its structures:
They are divided into 3 and are in the x86.h file, they are static structures and they are inside the kernel storage space.
-Smaps: contains information to be used globally as SgdtDescriptor, SkeyMap, ....
-Score: contains all the classes defined to the kernel such as Cstring, Cmemory, CcacheDisk, ...
-Sx86: contains classes of this architecture that will be used throughout the code such as Cpit8253, Cpic8259, CvirtualMemory, ...
If you want to use it in a class you only need to use an external definition like extern Sx86 x86, it is called x86.virtualMemory.createPageToDirectory (...)
How are your I / O to the kernel
-The classic syscall system call is the only form of communication between user programs and the kernel.
The kernel and its different layers
Storage Units:
-There is a Cdevices class that locates the storage media, adds them to a table and gives them a unique identification (id), in this class is where
it reads and writes on the devices, receives the device id, the sector to write and the data, and determines which driver to send, which can be a Hard Disk,
a CD or another to be added, these classes are Cdiskide, Ccdide for now.
-There is a CcacheDisk class that communicates the other classes with the storage devices and a cache memory.
-The CdiskPartition class checks the detected devices and looks for partitions, it only supports MBR for now, and in case of a CDROM it detects it as
a partition, it contains a function getFileSystem (...) that determines what file system is in the partition only FAT32, BFS and ISO9660 are supported.
Then it tells the CfileSystem class to mount the drive.
-The CfileSystem class mounts the file system and stores in a table the id of the storage unit, the letter, a pointer to the
structure that manipulates this file system. It is through them that file systems are read and written. For example, open a file
in the path "to / kernel / program / init.elf" he detects that the letter is 'a' and searches the table for the associated structure, then passes the path to the file system
for example Fat32 and it processes it.
-Cfat, Cbfs and Ciso9660 classes which are the supported file systems.
Soon I will put more things to comment
Greetings to all
The objective of creating this kernel is educational, the idea is as follows:
-Achieve an internal structure in the kernel capable of being maintained throughout the source code to facilitate understanding.
-Make a monolithic kernel that is not the synonym of disorganized.
How is the code organization:
-Class declaration begins with C and words are capitalized, example class CadminProcess
-Declaration of structures begins with S and words are capitalized, example struct SmemoryPagination
-Also the declarations of variables also begin with lowercase and the words are separated using uppercase, example u32 * directoryPageKernel
How are its structures:
They are divided into 3 and are in the x86.h file, they are static structures and they are inside the kernel storage space.
-Smaps: contains information to be used globally as SgdtDescriptor, SkeyMap, ....
-Score: contains all the classes defined to the kernel such as Cstring, Cmemory, CcacheDisk, ...
-Sx86: contains classes of this architecture that will be used throughout the code such as Cpit8253, Cpic8259, CvirtualMemory, ...
If you want to use it in a class you only need to use an external definition like extern Sx86 x86, it is called x86.virtualMemory.createPageToDirectory (...)
How are your I / O to the kernel
-The classic syscall system call is the only form of communication between user programs and the kernel.
The kernel and its different layers
Storage Units:
-There is a Cdevices class that locates the storage media, adds them to a table and gives them a unique identification (id), in this class is where
it reads and writes on the devices, receives the device id, the sector to write and the data, and determines which driver to send, which can be a Hard Disk,
a CD or another to be added, these classes are Cdiskide, Ccdide for now.
-There is a CcacheDisk class that communicates the other classes with the storage devices and a cache memory.
-The CdiskPartition class checks the detected devices and looks for partitions, it only supports MBR for now, and in case of a CDROM it detects it as
a partition, it contains a function getFileSystem (...) that determines what file system is in the partition only FAT32, BFS and ISO9660 are supported.
Then it tells the CfileSystem class to mount the drive.
-The CfileSystem class mounts the file system and stores in a table the id of the storage unit, the letter, a pointer to the
structure that manipulates this file system. It is through them that file systems are read and written. For example, open a file
in the path "to / kernel / program / init.elf" he detects that the letter is 'a' and searches the table for the associated structure, then passes the path to the file system
for example Fat32 and it processes it.
-Cfat, Cbfs and Ciso9660 classes which are the supported file systems.
Soon I will put more things to comment
Greetings to all
Re: mkfreeOS
Sounds great! The only thing I would suggest is that you capitalize the letter directly after the C or S. It makes it easier to read to read the name of the class or structure. I want to try it out. Do you have instructions on how to build and run it?
Re: mkfreeOS
I will prepare information on how to do it and write to you in details. Regards
Re: mkfreeOS
How to build the kernel ...:
-Used Applications
NetBeans IDE (Use 8.2): I use it for the great functionality it has, when you download the project in the repository you will find the folders, for example, nbproject
created by NetBeans itself.
NASM: To compile everything from assembler
GCC: To compile C ++
-The root directory is SRC inside contains several projects. All projects are compiled using makefile commands, the makefile file is the
the first one that appears and the only one that appears as a file the others are directories.
Directories:
bootloader: this folder contains the assembly of the Disk image, I don't use a loader like GRUB, if I didn't decide implement a simple one (visit https://github.com/ramonmayedo/mkfreeOS/wiki I explain more in details, it is for now the comments in Spanish).
Bootloader compilation: The bootloader generates an image.o file which is the one used in the virtual machine as a disk. To be able to compile the bootloader it is necessary to have the kernel compiled since the only thing it does in question is to assemble the image. It is in the image.asm file
Kernel compilation: A kernel.bin file that is previously used in the image assembly is compiled and generated in the end.
Library compilation: A library.lib file is generated that contains the implementation of all the functions that are in the library / includes header so that are used by our executable programs when they include it as a header.
GUImkfree compilation: gui.lib is generated that contains the implementation of all the functions of the graphic part. In addition to some window applications and the own graphic server. This is only minimal and is under development.
Soprogram folders: Contains all the programs that have been made so far, the most important being ini.elf, which is the one that gives visa to the entire system.
Isokernel compilation: Generate an ISO image of the kernel, it is under revision.
There is src / disk.img that contains a disk image in FAT32 which is where the kernel processes all processes.
When using the virtual machine quemu driver is configured, hard disk 0 the file ../src/bootloader/x86/image.o and on hard disk 1 the file ../src/disk.img
-Used Applications
NetBeans IDE (Use 8.2): I use it for the great functionality it has, when you download the project in the repository you will find the folders, for example, nbproject
created by NetBeans itself.
NASM: To compile everything from assembler
GCC: To compile C ++
-The root directory is SRC inside contains several projects. All projects are compiled using makefile commands, the makefile file is the
the first one that appears and the only one that appears as a file the others are directories.
Directories:
bootloader: this folder contains the assembly of the Disk image, I don't use a loader like GRUB, if I didn't decide implement a simple one (visit https://github.com/ramonmayedo/mkfreeOS/wiki I explain more in details, it is for now the comments in Spanish).
Bootloader compilation: The bootloader generates an image.o file which is the one used in the virtual machine as a disk. To be able to compile the bootloader it is necessary to have the kernel compiled since the only thing it does in question is to assemble the image. It is in the image.asm file
Kernel compilation: A kernel.bin file that is previously used in the image assembly is compiled and generated in the end.
Library compilation: A library.lib file is generated that contains the implementation of all the functions that are in the library / includes header so that are used by our executable programs when they include it as a header.
GUImkfree compilation: gui.lib is generated that contains the implementation of all the functions of the graphic part. In addition to some window applications and the own graphic server. This is only minimal and is under development.
Soprogram folders: Contains all the programs that have been made so far, the most important being ini.elf, which is the one that gives visa to the entire system.
Isokernel compilation: Generate an ISO image of the kernel, it is under revision.
There is src / disk.img that contains a disk image in FAT32 which is where the kernel processes all processes.
When using the virtual machine quemu driver is configured, hard disk 0 the file ../src/bootloader/x86/image.o and on hard disk 1 the file ../src/disk.img
Re: mkfreeOS
nexos, later I upload project to github to update it because it is a version that I have modified a little. Thanks for the help.
Re: mkfreeOS
Virtual memory (x86):
1- The kernel memory: (0x00000000-0x00800000)
* Kernel code (0x00100000 - 0x00200000):
The code size is 1MB in which the source code is stored. Expanding the size would be to restructure the linker.ld build file. The entrance to the kernel is exactly at the address 0x00100000. This entry code starts in the x86.cc file in the start () function.
* Static zone dedicated to the Global Kernel Variables (0x00200000 - 0x003FF000):
All the static kernel variables are stored in this area. The size is 1.9 MB. This are only 3 structures that contain all the varibles and static structures, they are Smaps, Sx86 and Score. If the kernel source code were expanded it would be necessary to reduce this size or completely restructure all memory.
In other words, the kernel can wrap between the code and the static variables up to 0x00100000 - 0x003FF000 (3.9 MB). If not, completely restructure all memory.
* Kernel Pages Directory (0x003FF000 - 0x00400000):
It is only 4KB and contains the kernel page directory.
* Kernel Page Frames (0x00400000 - 0x00800000):
This is the largest 4MB section, dedicated to the kernel and stores all page frames so that 4GB memory can be mapped, maximum in this architecture.
2- Kernel Page heap:
This memory section (0x00800000-0x08000000) contains all the pages that the kernel will use to assign them as a resource, these are listed below:
Directory of pages for processes.
Page frames for processes.
Process IPC buffer page.
Request for pages to disk cache.
Pages for DMA
Other uses of the kernel
3- Kernel heap:
This section of memory (0x08000000-0x40000000) is used by the kernel as heap memory.
4- User Page:
In this memory area (0x40000000-0xA0000000) it is dedicated to the executable code of our programs.
1- The kernel memory: (0x00000000-0x00800000)
* Kernel code (0x00100000 - 0x00200000):
The code size is 1MB in which the source code is stored. Expanding the size would be to restructure the linker.ld build file. The entrance to the kernel is exactly at the address 0x00100000. This entry code starts in the x86.cc file in the start () function.
* Static zone dedicated to the Global Kernel Variables (0x00200000 - 0x003FF000):
All the static kernel variables are stored in this area. The size is 1.9 MB. This are only 3 structures that contain all the varibles and static structures, they are Smaps, Sx86 and Score. If the kernel source code were expanded it would be necessary to reduce this size or completely restructure all memory.
In other words, the kernel can wrap between the code and the static variables up to 0x00100000 - 0x003FF000 (3.9 MB). If not, completely restructure all memory.
* Kernel Pages Directory (0x003FF000 - 0x00400000):
It is only 4KB and contains the kernel page directory.
* Kernel Page Frames (0x00400000 - 0x00800000):
This is the largest 4MB section, dedicated to the kernel and stores all page frames so that 4GB memory can be mapped, maximum in this architecture.
2- Kernel Page heap:
This memory section (0x00800000-0x08000000) contains all the pages that the kernel will use to assign them as a resource, these are listed below:
Directory of pages for processes.
Page frames for processes.
Process IPC buffer page.
Request for pages to disk cache.
Pages for DMA
Other uses of the kernel
3- Kernel heap:
This section of memory (0x08000000-0x40000000) is used by the kernel as heap memory.
4- User Page:
In this memory area (0x40000000-0xA0000000) it is dedicated to the executable code of our programs.
Re: mkfreeOS
The process manager:
1- The processes (Cprocess)
The processes contain as it is known a series of calls and structures, the most important in the mkfreeOS kernel, are the SprocessX86 processX86 that
store everything related to the state of the registers, virtual memory, ... and CadminThread * adminThread which is who manipulates which thread is going to be executed. Everyone
the processes are executed in ring 3. The processes and the execution threads have in common everything related to memory except the stack, which is independent
in each of the threads.
2- The process manager (CadminProcess)
It contains the list of processes, 'lock' for the blocked ones, 'ready' for the ready ones and a running process 'run'. From here everything is done
to process management. The process change is made by interrupting the timer.
1- The processes (Cprocess)
The processes contain as it is known a series of calls and structures, the most important in the mkfreeOS kernel, are the SprocessX86 processX86 that
store everything related to the state of the registers, virtual memory, ... and CadminThread * adminThread which is who manipulates which thread is going to be executed. Everyone
the processes are executed in ring 3. The processes and the execution threads have in common everything related to memory except the stack, which is independent
in each of the threads.
2- The process manager (CadminProcess)
It contains the list of processes, 'lock' for the blocked ones, 'ready' for the ready ones and a running process 'run'. From here everything is done
to process management. The process change is made by interrupting the timer.
Re: mkfreeOS
Blocking processes waiting for I / O:
Currently I do it only for the keyboard because I want to find the best variants:
1- The process requests the kernel to read a key, the syscall class
Send the cmkKeyEvent command to the Ckeyboard class:
2- The Ckeyboard class reviews the state of the keyboard
* If there is no key in the buffer, it stores the thread and the process that requests the key,
and it goes into a blocking state, then sends a signal to the process to suspend.
* The process itself tells the adminThread to suspend that thread and if there is no more
available threads then it changes its status to process blocked.
* Then the process requests process manager to make the process change
(that is, a blocking of a thread makes a process switch and not a thread), if the process has
More available threads put them on the ready list and if not add it to the blocked list.
3-When the keyboard receives a key in the buffer, it sends the process manager, what process
and thread got stuck waiting for a key, the process manager tells the process that
that unlocks the thread and if the process was blocked adds it to the ready list.
Problems I should solve:
p1-The keyboard must have a list of blocked devices waiting for a key,
if a process requests a key and the keyboard is already locked, then it is added
to the keyboard block list.
p2-When the keyboard sends the signal to the process manager to unlock the process
I request the key, the process manager adds it to the end of the ready queue
(if another process reads the keyboard it takes the information),
I can solve the problem just by adding the process to the beginning of the ready queue and
forcing the task switch to run. What to do with the process
interrupts ?, because this way you would go to the end of the queue of ready and not enjoy
its running time.
pX-
In summary I intend to do the same on I / O devices so I am looking for the best way
that suits the way the kernel is developed:
Please appreciate your advice
Currently I do it only for the keyboard because I want to find the best variants:
1- The process requests the kernel to read a key, the syscall class
Send the cmkKeyEvent command to the Ckeyboard class:
2- The Ckeyboard class reviews the state of the keyboard
* If there is no key in the buffer, it stores the thread and the process that requests the key,
and it goes into a blocking state, then sends a signal to the process to suspend.
* The process itself tells the adminThread to suspend that thread and if there is no more
available threads then it changes its status to process blocked.
* Then the process requests process manager to make the process change
(that is, a blocking of a thread makes a process switch and not a thread), if the process has
More available threads put them on the ready list and if not add it to the blocked list.
3-When the keyboard receives a key in the buffer, it sends the process manager, what process
and thread got stuck waiting for a key, the process manager tells the process that
that unlocks the thread and if the process was blocked adds it to the ready list.
Problems I should solve:
p1-The keyboard must have a list of blocked devices waiting for a key,
if a process requests a key and the keyboard is already locked, then it is added
to the keyboard block list.
p2-When the keyboard sends the signal to the process manager to unlock the process
I request the key, the process manager adds it to the end of the ready queue
(if another process reads the keyboard it takes the information),
I can solve the problem just by adding the process to the beginning of the ready queue and
forcing the task switch to run. What to do with the process
interrupts ?, because this way you would go to the end of the queue of ready and not enjoy
its running time.
pX-
In summary I intend to do the same on I / O devices so I am looking for the best way
that suits the way the kernel is developed:
Please appreciate your advice
Re: mkfreeOS
An initial solution
Q1- The Ckeyboard class contains a list of blocked processes (locksProcess), and a pointer to the
process that is unlocked to read (lockProcess).
Q2- At the end a new argument was added to the unlocking function, which is a priority, for now
There are only 2 priorities, HIGHT adds to the process if it is blocked at the top of the ready list,
and the thread in question the thread manager at the top of the threads ready list. That of
LOW priority is added by the end of the ready list. At the end the process in progress is not interrupted
if not wait until it ends.
From this 2 problems arise:
1- If the process that is running, when the key is pressed requests the
resource would consume it and the process in ready when it is her turn will be blocked. To resolve
this the keyboard is left locked and when the next reading is made the process and the thread are compared
stored in lockProcess with which it is running and if it is the same it is allowed to read, and if it is not
the one who is trying to consume the resource is blocked.
2- If the process that blocked the keyboard ended unexpectedly or thread was terminated by the
process, then the keyboard would be locked forever. This was resolved as follows
way: if the blocked process and thread are not the same as the one being executed, the
process manager if the thread exists, and if it doesn't it unlocks the next one in the list of
locked keyboard, the same is done for the thread, if at the end there are no longer processes in the list
blocked and the process had already been eliminated, the keyboard is unlocked and is ready to
the one that is running consumes the resource and if not it is blocked.
Q1- The Ckeyboard class contains a list of blocked processes (locksProcess), and a pointer to the
process that is unlocked to read (lockProcess).
Q2- At the end a new argument was added to the unlocking function, which is a priority, for now
There are only 2 priorities, HIGHT adds to the process if it is blocked at the top of the ready list,
and the thread in question the thread manager at the top of the threads ready list. That of
LOW priority is added by the end of the ready list. At the end the process in progress is not interrupted
if not wait until it ends.
From this 2 problems arise:
1- If the process that is running, when the key is pressed requests the
resource would consume it and the process in ready when it is her turn will be blocked. To resolve
this the keyboard is left locked and when the next reading is made the process and the thread are compared
stored in lockProcess with which it is running and if it is the same it is allowed to read, and if it is not
the one who is trying to consume the resource is blocked.
2- If the process that blocked the keyboard ended unexpectedly or thread was terminated by the
process, then the keyboard would be locked forever. This was resolved as follows
way: if the blocked process and thread are not the same as the one being executed, the
process manager if the thread exists, and if it doesn't it unlocks the next one in the list of
locked keyboard, the same is done for the thread, if at the end there are no longer processes in the list
blocked and the process had already been eliminated, the keyboard is unlocked and is ready to
the one that is running consumes the resource and if not it is blocked.
Re: mkfreeOS
The IPC buffer
Each process is assigned a 4KB page, it can be used for transfer
of information between processes. The cmpReadBufferIPC, cmpWriteBufferIPC commands are handled
by adminProcess.
For example on the graphics server:
case cmsCreateWindows:
{
Grect * windows = new Grect ();
if (parameter1 == 1) // The server is told to read the IPC buffer
readBufferIPC (pidClient, (char *) windows, 0, sizeof (Grect));
int error = createWindows (windows, pidClient);
.....
return 0;
}
On the client:
int Gclient :: activate () {
int command = 0, serverPid, status, parameter2;
sendCommand (cmsCreateConnection, pidServer, 0, 0); // Connection request with the server
getCommand (& command, & pidServer, & status, & parameter2);
if (status == 0) {// Connection accepted
Grect * rect = windows-> graphics; // A window is created
writeBufferIPC (pidClient, (char *) rect, 0, sizeof (Grect));
sendCommand (cmsCreateWindows, pidServer, 1, 1);
.....
}
return 0;
}
Each process is assigned a 4KB page, it can be used for transfer
of information between processes. The cmpReadBufferIPC, cmpWriteBufferIPC commands are handled
by adminProcess.
For example on the graphics server:
case cmsCreateWindows:
{
Grect * windows = new Grect ();
if (parameter1 == 1) // The server is told to read the IPC buffer
readBufferIPC (pidClient, (char *) windows, 0, sizeof (Grect));
int error = createWindows (windows, pidClient);
.....
return 0;
}
On the client:
int Gclient :: activate () {
int command = 0, serverPid, status, parameter2;
sendCommand (cmsCreateConnection, pidServer, 0, 0); // Connection request with the server
getCommand (& command, & pidServer, & status, & parameter2);
if (status == 0) {// Connection accepted
Grect * rect = windows-> graphics; // A window is created
writeBufferIPC (pidClient, (char *) rect, 0, sizeof (Grect));
sendCommand (cmsCreateWindows, pidServer, 1, 1);
.....
}
return 0;
}
Re: mkfreeOS
CvirtualMemory virtual memory, short description:
This class allows you to manage everything related to memory management.
1-Initialization:
--initBitapMemoryPages ();
* Initialization is accounted for in some way all
existing physical pages in (maps.memoryPagination.bitMapPages). Are marked
as occupied those consumed by the kernel which are 8MB (0x00000000-0x00800000)
--initDirectoryPages ();
* Kernel pages directory initialization, assigned at 1024
directory entries the location of the page frames. Paging is activated
Kernel Pages Dir: 0x003FF000-0x00400000, 1024 * 4 = 4K
Kernel Page Frames 0x00400000 - 0x00800000: 1024 * 4K = 4MB
--initMemoryPagesVirtual ();
* Initialization of a virtual memory area (CvirtualMemoryZone) to assign pages
the kernel heap. (0x00800000-0x08000000). 128MB
Kernel memory
2-Get physical pages (maps.memoryPagination.bitMapPages).
--getPageFrameToBitmap ()
3- Get and remove pages from the virtual memory of the kernel heap.
--getPagesVirtualKernel ()
--releasePageVirtualKernel ()
User memory
4-Create and delete page directory for processes
--createPageDirectory ()
--deleteDirectoryPages ()
5-Assign page within the page frame, if there is no page frame for that page it is also created.
--createPageToDirectory ()
This class allows you to manage everything related to memory management.
1-Initialization:
--initBitapMemoryPages ();
* Initialization is accounted for in some way all
existing physical pages in (maps.memoryPagination.bitMapPages). Are marked
as occupied those consumed by the kernel which are 8MB (0x00000000-0x00800000)
--initDirectoryPages ();
* Kernel pages directory initialization, assigned at 1024
directory entries the location of the page frames. Paging is activated
Kernel Pages Dir: 0x003FF000-0x00400000, 1024 * 4 = 4K
Kernel Page Frames 0x00400000 - 0x00800000: 1024 * 4K = 4MB
--initMemoryPagesVirtual ();
* Initialization of a virtual memory area (CvirtualMemoryZone) to assign pages
the kernel heap. (0x00800000-0x08000000). 128MB
Kernel memory
2-Get physical pages (maps.memoryPagination.bitMapPages).
--getPageFrameToBitmap ()
3- Get and remove pages from the virtual memory of the kernel heap.
--getPagesVirtualKernel ()
--releasePageVirtualKernel ()
User memory
4-Create and delete page directory for processes
--createPageDirectory ()
--deleteDirectoryPages ()
5-Assign page within the page frame, if there is no page frame for that page it is also created.
--createPageToDirectory ()