CS 111: Operating Systems

Lecture 5 Scribe Notes (Winter 2012)

Prepared by Matthew Arakaki, Danny Jung, and Edward Youn for a lecture given by Professor

Paul Eggert on January 25, 2012.

 

 

 

Orthogonality

 

 

What is Orthogonality?

 

  Any arbitrary point in a 3D space can be described in terms of three independent variables: x, y, and z. Each component has its distinct axis to represent.

  Similarly, orthogonality in computer systems is a property that guarantees that if one component of the system is modified it will not affect any of the other components of the system.

 

(process)

fork

waitpid

execlp

exit

(file)

open

read

write

close

 

  The more independent the system calls (left column) and I/O operations (right column) are, the more

orthogonal the OS becomes.

 

 

What does fork() do?

 

             

 

Formal definition:

Fork() creates a child process that duplicates the process that calls fork. The child process is

mostly identical to the calling process; however, it has a unique process ID. Any open file

descriptors are shared with the parent process. The child process executes independently of

the parent process.

 

Simple definition:

  Calling p = fork() will create a new process (the child process) based on current process. Child

process is a clone of parent, except:

 

Parent

Child

p = child's pid

getpid() returns ppid

p = 0

getpid() returns cpid

ppid() returns

parent’s parent ID

ppid() returns parent ID

Execution time is accumulated.

Since it was just created, there is no execution time accumulated.

File locks

(none)

Pending signals

(none)

 

The longer the list of differences between the parent and child processes, the less orthogonal

they are.

 

The child process is created with initially identical file descriptor table as its parent’s. However,

the child process’ file descriptor table is free to change in the future.

 

Each process has a file descriptor:

 

registers

file descriptor table

 

parent

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

registers

file descriptor table

child

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

The file description of the child is initially the same as the parent, but it can be changed.

 

 

What does execlp do?

 

execlp("/usr/bin/date", ...)

 

  Formal definition:

  Like all of the exec functions, execlp replaces the calling process image with a new process

image. This has the effect of running a new program with the process ID of the calling process.

Note that a new process is not started; the new process image simply overlays the original

process image. The execlp function is most commonly used to overlay a process image that

has been created by a call to the fork function.

 

  Simple definition:

  Keep all the things that fork() clones, destroy all the things that fork() keeps.

                                                            (all code, all data, stack, ip, ...)

Replaced by "date" freshcrt0, calls main()

 

process

axis

 

 

 

 

fork munges this

exec munges this

 

 

void printable(void)  {                                                    no return void error(void);

            pid_t p = fork();                                                          FUN FACT: no "void" in 1977

            switch(p) {

           case -1:  error();

           case 0:  execvp("usr/bin/date" (char * [2]) {"date", 0})  // we’re in the child

           error();

     }

     int status;

     if (waitpid(p, &status, 0) < 0)    error();

     if (!WIPEXITED(status) || EXITSTATUS(status) != 0)    error();

}

 

 

 

crt0.c

int argcMAGIC;

char ** argvMAGIC;

void MAGIC(void) {

     exit(main(argcMAGIC, argvMAGIC));

}

 

exit library call (flushes stdout)

-exit syscall

 

int posix_spawnvp(pid *restrict pid, char const *restric file,

posixspawnfile_action_t const file_acts,

posixspawn_attr_t const *restrict attr,

char *const *restrict argv,

                char *const *restrict envp);

 

 

Access to device + files

- devices are slow  syscall overhead is OK

- robustness is a real issue  syscall recommended

- devices differ, but we want a clean interface to them all

 

Device Categories

Network (stream) vs. Disk (storage)

Mouse, Keyboard, etc.

Spontaneous data generation

Sequential input

Potentially infinite in terms of size

SSD, Storage, etc

Request/Response

Random access

Finite in size

 

#1 BIG IDEA of UNIX: All devices use the same system calls using file descriptors

                                     (small integers in app mapped to files)

Despite the wide range of device functionality, from keyboards

to SSD, the same system calls can be used. The file descriptors

describe how the system calls will be used to carry out each

specific function of any device.

 

 

open

close

all

devices

 

read

write

lseek

storage devices only

pread

pwrite

 

What can go wrong with file descriptors?

 

while(open("/", O_RDONLY) >= 0)

            continue;   

// File descriptors are stored within a file descriptor table so there is a

// limited amount of space allocated for them. So, if a condition like in

// the code the given code occurs, they can be exhausted.

int fd = open("file", O_WRONLY | O_CREAT, 0666);

unlink("file");

write(fd, ...);                                                  doing I/O to nameless file is possible…

read(fd, ...);                                                     where is it stored? This is one of the ways

                                                                        to create temp files, or… to annoy people.

 

If someone is abusing this method to create traffic, this could be countered by using lsof(),

which could be used to list all of the currently open files.

 

//  By the way… How do you create temp files?

// char name[sizeof “/tmp/sort”+(sizeof(pid_t)*char_bit+2)/3];

// sprint(name,”/tmp/sort %d”, get_pid())disk SSD,…

// fd = open(name,O_RDWR | O_CREATE,0600);

// unlink(name);

 

Race condition -  This is a problem created when two processes are competing for a

     shared resource (like a global variable). Two processes access same

     "location" to see who "wins"

     Usually both sides get destroyed.

 

struct stat st;

f = new_file_name();

while(stat(f, &st) == 0)

     f = new_file_name(++i);

open(f, O_RDWR | O_CREAT | O_EXCEL, 0600);