Omar Sheikh
Karapet Shaginyan
CS111 Lecture 5
Professor Eggert
10/8/09 10:00AM 
Orthogonality
-decisions on each axis are independent, and (ideally) result in a useful design. This is out goal in OS design.
- Example: making changes in the file system should not result in having to rewrite the way processes are handled.
      - 
In OS design, our three main issues are files, processes, and memory. 
You can think of these as the labels on the axes of a 3-D plane and 
the orthogonality analogy should make sense. 
How to model O.S. resources in a 
user program.  (mechanism) 
O.S. data structure
(process descriptor)
      (file 
descriptor) 
Struct pte {int pid; int vid; ______;};
O.S. struct pte *p = return (struct pte foolya*) ~ (int) p;
| struct foolya; | 
3) an int (very common)
OS table
table itself is in memory
application sees the table
memory is invisible to application 
Passing out ints is a very common approach in Unix, here are some examples:
pid_t, fd(int), uid_t, gid_t, IP 
ports, ino_t, dev_t 
The drawback of this method: ints 
are easily forged. Anyone can guess a number. 
int main (void) {
kill (1, SIG_KILL);
} 
We get around this drawback by forcing 
out OS to check if an application has authority of certain ints. 
int main (void) {
char buf[512];
read(27, buf, sizeof(buf));
}
returns EBADF - bad file descriptors 
int main(int argc, char **argv) {
kill(atoi(argv[1]), SIGTERM));
return 0;
} 
how to kill yourself in shell
$ kill $$ 
kill(getpid(), SIGTERM); 
Files and Processes
creating/destroying file descriptors
      int 
open(char const *filename, int flags[, mode_t mode]); 
If a syscall fails (returns with 
-1, you can examine the variable errno to get more information about 
the failure. On a successful syscall, errno is garbage. Errno is special 
because it is a thread local variable. 
 
When opening a file use one either 
O_RDONLY, O_WRONLY, O_RDWR for either read-only, write-only, or read-and-write 
respectively. Use O_CREAT if you want the OS to create the file if it 
doesn't already exist. 
Example: open(“/tmp/foo”, O_RDONLY|O_CREAT, 
0666) 
0666 specifies the permissions. These 
are 9 bits that are used to specifiy the owner's, group's, and other's 
permissions for a file or directory. The first 3 bits represent the 
permissions for the owner, the next 3 bits for the group, and the final 
3 bits for others. In each category, if the first bit is on, then read 
permissions are available. If the second second bit is on, it represents 
write permissions, if the third bit is on, it represents execute permissions. 
a side note on permissions:
| 101 | 111 | 110 | 100 | 
| 5 | 7 | 6 | 4 | 
| sticky bit | user | group | other | 
arg to open for a created file
=> mask it with the process’s 
umask (in process descriptor) 
m&~u is file’s actual mode 
program: open(“foo”, O_WRONLY, 0666);
users says umask 022 
0666
0022
0644 
Too much orthogonality? 167 --x rw- 
rwx is possible. This means others can read, write, execute, but the 
owner can only execute. This is strange, but allowable. 
 
creating/destroying fds fd= open(--)
                              
creating/destroying processes. pid_t fork(void);
clone process
parent are identical except
                              
                              
multiple versions of exit:
int or void exit(int(exit status)); <--C library cleanup
void  _exit(int);    <--syscall 
int printdate(void){ ---char args [2] = {“date”, NULL};
pid_t p=fork();
switch(p){
case -1: return -1;
case 0: execup(“/usr/bin/date”, args);
default: int status;
if (waitpid(p, &status, 0 <0) return -1;
                  return status; 
int execup(char const *filename, char *const *args);
change program to filename, run it’s main function
always returns -1 (if it returns) 
settings errno 
 
date.c
int main(int argc, char **argv){
            decode_options(
gettimeofday(-);
int n = printf(---);
int o = fflush(stdout);
if (ok(n,o)) return 0;
else return 1;
} 
O.S. does this:
      exit(main(argc, 
argv)); 
race conditions
behavior goes bad if processes are scheduled in a certain way:
does waitpid get called in parent before or after -exit is called in child?
zombie processes: child has died, 
but parent hasn’t waited on it yet, preserve the exit status in the 
case that the parents requests it. 
open
exit => closes all open fds
fd = open (“foo”, o_RDWR, _ )
remove(“foo”);
read(fd, _) a nameless file: sticks around, until file is closed.
write(___) 
while (exists(n)) n = n+ “x”;
p1: open(n, O_RDWR, O_CREAT, 0666);
p2: