📂
build a OS
  • Learn OS with me
  • OS Interfaces
    • OS interfaces
    • I/O and File descriptors
    • Process and Memory
    • Pipes
    • File
  • OS Organization
    • OS Organization
    • Challenge yourself
  • Memory Management
    • XV6 Virtual Memory
    • Page Table
      • Part 1: How to translate address
      • Part 2: Create an Address Space
      • Part 3: How Page Table is used
      • Part 4: Page Fault and Swap
      • Part 5: How to operate on page tables
    • xv6 buddy allocator
      • How to display physical memory
    • Memory Management Walk Through
  • Traps and Interrupts
    • Trap Home Page
      • 系统调用的核心原理
    • What is trapframe
    • What is trampoline
    • Traps from kernel space
    • How fork() works
    • How system calls get into/out of the kernel
    • How exec() works
  • Scheduling
    • XV6 CPU Scheduling
    • How unix pipes work?
    • How does wait(), exit(), kill() work?
  • File System
    • Overview and Disk Layout
    • Buffer Cache
    • Design Inode Layer
    • Inode Content
    • Block Allocator
    • Design a log system for crash recovery
    • Directory Layer
    • Path names
    • File Descriptor Layer
    • FS System Calls
    • XV6 VS Real World
    • Make Xv6 File disk management system
    • Write FS simulator in python
    • How Redirect Shell command works
  • Concurrency
    • Spinlock
    • How linux select work
    • Hardware Support Locking
    • Exercise: Implement atomic counter
    • Locking in Xv6
    • Concurrency in Xv6
    • Exercise: Socket Programming with Event loop
  • Labs
    • Lab 1 Xv6 and Unix utilities
    • Lab 2 Shell
    • Lab 3 Buddy Allocator
    • Lab 4 Lazy
    • Lab 5 Copy-on-Write Fork for xv6
    • Lab 6 RISC-V assembly
    • Lab 6 Uthread: switching between threads
    • Lab 6 Alarm
    • Lab 7 Lock
    • Lab 8 File System: Large Files
    • Lab 8 File System: Symbolic links
    • Lab 9 mmap
    • Lab 10 Networking Part 1
    • Lab 10 Networking Part 2
  • Hardware, Device, Assembly
    • RISC-V assembly
    • Assembly: Access and Store information in Memory
    • Start xv6 and the first process
    • Why first user process loads another program?
    • What does kernel.ld do in XV6?
    • XV6 Device Driver
Powered by GitBook
On this page
  • Why we have a Driver?
  • Initialization
  • Config Hardware
  • Create console device
  • How to read or write from device
  • Flow
  • Every input char generates an interrupt
  • Trap handler determines interrupt source
  • Accumulate inputs and Wake up
  • Question:

Was this helpful?

  1. Hardware, Device, Assembly

XV6 Device Driver

Why we have a Driver?

A driver is the code in an operating system that manages a particular device: 1. It tells the device hardware to perform operations,. 2. Configures the device to generate interrupts when done. 3. Handles the resulting interrupts,. 4. Interacts with processes that may be waiting for I/O from the device.

Initialization

Config Hardware

Xv6’s main calls consoleinit (kernel/console.c:189) to initialize the UART hardware, and to configure the UART hardware to generate input interrupts (kernel/uart.c:34).

void
consoleinit(void)
{
  initlock(&cons.lock, “cons”);

  uartinit();

  // connect read and write system calls
  // to consoleread and consolewrite.
  devsw[CONSOLE].read = consoleread;
  devsw[CONSOLE].write = consolewrite;
}

Create console device

In init.c, create a console device:

mknod(“console”, 1, 1);
open(“console”, O_RDWR);

The file path is console, type is T_DEVICE.

mknod implementation.

uint64
sys_mknod(void)
{
  struct inode *ip;
  char path[MAXPATH];
  int major, minor;

  begin_op(ROOTDEV);
  if((argstr(0, path, MAXPATH)) < 0 ||
     argint(1, &major) < 0 ||
     argint(2, &minor) < 0 ||
     (ip = create(path, T_DEVICE, major, minor)) == 0){
    end_op(ROOTDEV);
    return -1;
  }

At this point, we have a console device. A file descriptor 0 points to this device.

How to read or write from device

Let’s look at fileread

int
fileread(struct file *f, uint64 addr, int n)
{
  int r = 0;

  if(f->readable == 0)
    return -1;

  if(f->type == FD_PIPE){
    r = piperead(f->pipe, addr, n);
  } else if(f->type == FD_DEVICE){
    if(f->major < 0 || f->major >= NDEV || !devsw[f->major].read)
      return -1;
    r = devsw[f->major].read(f, 1, addr, n);

If the file type is DEVICE, we call the special read function to perform read operation. Note: The special read is set up in consoleinit.

consoleread sleeps and wait for a line of inputs, then copy to user space. Details see flow section.

Flow

Every input char generates an interrupt

When the user types a character, the UART hardware asks the RISC-V to raise an interrupt.

Trap handler determines interrupt source

xv6’s trap handling code calls devintr (kernel/trap.c:177). devintr looks at the RISC-V scause register to discover that the interrupt is from an external device. Then it asks a hardware unit called the PLIC [1] to tell it which device interrupted (kernel/trap.c:186). If it was the UART, devintrcalls uartintr.

Accumulate inputs and Wake up

Read one char and hand over

uartintr (kernel/uart.c:84) reads any waiting input characters from the UART hardware and hands them to consoleintr.

// trap.c calls here when the uart interrupts.
void
uartintr(void)
{
  while(1){
    int c = uartgetc();
    if(c == -1)
      break;
    consoleintr(c);
  }
}

Accumulate inputs

The job of consoleintr is to accumulate input characters in cons.buf until a whole line arrives.

Wake up when get a whole line

When a newline arrives, consoleintr wakes up a waiting consoleread (if there is one).

Copy to user space

Once woken, consoleread will observe a full line in cons.buf, copy it to user space and return to user space.

Question:

How does open(“console", O_RDWR) opens a file with DEVICE type?

Research: It seems this console string is defined somewhere. I tried to change to other string, and it does not work. Using this console string to open file, the file inode returns a file with type is DEVICE.

Answer:

OS create a console device using system call mknod. Any read or write with console is interacting with the UART hardware.

PreviousWhat does kernel.ld do in XV6?

Last updated 5 years ago

Was this helpful?