In this lecture we are going to write a console where we can issue a command and get the result from kernel.
The command we support in this example
is get total memory. Let’s get started.
The console is running in the user mode.
So what we are going to do is we are going to implement it in the user2 program
As you see, I have added the code in the main.c file.
We start off with main function.
The variable buffer is used to save the data we send with keyboard. The buffer size specifies how many characters we get in the console
before we issue a command.
Each time we press enter, the buffer size is reset to 0.
The cmd is the index of the commands we support.
Then we get to the infinite loop where we receive the data, issue a command and print the result on the screen
.
The layout of the screen is like this, at the beginning of each line, we have the command prompt shell and hash tag.
Then we can type the command we want to execute,
and press enter to issue the command.
Ok, let’s continue. Next we will read the data from the keyboard. When we return from it,
we will check the buffer size,
if the buffer size is 0, then there is no command found. We simply continue the loop.
Otherwise, we will parse the command.
If the return value is negative, then it means that the command is invalid, we print command not found
.
Otherwise, this is a command we support, we execute the command by function execute command.
Ok, let’s see what we have in the function read command.
As you see, we read a key from keyboard.
The else clause deals with normal keys. In this case, we copy the data to the buffer
and update the buffer size, then we print it on the screen.
If it’s an enter key which means we want to issue a command, then we print the enter key,
break the loop and return buffer size.
Here we also check the buffer size, in this example, we will allow the size of a command no more than 80 characters.
So if it’s more than 80, we will view it as a command and return.
Another case we need to handle is when we press backspace key to delete characters.
So here we check the buffer size. If the buffer size is 0, it means that we are at the beginning of the line
and we do nothing.
Otherwise, we decrement the buffer size and print backspace.
Alright, that’s it for read command function.
Now let's move to function parse command.
First off, we define variable command used as an index number. We initialize it with -1 which means this is an invalid index.
Since we only have one command available,
so we check if the size of command is equal to 8 and it’s the totalmem command.
If it’s totalmem, we return the index number 0 in this case.
As for other commands, we simply return -1.
the memcpy function is implemented in the lib.asm file . So we can use the function in that file.
OK, after we get the index number, we can execute the command by the function execute command.
In the header file,
we define the command type.
At this point, we have one command in the list, get total mem.
Therefore, if the index number is 0, we will call get total memory function. In order to retrieve the memory information,
we need to send the request to the kernel. In this function,
we call get memory total u and print the result. a
In the syscall.c file,
we add the sys get total memory function.
And in this function, the only thing we will do is call get total memory function. Remember the total memory is saved
in the memory module.
So we open memory.c file.
As you can see, the variable total memory is defined here.
Now we define it as a global variable.
Also, we add function get total memory where we simply return the total memory in mb format.
Add the declaration in the header file and the kernel part is done. Move to the user part.
We are going to add function in syscall file.
So we define get total memoryu.
The index of get total memory u is 5
and it doesn’t have parameters. We clear rdi register
then we int 80
After we return from kernel, the data is in rax.
and then we return.
Since we used the memcpy function in the main.c file,
we need to copy the lib.asm file into user2 program.
We also need to add the declaration of the functions
into the header file.
OK, now we declare the get total memoryu
and add the declaration here.
OK, let's build the project. We first build the library.
We run the build script.
We copy the binary file into boot folder
and build the kernel project.
OK, let's open the bochs
OK, let's test the command. We type totalmem
And you can see the total memory is 1023mb
This is the memory we allocated for the virtual machine.
As for other commands,
the console simply returns command not found.
And now you know the general process of adding a command to the system.
if you like, you can add more commands to the system yourself.
OK, that's it for this lecture.