Lab 3: Let there be a process!
Advanced Operating Systems

Zubair Nabi
zubair.nabi@itu.edu.pk

February 13, 2013
Turning on a PC

1

PC boots

2

Starts executing the BIOS (stored on the motherboard)

3

Loads code from the first 512 bytes of boot disk a.k.a. boot sector
• Contains the kernel boot loader
• Instructions to load the kernel into memory
• Loads the boot loader at address 0x7c00
• Jumps to it (sets the %ip)

4

The OS boot loader starts running
• Contained within bootasm.S and bootmain.c in case of xv6
Turning on a PC

1

PC boots

2

Starts executing the BIOS (stored on the motherboard)

3

Loads code from the first 512 bytes of boot disk a.k.a. boot sector
• Contains the kernel boot loader
• Instructions to load the kernel into memory
• Loads the boot loader at address 0x7c00
• Jumps to it (sets the %ip)

4

The OS boot loader starts running
• Contained within bootasm.S and bootmain.c in case of xv6
Turning on a PC

1

PC boots

2

Starts executing the BIOS (stored on the motherboard)

3

Loads code from the first 512 bytes of boot disk a.k.a. boot sector
• Contains the kernel boot loader
• Instructions to load the kernel into memory
• Loads the boot loader at address 0x7c00
• Jumps to it (sets the %ip)

4

The OS boot loader starts running
• Contained within bootasm.S and bootmain.c in case of xv6
Turning on a PC

1

PC boots

2

Starts executing the BIOS (stored on the motherboard)

3

Loads code from the first 512 bytes of boot disk a.k.a. boot sector
• Contains the kernel boot loader
• Instructions to load the kernel into memory
• Loads the boot loader at address 0x7c00
• Jumps to it (sets the %ip)

4

The OS boot loader starts running
• Contained within bootasm.S and bootmain.c in case of xv6
Process

• A sandboxed container for a program
• Illusion of an exclusive CPU;
• and a private address space

• Works on virtual addresses
• Need hardware support to make virtual to physical mapping
• OS maintains a page table for each process
Process

• A sandboxed container for a program
• Illusion of an exclusive CPU;
• and a private address space

• Works on virtual addresses
• Need hardware support to make virtual to physical mapping
• OS maintains a page table for each process
Process

• A sandboxed container for a program
• Illusion of an exclusive CPU;
• and a private address space

• Works on virtual addresses
• Need hardware support to make virtual to physical mapping
• OS maintains a page table for each process
Process

• A sandboxed container for a program
• Illusion of an exclusive CPU;
• and a private address space

• Works on virtual addresses
• Need hardware support to make virtual to physical mapping
• OS maintains a page table for each process
Process (2)

• The address space contains the process’s memory
• Instructions, data, stack, and heap

• Where does the kernel reside then?
• Kernel’s instructions and data is also mapped to high addresses
to each process’s address space
• Each system call executes in the kernel’s mapping of this address
space
• Can directly refer user memory
Process (2)

• The address space contains the process’s memory
• Instructions, data, stack, and heap

• Where does the kernel reside then?
• Kernel’s instructions and data is also mapped to high addresses
to each process’s address space
• Each system call executes in the kernel’s mapping of this address
space
• Can directly refer user memory
Process (2)

• The address space contains the process’s memory
• Instructions, data, stack, and heap

• Where does the kernel reside then?
• Kernel’s instructions and data is also mapped to high addresses
to each process’s address space
• Each system call executes in the kernel’s mapping of this address
space
• Can directly refer user memory
Process (3)

• Process state within the kernel resides within a struct proc
• Page table, kernel stack, and run state

• Each process has:
• A thread of execution, which can be suspended and resumed
• Two stacks:
1
2

User stack
Kernel stack

• During the execution of user code, the user stack is used and the
kernel stack is empty
Process (3)

• Process state within the kernel resides within a struct proc
• Page table, kernel stack, and run state

• Each process has:
• A thread of execution, which can be suspended and resumed
• Two stacks:
1
2

User stack
Kernel stack

• During the execution of user code, the user stack is used and the
kernel stack is empty
Process (3)

• Process state within the kernel resides within a struct proc
• Page table, kernel stack, and run state

• Each process has:
• A thread of execution, which can be suspended and resumed
• Two stacks:
1
2

User stack
Kernel stack

• During the execution of user code, the user stack is used and the
kernel stack is empty
Process (4)

• In case of an interrupt or a system call, the processor:
1

Switches to the kernel stack
• The user stack is still present

2

Raises the hardware privilege level
Starts executing kernel instructions

3

• Once the kernel is done, the processor:
Lowers the privilege level
Switches back to the user stack
3 Resumes executing user instructions
1
2
Process (4)

• In case of an interrupt or a system call, the processor:
1

Switches to the kernel stack
• The user stack is still present

2

Raises the hardware privilege level
Starts executing kernel instructions

3

• Once the kernel is done, the processor:
Lowers the privilege level
Switches back to the user stack
3 Resumes executing user instructions
1
2
Process (4)

• In case of an interrupt or a system call, the processor:
1

Switches to the kernel stack
• The user stack is still present

2

Raises the hardware privilege level
Starts executing kernel instructions

3

• Once the kernel is done, the processor:
Lowers the privilege level
Switches back to the user stack
3 Resumes executing user instructions
1
2
Process (4)

• In case of an interrupt or a system call, the processor:
1

Switches to the kernel stack
• The user stack is still present

2

Raises the hardware privilege level
Starts executing kernel instructions

3

• Once the kernel is done, the processor:
Lowers the privilege level
Switches back to the user stack
3 Resumes executing user instructions
1
2
Process (4)

• In case of an interrupt or a system call, the processor:
1

Switches to the kernel stack
• The user stack is still present

2

Raises the hardware privilege level
Starts executing kernel instructions

3

• Once the kernel is done, the processor:
Lowers the privilege level
Switches back to the user stack
3 Resumes executing user instructions
1
2
Process (4)

• In case of an interrupt or a system call, the processor:
1

Switches to the kernel stack
• The user stack is still present

2

Raises the hardware privilege level
Starts executing kernel instructions

3

• Once the kernel is done, the processor:
Lowers the privilege level
Switches back to the user stack
3 Resumes executing user instructions
1

2
Process (4)

• In case of an interrupt or a system call, the processor:
1

Switches to the kernel stack
• The user stack is still present

2

Raises the hardware privilege level
Starts executing kernel instructions

3

• Once the kernel is done, the processor:
Lowers the privilege level
Switches back to the user stack
3 Resumes executing user instructions
1

2
Process (4)

• In case of an interrupt or a system call, the processor:
1

Switches to the kernel stack
• The user stack is still present

2

Raises the hardware privilege level
Starts executing kernel instructions

3

• Once the kernel is done, the processor:
Lowers the privilege level
Switches back to the user stack
3 Resumes executing user instructions
1

2
Process (5)

• Process states are present within p->state
•
•
•
•
•

Allocated
Ready to run
Running
Waiting for I/O
Exiting

• Page table exists at p->pgdir
• Used by the paging hardware
Process (5)

• Process states are present within p->state
•
•
•
•
•

Allocated
Ready to run
Running
Waiting for I/O
Exiting

• Page table exists at p->pgdir
• Used by the paging hardware
First page table

• When the kernel starts running, virtual addresses map directly to
physical ones
• Why?

• Assembly code within the kernel sets up the first page table
• Now the kernel main can run
First page table

• When the kernel starts running, virtual addresses map directly to
physical ones
• Why?

• Assembly code within the kernel sets up the first page table
• Now the kernel main can run
First page table

• When the kernel starts running, virtual addresses map directly to
physical ones
• Why?

• Assembly code within the kernel sets up the first page table
• Now the kernel main can run
First process

• main first initializes devices and subsystems
• The first process is then created via userinit() which in turn
calls allocproc()
• allocproc() is in charge of allocating a new struct proc
in the process table and setting up its kernel state
• userinit() is only called for the first process while
allocproc() is called for each process creation
First process

• main first initializes devices and subsystems
• The first process is then created via userinit() which in turn
calls allocproc()
• allocproc() is in charge of allocating a new struct proc
in the process table and setting up its kernel state
• userinit() is only called for the first process while
allocproc() is called for each process creation
First process

• main first initializes devices and subsystems
• The first process is then created via userinit() which in turn
calls allocproc()
• allocproc() is in charge of allocating a new struct proc
in the process table and setting up its kernel state
• userinit() is only called for the first process while
allocproc() is called for each process creation
First process

• main first initializes devices and subsystems
• The first process is then created via userinit() which in turn
calls allocproc()
• allocproc() is in charge of allocating a new struct proc
in the process table and setting up its kernel state
• userinit() is only called for the first process while
allocproc() is called for each process creation
First process (2)

• allocproc() (also called by fork()):
1 Scans the process table for a free slot (p->state ==
UNUSED)
2 When it finds one, sets p->state = EMBRYO
4

Assigns the process a pid
Allocates a kernel stack for the process
• In case of failure, sets p->state = UNUSED

5

Sets up a specially prepared kernel stack

3
First process (2)

• allocproc() (also called by fork()):
1 Scans the process table for a free slot (p->state ==
UNUSED)
2 When it finds one, sets p->state = EMBRYO
4

Assigns the process a pid
Allocates a kernel stack for the process
• In case of failure, sets p->state = UNUSED

5

Sets up a specially prepared kernel stack

3
First process (2)

• allocproc() (also called by fork()):
1 Scans the process table for a free slot (p->state ==
UNUSED)
2 When it finds one, sets p->state = EMBRYO
4

Assigns the process a pid
Allocates a kernel stack for the process
• In case of failure, sets p->state = UNUSED

5

Sets up a specially prepared kernel stack

3
First process (2)

• allocproc() (also called by fork()):
1 Scans the process table for a free slot (p->state ==
UNUSED)
2 When it finds one, sets p->state = EMBRYO
4

Assigns the process a pid
Allocates a kernel stack for the process
• In case of failure, sets p->state = UNUSED

5

Sets up a specially prepared kernel stack

3
First process (2)

• allocproc() (also called by fork()):
1 Scans the process table for a free slot (p->state ==
UNUSED)
2 When it finds one, sets p->state = EMBRYO
4

Assigns the process a pid
Allocates a kernel stack for the process
• In case of failure, sets p->state = UNUSED

5

Sets up a specially prepared kernel stack

3
First process (3)

• userinit():
2

Sets up a page table for the process via setupkvm()
Copies the binary for initcode.S (the first process) via

3

inituvm()
Sets p->state = RUNNABLE

1
First process (3)

• userinit():
2

Sets up a page table for the process via setupkvm()
Copies the binary for initcode.S (the first process) via

3

inituvm()
Sets p->state = RUNNABLE

1
First process (3)

• userinit():
2

Sets up a page table for the process via setupkvm()
Copies the binary for initcode.S (the first process) via

3

inituvm()
Sets p->state = RUNNABLE

1
Running the first process

1

After userinit(), main() calls mpmain() which in turn
calls scheduler()

2

scheduler() looks for a process with p->state ==
RUNNABLE

3

It then sets the per-cpu proc variable to the target process

4

Calls switchuvm() to enable the hardware to use p->pgdir

5

Sets p->state = RUNNING

6

Calls swtch() to force a context switch and load p->context
Running the first process

1

After userinit(), main() calls mpmain() which in turn
calls scheduler()

2

scheduler() looks for a process with p->state ==
RUNNABLE

3

It then sets the per-cpu proc variable to the target process

4

Calls switchuvm() to enable the hardware to use p->pgdir

5

Sets p->state = RUNNING

6

Calls swtch() to force a context switch and load p->context
Running the first process

1

After userinit(), main() calls mpmain() which in turn
calls scheduler()

2

scheduler() looks for a process with p->state ==
RUNNABLE

3

It then sets the per-cpu proc variable to the target process

4

Calls switchuvm() to enable the hardware to use p->pgdir

5

Sets p->state = RUNNING

6

Calls swtch() to force a context switch and load p->context
Running the first process

1

After userinit(), main() calls mpmain() which in turn
calls scheduler()

2

scheduler() looks for a process with p->state ==
RUNNABLE

3

It then sets the per-cpu proc variable to the target process

4

Calls switchuvm() to enable the hardware to use p->pgdir

5

Sets p->state = RUNNING

6

Calls swtch() to force a context switch and load p->context
Running the first process

1

After userinit(), main() calls mpmain() which in turn
calls scheduler()

2

scheduler() looks for a process with p->state ==
RUNNABLE

3

It then sets the per-cpu proc variable to the target process

4

Calls switchuvm() to enable the hardware to use p->pgdir

5

Sets p->state = RUNNING

6

Calls swtch() to force a context switch and load p->context
Running the first process

1

After userinit(), main() calls mpmain() which in turn
calls scheduler()

2

scheduler() looks for a process with p->state ==
RUNNABLE

3

It then sets the per-cpu proc variable to the target process

4

Calls switchuvm() to enable the hardware to use p->pgdir

5

Sets p->state = RUNNING

6

Calls swtch() to force a context switch and load p->context
First system call

1

Once initcode.S starts, it makes a call to exec() asking it
to load /init

2

/init creates a new console file and opens it as file descriptors
0, 1, and 2

3

Starts looping

4

Creates a console shell

5

Once the shell exits, it handles zombies
First system call

1

Once initcode.S starts, it makes a call to exec() asking it
to load /init

2

/init creates a new console file and opens it as file descriptors
0, 1, and 2

3

Starts looping

4

Creates a console shell

5

Once the shell exits, it handles zombies
First system call

1

Once initcode.S starts, it makes a call to exec() asking it
to load /init

2

/init creates a new console file and opens it as file descriptors
0, 1, and 2

3

Starts looping

4

Creates a console shell

5

Once the shell exits, it handles zombies
First system call

1

Once initcode.S starts, it makes a call to exec() asking it
to load /init

2

/init creates a new console file and opens it as file descriptors
0, 1, and 2

3

Starts looping

4

Creates a console shell

5

Once the shell exits, it handles zombies
First system call

1

Once initcode.S starts, it makes a call to exec() asking it
to load /init

2

/init creates a new console file and opens it as file descriptors
0, 1, and 2

3

Starts looping

4

Creates a console shell

5

Once the shell exits, it handles zombies
xv6

Your operating system is up and running now!
Today’s Task

• Write C code that implements a grep with two optional flags: -f
and -v and a wc with three optional flags: -b, -l, and -w
• Make two different source files: grep.c and wc.c
• Should be callable via ./grep -v -f foo for instance
• Boilerplate code:

void main(int argc, char *argv[]) {
// argc: number of arguments
// argv[]: array of string arguments
// your code goes here
}
Reading

Appendix A and B and Chapter 1 from “xv6: a simple, Unix-like
teaching operating system”

AOS Lab 1: Hello, Linux!

  • 1.
    Lab 3: Letthere be a process! Advanced Operating Systems Zubair Nabi zubair.nabi@itu.edu.pk February 13, 2013
  • 2.
    Turning on aPC 1 PC boots 2 Starts executing the BIOS (stored on the motherboard) 3 Loads code from the first 512 bytes of boot disk a.k.a. boot sector • Contains the kernel boot loader • Instructions to load the kernel into memory • Loads the boot loader at address 0x7c00 • Jumps to it (sets the %ip) 4 The OS boot loader starts running • Contained within bootasm.S and bootmain.c in case of xv6
  • 3.
    Turning on aPC 1 PC boots 2 Starts executing the BIOS (stored on the motherboard) 3 Loads code from the first 512 bytes of boot disk a.k.a. boot sector • Contains the kernel boot loader • Instructions to load the kernel into memory • Loads the boot loader at address 0x7c00 • Jumps to it (sets the %ip) 4 The OS boot loader starts running • Contained within bootasm.S and bootmain.c in case of xv6
  • 4.
    Turning on aPC 1 PC boots 2 Starts executing the BIOS (stored on the motherboard) 3 Loads code from the first 512 bytes of boot disk a.k.a. boot sector • Contains the kernel boot loader • Instructions to load the kernel into memory • Loads the boot loader at address 0x7c00 • Jumps to it (sets the %ip) 4 The OS boot loader starts running • Contained within bootasm.S and bootmain.c in case of xv6
  • 5.
    Turning on aPC 1 PC boots 2 Starts executing the BIOS (stored on the motherboard) 3 Loads code from the first 512 bytes of boot disk a.k.a. boot sector • Contains the kernel boot loader • Instructions to load the kernel into memory • Loads the boot loader at address 0x7c00 • Jumps to it (sets the %ip) 4 The OS boot loader starts running • Contained within bootasm.S and bootmain.c in case of xv6
  • 6.
    Process • A sandboxedcontainer for a program • Illusion of an exclusive CPU; • and a private address space • Works on virtual addresses • Need hardware support to make virtual to physical mapping • OS maintains a page table for each process
  • 7.
    Process • A sandboxedcontainer for a program • Illusion of an exclusive CPU; • and a private address space • Works on virtual addresses • Need hardware support to make virtual to physical mapping • OS maintains a page table for each process
  • 8.
    Process • A sandboxedcontainer for a program • Illusion of an exclusive CPU; • and a private address space • Works on virtual addresses • Need hardware support to make virtual to physical mapping • OS maintains a page table for each process
  • 9.
    Process • A sandboxedcontainer for a program • Illusion of an exclusive CPU; • and a private address space • Works on virtual addresses • Need hardware support to make virtual to physical mapping • OS maintains a page table for each process
  • 10.
    Process (2) • Theaddress space contains the process’s memory • Instructions, data, stack, and heap • Where does the kernel reside then? • Kernel’s instructions and data is also mapped to high addresses to each process’s address space • Each system call executes in the kernel’s mapping of this address space • Can directly refer user memory
  • 11.
    Process (2) • Theaddress space contains the process’s memory • Instructions, data, stack, and heap • Where does the kernel reside then? • Kernel’s instructions and data is also mapped to high addresses to each process’s address space • Each system call executes in the kernel’s mapping of this address space • Can directly refer user memory
  • 12.
    Process (2) • Theaddress space contains the process’s memory • Instructions, data, stack, and heap • Where does the kernel reside then? • Kernel’s instructions and data is also mapped to high addresses to each process’s address space • Each system call executes in the kernel’s mapping of this address space • Can directly refer user memory
  • 13.
    Process (3) • Processstate within the kernel resides within a struct proc • Page table, kernel stack, and run state • Each process has: • A thread of execution, which can be suspended and resumed • Two stacks: 1 2 User stack Kernel stack • During the execution of user code, the user stack is used and the kernel stack is empty
  • 14.
    Process (3) • Processstate within the kernel resides within a struct proc • Page table, kernel stack, and run state • Each process has: • A thread of execution, which can be suspended and resumed • Two stacks: 1 2 User stack Kernel stack • During the execution of user code, the user stack is used and the kernel stack is empty
  • 15.
    Process (3) • Processstate within the kernel resides within a struct proc • Page table, kernel stack, and run state • Each process has: • A thread of execution, which can be suspended and resumed • Two stacks: 1 2 User stack Kernel stack • During the execution of user code, the user stack is used and the kernel stack is empty
  • 16.
    Process (4) • Incase of an interrupt or a system call, the processor: 1 Switches to the kernel stack • The user stack is still present 2 Raises the hardware privilege level Starts executing kernel instructions 3 • Once the kernel is done, the processor: Lowers the privilege level Switches back to the user stack 3 Resumes executing user instructions 1 2
  • 17.
    Process (4) • Incase of an interrupt or a system call, the processor: 1 Switches to the kernel stack • The user stack is still present 2 Raises the hardware privilege level Starts executing kernel instructions 3 • Once the kernel is done, the processor: Lowers the privilege level Switches back to the user stack 3 Resumes executing user instructions 1 2
  • 18.
    Process (4) • Incase of an interrupt or a system call, the processor: 1 Switches to the kernel stack • The user stack is still present 2 Raises the hardware privilege level Starts executing kernel instructions 3 • Once the kernel is done, the processor: Lowers the privilege level Switches back to the user stack 3 Resumes executing user instructions 1 2
  • 19.
    Process (4) • Incase of an interrupt or a system call, the processor: 1 Switches to the kernel stack • The user stack is still present 2 Raises the hardware privilege level Starts executing kernel instructions 3 • Once the kernel is done, the processor: Lowers the privilege level Switches back to the user stack 3 Resumes executing user instructions 1 2
  • 20.
    Process (4) • Incase of an interrupt or a system call, the processor: 1 Switches to the kernel stack • The user stack is still present 2 Raises the hardware privilege level Starts executing kernel instructions 3 • Once the kernel is done, the processor: Lowers the privilege level Switches back to the user stack 3 Resumes executing user instructions 1 2
  • 21.
    Process (4) • Incase of an interrupt or a system call, the processor: 1 Switches to the kernel stack • The user stack is still present 2 Raises the hardware privilege level Starts executing kernel instructions 3 • Once the kernel is done, the processor: Lowers the privilege level Switches back to the user stack 3 Resumes executing user instructions 1 2
  • 22.
    Process (4) • Incase of an interrupt or a system call, the processor: 1 Switches to the kernel stack • The user stack is still present 2 Raises the hardware privilege level Starts executing kernel instructions 3 • Once the kernel is done, the processor: Lowers the privilege level Switches back to the user stack 3 Resumes executing user instructions 1 2
  • 23.
    Process (4) • Incase of an interrupt or a system call, the processor: 1 Switches to the kernel stack • The user stack is still present 2 Raises the hardware privilege level Starts executing kernel instructions 3 • Once the kernel is done, the processor: Lowers the privilege level Switches back to the user stack 3 Resumes executing user instructions 1 2
  • 24.
    Process (5) • Processstates are present within p->state • • • • • Allocated Ready to run Running Waiting for I/O Exiting • Page table exists at p->pgdir • Used by the paging hardware
  • 25.
    Process (5) • Processstates are present within p->state • • • • • Allocated Ready to run Running Waiting for I/O Exiting • Page table exists at p->pgdir • Used by the paging hardware
  • 26.
    First page table •When the kernel starts running, virtual addresses map directly to physical ones • Why? • Assembly code within the kernel sets up the first page table • Now the kernel main can run
  • 27.
    First page table •When the kernel starts running, virtual addresses map directly to physical ones • Why? • Assembly code within the kernel sets up the first page table • Now the kernel main can run
  • 28.
    First page table •When the kernel starts running, virtual addresses map directly to physical ones • Why? • Assembly code within the kernel sets up the first page table • Now the kernel main can run
  • 29.
    First process • mainfirst initializes devices and subsystems • The first process is then created via userinit() which in turn calls allocproc() • allocproc() is in charge of allocating a new struct proc in the process table and setting up its kernel state • userinit() is only called for the first process while allocproc() is called for each process creation
  • 30.
    First process • mainfirst initializes devices and subsystems • The first process is then created via userinit() which in turn calls allocproc() • allocproc() is in charge of allocating a new struct proc in the process table and setting up its kernel state • userinit() is only called for the first process while allocproc() is called for each process creation
  • 31.
    First process • mainfirst initializes devices and subsystems • The first process is then created via userinit() which in turn calls allocproc() • allocproc() is in charge of allocating a new struct proc in the process table and setting up its kernel state • userinit() is only called for the first process while allocproc() is called for each process creation
  • 32.
    First process • mainfirst initializes devices and subsystems • The first process is then created via userinit() which in turn calls allocproc() • allocproc() is in charge of allocating a new struct proc in the process table and setting up its kernel state • userinit() is only called for the first process while allocproc() is called for each process creation
  • 33.
    First process (2) •allocproc() (also called by fork()): 1 Scans the process table for a free slot (p->state == UNUSED) 2 When it finds one, sets p->state = EMBRYO 4 Assigns the process a pid Allocates a kernel stack for the process • In case of failure, sets p->state = UNUSED 5 Sets up a specially prepared kernel stack 3
  • 34.
    First process (2) •allocproc() (also called by fork()): 1 Scans the process table for a free slot (p->state == UNUSED) 2 When it finds one, sets p->state = EMBRYO 4 Assigns the process a pid Allocates a kernel stack for the process • In case of failure, sets p->state = UNUSED 5 Sets up a specially prepared kernel stack 3
  • 35.
    First process (2) •allocproc() (also called by fork()): 1 Scans the process table for a free slot (p->state == UNUSED) 2 When it finds one, sets p->state = EMBRYO 4 Assigns the process a pid Allocates a kernel stack for the process • In case of failure, sets p->state = UNUSED 5 Sets up a specially prepared kernel stack 3
  • 36.
    First process (2) •allocproc() (also called by fork()): 1 Scans the process table for a free slot (p->state == UNUSED) 2 When it finds one, sets p->state = EMBRYO 4 Assigns the process a pid Allocates a kernel stack for the process • In case of failure, sets p->state = UNUSED 5 Sets up a specially prepared kernel stack 3
  • 37.
    First process (2) •allocproc() (also called by fork()): 1 Scans the process table for a free slot (p->state == UNUSED) 2 When it finds one, sets p->state = EMBRYO 4 Assigns the process a pid Allocates a kernel stack for the process • In case of failure, sets p->state = UNUSED 5 Sets up a specially prepared kernel stack 3
  • 38.
    First process (3) •userinit(): 2 Sets up a page table for the process via setupkvm() Copies the binary for initcode.S (the first process) via 3 inituvm() Sets p->state = RUNNABLE 1
  • 39.
    First process (3) •userinit(): 2 Sets up a page table for the process via setupkvm() Copies the binary for initcode.S (the first process) via 3 inituvm() Sets p->state = RUNNABLE 1
  • 40.
    First process (3) •userinit(): 2 Sets up a page table for the process via setupkvm() Copies the binary for initcode.S (the first process) via 3 inituvm() Sets p->state = RUNNABLE 1
  • 41.
    Running the firstprocess 1 After userinit(), main() calls mpmain() which in turn calls scheduler() 2 scheduler() looks for a process with p->state == RUNNABLE 3 It then sets the per-cpu proc variable to the target process 4 Calls switchuvm() to enable the hardware to use p->pgdir 5 Sets p->state = RUNNING 6 Calls swtch() to force a context switch and load p->context
  • 42.
    Running the firstprocess 1 After userinit(), main() calls mpmain() which in turn calls scheduler() 2 scheduler() looks for a process with p->state == RUNNABLE 3 It then sets the per-cpu proc variable to the target process 4 Calls switchuvm() to enable the hardware to use p->pgdir 5 Sets p->state = RUNNING 6 Calls swtch() to force a context switch and load p->context
  • 43.
    Running the firstprocess 1 After userinit(), main() calls mpmain() which in turn calls scheduler() 2 scheduler() looks for a process with p->state == RUNNABLE 3 It then sets the per-cpu proc variable to the target process 4 Calls switchuvm() to enable the hardware to use p->pgdir 5 Sets p->state = RUNNING 6 Calls swtch() to force a context switch and load p->context
  • 44.
    Running the firstprocess 1 After userinit(), main() calls mpmain() which in turn calls scheduler() 2 scheduler() looks for a process with p->state == RUNNABLE 3 It then sets the per-cpu proc variable to the target process 4 Calls switchuvm() to enable the hardware to use p->pgdir 5 Sets p->state = RUNNING 6 Calls swtch() to force a context switch and load p->context
  • 45.
    Running the firstprocess 1 After userinit(), main() calls mpmain() which in turn calls scheduler() 2 scheduler() looks for a process with p->state == RUNNABLE 3 It then sets the per-cpu proc variable to the target process 4 Calls switchuvm() to enable the hardware to use p->pgdir 5 Sets p->state = RUNNING 6 Calls swtch() to force a context switch and load p->context
  • 46.
    Running the firstprocess 1 After userinit(), main() calls mpmain() which in turn calls scheduler() 2 scheduler() looks for a process with p->state == RUNNABLE 3 It then sets the per-cpu proc variable to the target process 4 Calls switchuvm() to enable the hardware to use p->pgdir 5 Sets p->state = RUNNING 6 Calls swtch() to force a context switch and load p->context
  • 47.
    First system call 1 Onceinitcode.S starts, it makes a call to exec() asking it to load /init 2 /init creates a new console file and opens it as file descriptors 0, 1, and 2 3 Starts looping 4 Creates a console shell 5 Once the shell exits, it handles zombies
  • 48.
    First system call 1 Onceinitcode.S starts, it makes a call to exec() asking it to load /init 2 /init creates a new console file and opens it as file descriptors 0, 1, and 2 3 Starts looping 4 Creates a console shell 5 Once the shell exits, it handles zombies
  • 49.
    First system call 1 Onceinitcode.S starts, it makes a call to exec() asking it to load /init 2 /init creates a new console file and opens it as file descriptors 0, 1, and 2 3 Starts looping 4 Creates a console shell 5 Once the shell exits, it handles zombies
  • 50.
    First system call 1 Onceinitcode.S starts, it makes a call to exec() asking it to load /init 2 /init creates a new console file and opens it as file descriptors 0, 1, and 2 3 Starts looping 4 Creates a console shell 5 Once the shell exits, it handles zombies
  • 51.
    First system call 1 Onceinitcode.S starts, it makes a call to exec() asking it to load /init 2 /init creates a new console file and opens it as file descriptors 0, 1, and 2 3 Starts looping 4 Creates a console shell 5 Once the shell exits, it handles zombies
  • 52.
    xv6 Your operating systemis up and running now!
  • 53.
    Today’s Task • WriteC code that implements a grep with two optional flags: -f and -v and a wc with three optional flags: -b, -l, and -w • Make two different source files: grep.c and wc.c • Should be callable via ./grep -v -f foo for instance • Boilerplate code: void main(int argc, char *argv[]) { // argc: number of arguments // argv[]: array of string arguments // your code goes here }
  • 54.
    Reading Appendix A andB and Chapter 1 from “xv6: a simple, Unix-like teaching operating system”