The document describes the process of starting a process on a PC. It explains that when a PC boots, the BIOS starts executing and loads the boot loader from the boot disk sector. The boot loader then loads the kernel into memory and jumps to it. The kernel boot loader then initializes devices and creates the first process by setting up its page table and memory space. The first process's state is set to runnable and the scheduler runs it, switching to its address space. The first process makes a system call to load the /init program, which creates the console and shell that runs as the main process.
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
AOS Lab 1: Hello, Linux!
1. Lab 3: Let there be a process!
Advanced Operating Systems
Zubair Nabi
zubair.nabi@itu.edu.pk
February 13, 2013
2. 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
3. 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
4. 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
5. 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
6. 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
7. 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
8. 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
9. 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
10. 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
11. 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
12. 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
13. 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
14. 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
15. 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
16. 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
17. 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
18. 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
19. 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
20. 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
21. 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
22. 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
23. 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
24. 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
25. 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
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
• 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
30. 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
31. 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
32. 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
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 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
42. 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
43. 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
44. 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
45. 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
46. 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
47. 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
48. 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
49. 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
50. 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
51. 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
53. 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
}
54. Reading
Appendix A and B and Chapter 1 from “xv6: a simple, Unix-like
teaching operating system”