CS111 - scribe notes for 04/09/2008

by Amir Baharlou, Kin Thai, Khuong Truong

 

Organization of Operating Systems

Goals (what we want):

  • Protection – we want to prevent a program running by one user from accessing the data of another
  • Robustness – programs do not affect one another in adverse ways
  • Utilization – the computer is a resource, we don’t want to waste it
  • Performance – we’re trying to get the best performance from applications, not to be confused with utilization though they certainly overlap.
  • Flexibility – trying to make the computer as flexible as possible to maximize what can be done
  • Simplicity – we seek clarity
  • These goals cannot all be satisfied at once, a balance is sought

Virtualized Processor (what we have)

  • Lets us (the OS) take control when an application behaves improperly (i.e. halt, etc…) such as a privileged instruction.
  • Lets us (the OS) take control periodically no matter what
    • For example when a program seems to fall into a loop
  • Lets us (the OS) take control when an application accesses memory that it “shouldn’t.”
  • This “shouldn’t” is defined by us
  • Lets us (the OS) take control when the application attempts to communicate with the outside world (i.e. network connections, other applications, I/O devices, USB ports, DVD, clock, etc…)
    • Usually occurs on a case by case basis
    • The “outside world” has a disputed definition
  • Runs at “full” speed

Virtualized processor + OS = support for a set of processes

  • A process is a program running atop an abstract computer
    • Lacks halt, etc. (privileged instructions)
    • Has higher-level “instructions” built on these lower level ones
      • Referred to as system calls
    • Created using a primitive call
    •  
      • Pid_t fork(void);
        • it takes a process to create a process”
        • when a computer boots the OS initially calls a process called init who then “forks” the other processes.
        • It creates a near clone of the existing process. One is the parent, and the other is the child.
      • Int execvp(char const *file, char const **argv);
        • File – file containing new process
        • Argv – pointer to a an array of pointers to a an array of characters containing each parameter
        • Terminates a current process and starts another
        • Returns an Int
          • -1 = error
            • error type stored in errno. To do so, we need to have #include <errno.h>
          • always fails because the caller no longer exists…
          • historical value
      • x86 is completely unaware of these functions

layering build a more-useful high level of abstraction (e.g. fork) atop a more detailed low level of abstraction (e.g. halt int)

  • at the bottom is the hardware layer (controlled by intel)
  • at the top are applications (written by user)
  • in the middle are the low level called OS Kernel and some allowed instructions.
    • OS Kernel has the ability to access privileged hardware instruction. It also has as set of system calls available to applications to allow controlled access to hardware
    • Allowed hardware instructions include: load, store, multiply, etc…
  • ‘read’ is too low level for most users
  • operates on file descriptors
    above it exist libraries like stdio (in the C library) that contain functions that more efficiently manage the calling of kernel system calls, such as getchr()
    a separate layer or abstract machine

How do we do system calls?

  • Method 0 – implement them as function calls
    • This method is just like using other function calls in C-program. It is very popular in embedded applications where applications are under tight control. The downside of this method is that it will not prevent application from bypassing restrictions (using privileged insfructions.)
  • Method 1 - protected transfer of control
    • Ordinary applications can’t execute “bad” instructions
    • Kernel can
    • Memory is divided into app area and kernel area
      • Privileged instructions only work when they exist in the kernel area
        • Does not necessarily prevent applications from writing into kernel
        • Does not necessarily prevent applications from jumping to privileged instructions
      • X86 – to get protected transfer of control, execute a privileged instruction
        • By convention the INT (interrupt) instruction
        • Causes the processor to enter kernel state at a place specified by the kernel
        • In the kernel
          • Interrupt address table
          • 256 pointers to interrupt handler code (there are normally more pointers than this, i.e. larger than 8 bit operand)
          • x86 pushes onto the kernel stack
            • ss – stack segment
            • esp – stack pointer
            • eflags –
            • cs – code segment
            • eip – instruction pointer
            • error code sets ip
          • what if another interrupt comes in? (i.e. from a device)
            • for now: assume it waits
          • one must be aware of stack overflow
            • a separate area of memory is reserved for the kernel
          • after the error code is executes
            • RETI instruction occurs
            • Pops the kernel stack and returns control

Levels of control:

  • X86 has 4 levels of control:
    • Kernel at the center
    • Applications at the outermost
    • Two levels in between for other services such as drivers
  • In this class, we only use 2 levels (Kernel and Applications)

Syscall

  • Similar to function calls
  • Somewhat slower
    • More stuff saved on stack
    • Compiler can’t optimize as well
    • Decoding overhead in interrupt handler
  • We want these to be relatively rare
  • What (machine resources) are we protecting/managing with the syscall mechanism?
    • Components that need management
      • ALU – user code gets full access
        • Registers
          • General purpose – user code gets full access
            • Gets more complicated with shared memory
          • Privileged – read-only or sometimes no access
          • Primary memory (RAM)
            • User memory – full (or partial) access
            • Kernel memory – protected
        • I/O devices
          • Typically no access for user code
          • There are exceptions
            • Video memory for graphics, etc
          • Time
            • To catch loops/hogs
      • Register control
        • Assume virtualizable processor (hardware) controls access
        • Each process has its own copy of all these registers
          • Kernel has a table of all the processes on the system: process descriptor table
          • Each process descriptor contains a copy of all registers as well as other information
          • While the process is running the information in the table is useless
        • Context switch overhead – time lost doing this.
      • Memory control
        • Virtual memory – same analogy as applied to virtual processor
        • Process sees a segment of memory that is in actuality spread out around physical memory.
        • A magic box handles all mapping and makes interrupts when necessary.
          • The magic box has virtual memory page tables
            • Stored in kernel memory
            • Process descriptor table gives location of virtual memory page tables.
          • The magic box prevents access to the stack
      • Device Control
        • Typically so slow that operating system does not attempt to optimize
        • System calls on their own tend to work
        • Classic examples: read, write, open, close, lseek
        • Robustness is often a real issue
          • High probability of something going wrong
          • Accesses are checked more carefully
        • Devices tend to differ greatly
          • More work to develop clean and portable interfaces
        • Two “types” of devices (line is blurry)
          • Network/stream devices
            • More spontaneous
            • Potentially infinite data
          • Random access devices
            • More request/response


UNIX’s big idea:

  • Treat all resources as files. Therefore, it allows to use anything simply by executing "read" and "write"
    • Linux has a whole directory called /proc/
  • How well does this work?
  • It definitely works for a keyboard; however, some things don’t fit and have extra functions ( i.e. changing the speed of a serial port and ioctl)