Operating systems function at lower levels of abstraction
Kernel operates in supervisor mode
init
(process #1): system startup
Kernel concerns
Process: (essentially) running program
Conventions for file descriptors
cin
in C++)cout
)cerr
)File descriptors are used for low-level operations (read/write array of bytes)
FILE*
or C++ iostream
are language-level objects that wrap a file descriptor
System call/trap
int
s & pointersGlobal variable errno
hold integer error code (raw info)
perror
(standard library function) prints meaningful error messageUnix/Linux/Posix: separation between process creation & program invocation
pid_t pid = fork()
clones process (not to be confused with Linux clone
system call)
Child process inherits same open files as parents
Parent is responsible for collecting child exit status: wait
/waitpid
Process tree
Fork is useful for distributing workload
But, what if you want to run a different program
Pipe: original IPC (inter-process communication) mechanism
Pipe is unidirectional: one end writes; other end reads
Pipe instance is a file descriptor (2 descriptors, one for write, other for read)
write
/read
system calls as regular file
vtbl
)From programming POV (point-of-view), pipe is just like an ordinary file
pipe
system call returns a pair of open file descriptors for producer (writer) & consumer (reader)
Single process can't really use pipe descriptors
File descriptor is index into a kernel data structure (array element)
Recall: files stay open across fork
Typically one process closes the reader and keeps the writer while the other does the opposite
Patterns of usage TODO: diagram
Shell syntax: vertical bar
do_this | do_that
or
operatorShell only supports pipelines with standard input/standard output
Basic file ops (read bytes, write bytes): good abstraction for many things
/dev/null
, /dev/zero
, /dev/random
Standard input (fd 0) & standard output (fd 1) are pre-opened by parent process
Standard input is not the keyboard; standard ouput is not the screen
Unless you have a good reason otherwise, your programs will be simpler & more flexible if you use standard input & standard output
Shell syntax for redirecting input/output
<
standard input from file>
standard output to file>>
standard output append file2>
standard error to file|
pipe standard output of command 1 into standard input of command 2fork
allows a program to divide work arcorss multiple processes, each running the same program
pipe
is just one IPC mechanism
But what if you want to run a different program?
excve
(plus several standard library wrappers that let you marshal arguments differently)exec*
replaces current running program in process wtih new program, new argv
exec
is successful, it does not return (you can't go home again)Open files (file descriptors) stay open across exec
Why separate calls for fork
& exec
?
fork
, before exec
fork
but not exec
exec
without fork
init
processWe now have enough information to construct a rudimentary shell
argv
)stdin
/stdout
/stderr
fork
wait
(or wait_pid
)argv
exec
exit
when doneTODO: diagram
TODO: diagram
Convex hull problem
Graham scan algorithm
Performance analysis:
TODO: diagrams
TODO: diagrams
Divide & conquer algorithm
The assignment is to use fork
to compute the halves in separate processes
pipe
)