Scribe Notes
1/23/08
by:
Jeff Lee
Hagop Hagopian
Alan Zhao
Orthogonality
y z
| /
| /
|/___ x (3-D axis grid)
any combination of (x,y,z) works
features
OS
we can explore the space by combining features (like using x,y,z to define a position in a space), use this to design systems
examples of non-orthogonality
Java: every value is an object
put them into hash tables
subclass them
except for; int, double
Double <--- object
Orthogonal axes for accessing files:
open
close
read
write
is this enough?
create a temp file
read_write truncate any existing file to 0 length
\ \
int fol = open ("/tmp/CS111",O_RDWR | O_CREAT | O_TRUNC, 0666)
/ \ \
don't really care create file if it doesnt exist mode argument - specifies permission of
Why all these options? any newly created file
used only in some cases, awkward
Alternative primitives
(steal this from UNIX v7 1979)
int fd = creat("temp/cs111", 0666) == open("temp/cs111",O_CREAT, 0666)
( no O_CREAT )
pros/cons
+ push complexity of the file creation into a different axis
- complicates code that may want open or create, depending on options
- implemention/documentation overlap quite a lot
SIDE NOTE 1:
open options
O_RDONLY - read
O_WRONLY - write
O_RDWR - read/write
O_CREAT - boolean value, create if needed
O_TRUNC - truncate if it exists
circa 1985
CREAT defined to mean open(...,O_WRONLY|O_CREAT|O_TRUNC,...)
new axis: what flags can you give open?
combinations that are questionable
(...,O_RDONLY|O_CREAT|O_TRUNC,...) (..., O_RDONLY|O_TRUNC,...)
Permissions are determined by two things
1) Application - specifies most generous permission
2) umask - restricts permissions according to user preferences
$umask 022 <- bits to turn off when files are created
$umask 077 = trust only myself
0666-022 = 0644
SIDE NOTE 2:
unix permissions
ls -l
-rwxr-xr-x
111,101,101
7 5 5
owner group other
read write execute
-rw-rw-rw
110 110 110
6 6 6
SIDE NOTE 3:
Unix: orthogonality vs compactness
1. Compactness is the property that a design can fit inside the OS without intervening other parts.
2. When the OS has too many components, (in other words: extremely orthogonal), each component
will interrupt other components or they will compete to get enough memory to run their processes.
3. If 2 happens, a racing condition was raised.
open("f",O_WRONLY|O_CREAT, 0)
2 processes executing program at same time
1) fd = open ("tmp/cs111a",O_RDWR|O_CREAT|O_TRUNC,0666)
2) fd = open ("tmp/cs111b",O_RDWR|O_CREAT|O_TRUNC,0666)
we dont want this! we want each process to have its own file (assume we are writng the code)
Race Condition - bug engendered by two processes "racing" to access the same resource
Possible solutions
A) File locking: 1st opener wins
B) open with permission 0, remove when done
-pain to have unreadable files
C) use differnet file names: derived from time of day, process id, host name, random number, etc.
-crash means everyone is locked out
D) look at all files in /tmp choose a name not in that list
-slow
-doesn't work due to race condition
E) check where file exists
if so, sleep 1 sec, try again
if not, open
use file
remove it
introduce 4th flag: O_EXCL, don't open file if it already exists, no race conditions
always used with O_CREAT
char file[100]
do
generate_randomname(file)
while (fd = open(file,O_RDWR|O_CREAT|O_EXCL,0666) < 0 && errno == Eexist)
SIDE NOTE 4:
create a temp file
int mkstemp(char* template) <- some OS's don't pass in a value
/ \
fd of a new file "tmp/abcdxxxxxx" 6 x's
this is a library function, not a system call
This is a primitive in some OS's
pro/cons
+ let OS choose file location
+ let OS free file
+ OS need not worry about persistence
SIDE NOTE 5:
locking files struct flock*
F_SETLK /
int s = fcntl(fd,F_SETLKW, P)
F_GETLK \
pointer
\
l_type
l_whence
l_start
l_len
l_pid
<- read/write/unlock
<- SEEK_SET, SEEK_CUR, SEEK_END
<- starting offset
<- size of region locked
<- which pid is being looked at
--------------------------------------------------------------------
| lock | | lock |
--------------------------------------------------------------------
/ \
i want a "write lock" i want a read lock
exclusive shared
honor system, with respect to read+write
advisory locks (not mandatory)
pros
+ I/O is a bit faster
+ minimizes hassle
cons
- "dishonorable" processes
- program crashes with a lock => locks evaporate
- overlapping locks collide within a process, freeing up one lock frees up part of another lock
- fork : child lacks locks
primitives for process creation/destruction
parent stuff/child process id
pid_t fork (void); or 0
or -1
int execvp(char const* file, char* const *argv);
always returns -1; errno says failure reason
WNOHANO = don't wait
/
pid_t waitpid(pid_t pid, int* status, int options)
/ \
process waiting for child's exit status
or any
child stuff 8 bit
/
void_exit(status)
void exit(status)
int main (...) {return 27;}
void print_date(void){
pid_t p = fork();
if (p<0)
error(); //error calls exit
if (p == 0){
char* const args[2] = {"/bin/date",NULL};
execvp(args[0],args);
error();
}
int status;
if (waitpid(p,&status,0)< 0) error();
if (!WIFEXITED(status) || WEXITSTATUS(status)!=0) error();
}
int posix_spawnp(pid_t* restrict_pid, const char* restrict_file,
const posispawnfileactions_t* file_acts, describes all
const posix_spawn_attract* restrict_attrp, "interesting things"
char* const* restrict_argv,
char* const* restrict_envp);