[OSTEP] 1. Introduction to Operating Systems

ch1 ~ 2: 인트로


Table Of Contents


Three pieces


  • virtualization
  • concurrency
  • persistence

In learning about these three pieces, we'll learn about

  • how an operantion system works
  • how OS decides what program to run next on a CPU
  • how OS handles memory overload in a virtual memory system
  • how virtual machine monitors work
  • how to manage information on disks
  • how to build a distributed system that works when parts have failed

Introduction to Operating Systems


  • What happens when a program runs?
    • It executes instructions.
      1. Fetch : The processor fetches an instruction from memory.
      2. Decode : i.e., figure out which instruction this is
      3. Execute : i.e., add two numbers, access memory, check a condition, jump to function, and so forth.
    • and the processor moves on to the next instruction and so on until the program completes.

Operating System

There is a body of software(= operating system, OS) which is responsible for

  • making it easy to run programs
  • allowing to share memory
  • enabling programs to interact with devices

Virtualization

  • The primary way the OS does things above.
  • virtual machine: the OS takes a physical resource and transforms it into a virtual form of itself.
    • physical resource : i.e., processor, memory, disk, etc.
    • virtual form : more general, powerful, easy-to-use
    • thus we sometimes refer OS as a virtual machine
  • system calls: interfaces provided by the OS in order to allow users to tell the OS what to do and thus make use of the features of the virtual machine.
    • we sometimes say that the OS provies a standard library to applications.
  • resource manager : the OS's role is to manage resourses(CPU, memory, disk) efficiently or fairly or other possible goals in mind.
    • sharing the CPU → allows many programs to run
    • sharing memory → allows many program to comcurrently access their own instructions and data
    • sharing disks → allows many programs to access devices

1. Virtualizing The CPU

Example

#include <stdio.h> #include <stdlib.h> #include <sys/time.h> #include <assert.h> #include "common.h" int main(int argc, char* argv[]) { if (argc != 2) { fprintf(stderr, "usage: cpu <string>\n"); exit(1); } char* str = argv[1]; while (1) { Spin(1); printf("%s\n", str); } return 0; }

Figure 2.1: Simple Example: Code That Loops And Prints (cpu.c)

  • This program repeatedly checks the time and returns once it has run for a second. Then, it prints out the string that the user passed in on the command line, and repeats, forever.

  • Let's run this file on a system with a single processor the result will be like

    prompt> gcc -o cpu cpu.c -Wall prompt> ./cpu "A" A A A A ˆC prompt>

    and this program will run forever until we press "Control-c" to halt the program.

  • Let's do more complicated example

    prompt> ./cpu A & ./cpu B & ./cpu C & ./cpu D & [1] 7353 [2] 7354 [3] 7355 [4] 7356 A B D C A B D C A ...

    Even though we have only one processor, all four of programs seem to be running at the same time.

virtualiziing the CPU = the OS turns a single CPU (or small set of them) into a seemingly infinite number of CPUs and thus allowing many programs to seemingly run at once

2. Virtualizing Memory

(Physical) Memory

  • an array of bytes
    • to read memory : one must specify an address to be able to access the data sotred there
    • to write(update) memory : one muse specify the data to be written to the given address
  • memory is accessed all the time when a program is running.
    • program keeps all of its data structures in memory
    • each instruction of the program is in memory → memory is accessed on each insstruction fetch

Example

#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include "common.h" int main(int argc, char* argv[]) { int* p = malloc(sizeof(int)); // a1 assert(p != NULL); printf("(%d) address pointed to by p: %p\n", getpid(), p); // a2 *p = 0; // a3 while (1) { Spin(1); *p = *p + 1; printf("(%d) p: %d\n", getpid(), *p); // a4 } return 0; }

Figure 2.3: A Program That Accesses Memory (mem.c)

  • a1 : allocate some memory

  • a2 : print out the address of the memory

  • a3 : put the number zero into the first slot of the newly allocated memory

  • a4 : loop, delaying for a second and incrementing the value stored at the address held in p.

  • in every print statement, there is process identifier(the PID) of the running program.

  • The output

    prompt> ./mem (2134) address pointed to by p: 0x200000 (2134) p: 1 (2134) p: 2 (2134) p: 3 (2134) p: 4 (2134) p: 5 ˆC
    • The newly allocated memory is at address 0x200000
    • It updates the value and prints out the result
  • Running mem.c multiple times

    prompt> ./mem &; ./mem & [1] 24113 [2] 24114 (24113) address pointed to by p: 0x200000 (24114) address pointed to by p: 0x200000 (24113) p: 1 (24114) p: 1 (24114) p: 2 (24113) p: 2 (24113) p: 3 (24114) p: 3 (24113) p: 4 (24114) p: 4 ...
    • It is as if each program has its own private memory.
    • Each program allocated memory at the same address, but updated the value at the address independently.

Each process accesses its own private virtual address space (address space)

  • the OS maps address space onto the physical memory of the machine
  • A memory reference within one running program does not affect the address space of other processes

3. Concurrency

  • refers a host of problems when working on many things at once (i.e., concurrently) in the same program
  • the problems of concurrency are not limited to the OS: modern multi-threaded programs exhibit the same problems

Example

#include <stdio.h> #include <stdlib.h> #include "common.h" volatile int counter = 0; int loops; void* worker(void* arg) { int i; for (i = 0; i < loops; i++) { counter++; } return NULL; } int main(int argc, char* argv[]) { if (argc != 2) { fprintf(stderr, "usage: threads <value>\n"); exit(1); } loops = atoi(argv[1]); pthread_t p1, p2; printf("Initial value : %d\n", counter); Pthread_create(&p1, NULL, worker, NULL); Pthread_create(&p2, NULL, worker, NULL); Pthread_join(p1, NULL); Pthread_join(p2, NULL); printf("Final value : %d\n", counter); return 0; }

Figure 2.5: A Multi-threaded Program (threads.c)

  • main program creates to threads
  • each thread starts running in a routeine called worker(), in which it simply increments a counter in a loop for loops number of times
prompt> ./thread 100000 Initial value : 0 Final value : 143012 // huh?? prompt> ./thread 100000 Initial value : 0 Final value : 137298 // what the??
  • these odd and unusual outcomes relate to how instructions are executed.
    1. load the value of the counter from memory into a register
    2. increment it
    3. store it back into memeory
  • these three instructions do not execute atomically (all at once) → problem of concurrency happen

4. Persistence

  • We need hardware and software to be able to store data persistently
    • hardware: I/O device; hard drive, solid-state drive(SSD)
    • software: file system

Example

#include <stdio.h> #include <unistd.h> #include <assert.h> #include <fcntl.h> #include <sys/types.h> int main(int argc, char* argv[]) { int fd = open("/tmp/file", O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU); assert(fd > -1); int rc = write(fd, "hello world\n", 13); assert(rc == 13); close(fd); return 0; }

Figure 2.6: A Program That Does I/O (io.c)

  • code to create a file (/tmp/file) that contains the string “hello world”, making three calls into the OS.
    1. open(): opens the file and creates it
    2. write(): writes some data to the file
    3. close(): closes the file thus indicating the program won't be writing any more data to it.

5. Design Goals

  • OS does:
    1. takes physical resources such as a CPU, memory or disk
    2. virtualizes them
    3. handles tough and tricky issues related to concurrency
    4. stores files persistently
  • Design goals
    1. Build up some abstractions
      • Make the system convenient and easy to use
    2. Provide high performance
      • = Minimize the overheads of the OS
      • provide virtualization and other OS features without excessive overheads.
    3. Provide protection between applications or the OS and applications
      • isolation; isolating processes from one another is the key to protection
    4. Provide a high degree of reliability
      • OS must run non-stop
    5. energy0efficiency
    6. security
    7. mobility