CS 111: Operating Systems
Lecture 5 Scribe Notes (Winter 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);