Onion Peeling lecture in color

Disclaimer

Creating a discipline

Onion Peeling

The top level: sanity checks

Files and Directories

  1. All files are stored in inodes.
  2. Inode number uniquely identifies file.
  3. A directory is just a special kind of file that contains names for inodes.
  4. .. in a directory points to containing directory (except that /.. is /).
  5. To derive a name for an inode, follow ..'s all the way to /.

Protections

  1. Protection of a thing determines what you can do with the content of the thing.
    1. r: can read it (ls).
    2. w: can write it (edit).
    3. x: can execute it (or search it for a name).
  2. Whether you can rm or create a file is determined by the protection of the immediate parent directory.
  3. Whether you can access a thing is determined by all components of the full path to it.

Filesystems

  1. start with `unformatted' storage device.
  2. create filesystem on device with newfs.
  3. mount filesystem on directory.
  4. fsck filesystem to correct errors.
  5. umount filesystem to stop using it.
  6. df to check status of mounts.
  7. kinds of filesystems:
    1. local: on device (ext2)
    2. remote: on network (nfs)

Processes

  1. Every process is a descendant of init.
  2. Every process has a process id that identifies it.
  3. Environment variables are inherited by children.
  4. When a child dies, environment is not transferred back to parent.
  5. Communicate with processes via kill command
    1. actually sends signals
    2. HUP (-1): hangup; `re-read databases'.
    3. KILL (-9): die now.
    4. TERM (-15): die when convenient.

Environment

  1. PATH: where to find programs
    1. list of directories containing candidate programs.
    2. all programs executable by you become available.
    3. first match wins.
  2. MANPATH: where to find man pages
    1. like PATH but for man pages.
  3. LD_LIBRARY_PATH: where to find libraries
    1. like PATH but for libraries.

Networking

  1. To understand a an IP networking problem, first identify the logical wires.
  2. Each logical wire must have a distinct network address.
  3. (Net address) = (IP address) & (Subnet mask) (bitwise and).
  4. (Broadcast address) = (IP address) | ~(Subnet mask) (bitwise or).
  5. available addresses between (Net address) and (Broadcast address)-1
  6. The ARP table describes only IP-to-MAC addresses for directly connected wires.
  7. Routing table gateways must be addressed on directly connected wires.
  8. Routing targets can be anywhere.
  9. meaning of RIP information is based upon the router that sent it.

Refinement

MAC address:

IP address:

Name:

ARP protocol/tables

Routing tables

RIP

Services

Difficult example: shell startup

Need a new model of knowledge

New concept: algorithmic skeletons

Structured abstraction and descent

Step 1: form a naive model

  1. Runlevel between 0 and 6
    1. 0: halted
    2. 1: single-user
    3. 3: multi-user
    4. 6: reboot
  2. scripts in /etc/rc.d/rc[0-6].d say what to do.
    1. K[0-9][0-9]something: stop something
    2. S[0-9][0-9]something: start something
  3. these are symlinks to scripts in /etc/rc.d/init.d
    1. two possible arguments: start and stop.

Step 2: refine this model

  1. /etc/rc.d/rc:
     runlevel=3
     for s in /etc/rc.d/rc$runlevel.d/K??*; do 
       $s stop
     done
     for s in /etc/rc.d/rc$runlevel.d/S??*; do 
       $s start
     done
    
  2. a typical startup script:
     pid=`/bin/ps -e | /bin/awk '$4=="foo" { print $1 }'`
     case $1 in 
       start) 
        [ $pid = '' ] && [ -x /usr/sbin/foo ] && /usr/sbin/foo &  
        ;; 
       stop) 
        [ $pid != '' ] && /bin/kill $pid  
        ;; 
       *) 
        echo "usage: foo {start or stop}"
    

Step 3: refine more as necessary

  1. /var/lock/subsys/* contain lockfiles for subsystems.
     pid=`/bin/ps -e | /bin/awk '$4=="foo" { print $1 }'`
     case $1 in 
       start) 
        [ $pid = '' ] && [ ! -e /var/lock/subsys/foo ] \
                      && [ -x /usr/sbin/foo ] \
                      && /bin/touch /var/lock/subsys/foo \
                      && /usr/sbin/foo &  
        ;; 
       stop) 
        [ $pid != '' ] && /bin/rm -f /var/lock/subsys/foo \
                       && /bin/kill $pid  
        ;; 
       *) 
        echo "usage: foo {start or stop}"
    
  2. add functions to kill process or start daemon:
     #! /bin/sh
     
     # Source function library.
     . /etc/rc.d/init.d/functions
     
     # Get config.
     . /etc/sysconfig/network
     
     # Check that networking is up.
     if [ ${NETWORKING} = "no" ]
     then
             exit 0
     fi
     
     [ -f /var/local/ssh/sbin/sshd2 ] || exit 0
     
     RETVAL=0
     
     # See how we were called.
     case "$1" in
       start)
             echo -n "Starting sshd: "
             daemon /var/local/ssh/sbin/sshd2
             RETVAL=$?
             echo
             [ $RETVAL -eq 0 ] && touch /var/lock/subsys/sshd
             ;;
       stop)
             echo -n "Stopping sshd services: "
             killproc sshd2
             RETVAL=$?
             echo
             [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/sshd
             ;;
       status)
             status sshd2
             RETVAL=$?
             ;;
       restart|reload)
             $0 stop
             $0 start
             RETVAL=$?
             ;;
       *)
             echo "Usage: $0 {start|stop|status|restart|reload}"
             exit 1
     esac
     
     exit $RETVAL
    
  3. here's where it gets complex: functions call others:
  4. A function to stop a program.
     killproc() {
       RC=0
       # Test syntax.
       if [ $# = 0 ]; then
         echo "Usage: killproc {program} [signal]"
         return 1
       fi
    
       notset=0
       # check for second arg to be kill level
       if [ "$2" != "" ] ; then
         killlevel=$2
       else
         notset=1
         killlevel="-9"
       fi
    
       # Save basename.
       base=`basename $1`
     
       # Find pid.
       pidlist=`pidofproc $base`
     
       pid=
       for apid in $pidlist ; do
          [ -d /proc/$apid ] && pid="$pid $apid"
       done
    
       # Kill it.
       if [ "$pid" != "" ] ; then
         [ $BOOTUP = "verbose" ] && echo -n "$base "
         if [ "$notset" = "1" ] ; then
           if ps h $pid>/dev/null 2>&1; then
             # TERM first, then KILL if not dead
             kill -TERM $pid
             usleep 100000
             if ps h $pid >/dev/null 2>&1 ; then
               sleep 1
               if ps h $pid >/dev/null 2>&1 ; then
                 sleep 3
                 if ps h $pid >/dev/null 2>&1 ; then
                   kill -KILL $pid
                 fi
               fi
             fi
           fi
           ps h $pid >/dev/null 2>&1
           RC=$?
           [ $RC -eq 0 ] && failure "$base shutdown" || success "$base shutdown"
           RC=$((! $RC))
           # use specified level only
         else
           if ps h $pid >/dev/null 2>&1; then
             kill $killlevel $pid
             RC=$?
             [ $RC -eq 0 ] && success "$base $killlevel" || failure "$base $killlevel"
           fi
         fi
       else
         failure "$base shutdown"
       fi
     
       # Remove pid file if any.
       if [ "$notset" = "1" ]; then
         rm -f /var/run/$base.pid
       fi
       return $RC
     }
    
  5. but it's not over yet:
  6. A function to find the pid of a program.
     pidofproc() {
       # Test syntax.
       if [ $# = 0 ] ; then
         echo "Usage: pidofproc {program}"
         return 1
       fi
    
       # First try "/var/run/*.pid" files
       if [ -f /var/run/$1.pid ] ; then
         pid=`head -1 /var/run/$1.pid`
         if [ "$pid" != "" ] ; then
           echo $pid
           return 0
         fi
       fi
     
       # Next try "pidof"
       pid=`pidof -o $$ -o $PPID -o %PPID -x $1`
       if [ "$pid" != "" ] ; then
         echo $pid
         return 0
       fi
     }
    
  7. Gasp! Another function pidof: see man pidof for details.

lecture in color

/comp/150NET/notes/onion.php
downloaded on Nov-23-2009 03:45:32 PM,
was last modified on Feb-17-2004 10:49:11 PM.

All lecture note content is copyright 2004 by
Alva L. Couch, Computer Science, Tufts University