OSDev.org

The Place to Start for Operating System Developers
It is currently Fri Mar 29, 2024 5:22 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 5 posts ] 
Author Message
 Post subject: Trying to move to usermode
PostPosted: Mon Feb 25, 2019 1:15 pm 
Offline

Joined: Mon Feb 25, 2019 12:47 pm
Posts: 5
Hey, I started to develop my own os, my finale result I want is a shell screen that the user can write commands like "ls", "echo" and so on..
I just success to develop the kernel and I moved to the user mode.
I have some questions about it, hope you can help me.
1) When im in user mode, i can't get keyboard interrupt or any other interrupt is it suppose to be?

2) If yes, how do I build the shell, if the user can't write with keyboard or the os cant print to screen?
I think that I will have a shell code that call a systemcall for printing to the screen and when you in the syscall you will be in kernel mode, and the user can write till he will press enter and then the user will be back to user mode and the command he was write will call to the next syscall.
just to be clear:
usermode
syscall - read from keyboard
kernelmode
ls (command example)
usermode
and then calling the ls handler.
this is how I should do it?

if no please can you tell me how I should do the user mode to work right?

thanks for your help! :D


Top
 Profile  
 
 Post subject: Re: Trying to move to usermode
PostPosted: Wed Feb 27, 2019 3:50 am 
Offline
Member
Member

Joined: Fri Jun 28, 2013 1:48 am
Posts: 63
First you need to handle interrupts properly under kernel mode.

Then make interrupts also work under user mode. Same applies to system call.

So when user types on the keyboard, the interrupt will cause CPU switch into kernel mode, so your kernel code can read the scan code.

When your user-mode application want to print something on the screen, do a system call and switch into kernel mode, then your syscall handler will do the actual job on behalf of user-mode programs.

_________________
Reinventing the Wheel, code: https://github.com/songziming/wheel


Top
 Profile  
 
 Post subject: Re: Trying to move to usermode
PostPosted: Wed Feb 27, 2019 9:09 am 
Offline
Member
Member
User avatar

Joined: Thu Oct 13, 2016 4:55 pm
Posts: 1584
Hi,

lidorelias3 wrote:
1) When im in user mode, i can't get keyboard interrupt or any other interrupt is it suppose to be?

2) If yes, how do I build the shell, if the user can't write with keyboard or the os cant print to screen?

As songziming wrote, you should get your interrupt code right first. Interrupt Service Routines (or interrupt handlers) must be implemented in the kernel, can't be otherwise.

The interrupt handler and the syscall should be very similar, the only difference is, the interrupt is raised by the interrupt controller, and the syscall is issued by the user code. The reason why early Linux kernels used int 0x80 for syscalls is because of this obvious similarity. These days you can still find that for compatibility reasons, but mostly sysenter or syscall instructions used to pass calls to the kernel.

In both cases, you must receive inputs and generate outputs. For the keyboard, the input is read from the keyboard controller, which is a scancode, and has to be converted to an ASCII character. With print, the input is a memory address of a string. As for the output, the character code should be passed to userland, and in case of print the return value can be omitted (but you could return the number of printed characters for example).

How to connect the user land to receive the return value is the big question here. Some simple kernels do a getc() system call, which waits until a key arrives, and therefore the kernel knows which task executed the getc() and to which to return the character. More sophisticated kernels would keep track of the focused application, and would return the character to the focused one.

But on UNIXes, the proper way to do this is to implement pipes. The user code uses getc() to read from the pipe, which is empty, therefore the task blocks. More tasks can do this at the same time, because they all have their own pipes, and nobody cares if there are more blocked tasks waiting for pipe input. Now when the interrupt handler gets called in the kernel, it would select the focused application's pipe and put the character there, and would unblock that particular task. That task would then read the character from it's pipe. How the focused pipe is selected usually includes another abstraction level, called ttys or pseudo-ttys like in Linux for example.

In a micro-kernel, there are even more layers to be dealt with: the kernel interrupt handler should identify the keyboard task, and pass control to it. Then the user mode keyboard task would read the scancode, convert it to a character and then send it to the tty service. The tty service would then find the pipe's file descriptor assossiated with the focused tty, and would pass the character to the file system service. The file system service would place the character in the pipe, and would call a system service to unblock the user task wanting to read from its stdin. After that point there are no differences between micro- and monolitic kernels, the unblocked user task would read the character from it's stdin pipe.

In UNIX all characters written to the stdout pipe would be read by the tty (either service or kernel subsystem), and would be displayed. Another twist, if a user task is not blocked waiting for input when a key is pressed on the keyboard, then the character would be written to the application's stdout pipe instead of the stdin pipe. From there it would go the tty which would display it. This is called default echo, and you can turn this behaviour off by setting a flag in the tty descriptor struct associated. You can test this by creating a simple "int main() { while(1); return 0; }" application and run it on Linux. Because the application does not read the character from the stdin pipe, all keys you type will be sent to its stdout instead of stdin, and therefore will be read by the tty handler and displayed automatically.

This means if your application reads from the stdin, then it's the application's responsibility to print out the character received to the stdout pipe, otherwise it won't get displayed.

See https://wiki.osdev.org/Unix_Pipes. Maybe a figure would be propriate to help understanding (monolithic kernel design):
Code:
          kernel          | user land
------+-------+-----------+-------------
  ISR |  tty  |    fs     | shell
------+-------+-----------+-------------
IRQ1 -> tty1 -> stdin ->  | getc()
                          |   |
                          |   V
        tty1 <- stdout <- | putc()
        |                 |
        V                 |
  framebuffer renderer    |

Cheers,
bzt


Top
 Profile  
 
 Post subject: Re: Trying to move to usermode
PostPosted: Sat Mar 09, 2019 12:13 pm 
Offline

Joined: Mon Feb 25, 2019 12:47 pm
Posts: 5
songziming wrote:
First you need to handle interrupts properly under kernel mode.

Then make interrupts also work under user mode. Same applies to system call.

So when user types on the keyboard, the interrupt will cause CPU switch into kernel mode, so your kernel code can read the scan code.

When your user-mode application want to print something on the screen, do a system call and switch into kernel mode, then your syscall handler will do the actual job on behalf of user-mode programs.



Hey, can you tell me how I need to handle my interrupts to make them work in user mode?


Top
 Profile  
 
 Post subject: Re: Trying to move to usermode
PostPosted: Sun Mar 10, 2019 6:33 am 
Offline
Member
Member

Joined: Wed Aug 30, 2017 8:24 am
Posts: 1593
Well that's a vague question.

First, the keyboard actually needs to generate an interrupt. If you truly are still working with a PS2 controller, I suggest you read up on that in the wiki. Check that both keyboard processing is enabled and interrupts are not masked there.

Then the interrupt needs to be sent to the CPU. The PIC or APIC is responsible for this. You need to ensure whatever PIC you're using is set up correctly and is sending the keyboard IRQ through to the CPU as an INT.

Then the interrupt needs to be recognized. You need to ensure the interrupt flag is set. You propably go into user space with the IRET instruction. That instruction will pop flags (the third word from the stack). If the IF is not set there, your userspace program will run without interrupts enabled, and thus it won't recognize keypresses.

Then you actually need to handle the interrupt. Whatever INT is generated when the keyboard IRQ fires needs to have an interrupt gate set up in the IDT.

Check back once you know which part of this process you are hanging on.

_________________
Carpe diem!


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 5 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Amazonbot [bot], Bing [Bot], Google [Bot], Majestic-12 [Bot] and 106 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group