150 likes | 288 Views
CSC 552.201 - Advanced Unix Programming, Fall, 2008. Welcome back to UNIX System Programming! Tuesday, September, class 2. Before next class (Sept. 8). cp –pr ~parson/UnixSysProg ~/UnixSysProg chmod 700 ~/UnixSysProg ls –l ~/UnixSysProg For each of UnixSysProg/ forkexec redirectio multiplex
E N D
CSC 552.201 - Advanced Unix Programming, Fall, 2008 Welcome back to UNIX System Programming! Tuesday, September, class 2
Before next class (Sept. 8) • cp –pr ~parson/UnixSysProg ~/UnixSysProg • chmod 700 ~/UnixSysProg • ls –l ~/UnixSysProg • For each of UnixSysProg/ forkexec redirectio multiplex • “cd” into directory, then “gmake clean test” • Examine and play with examples until you understand them. • Bring any questions to our next class.
C++ interfaces and dynamic loading • ~parson/UnixSysProg/lecture1/oo_variant • We will walk through code and test execution in class. • Important points • C++ abstract classes are used as interfaces. • Derived C++ concrete classes provide implementation. • An abstract factory method uses dynamic loading and run-time type checking (RTTI) to load a concrete derived class and its concrete factory method. • An factory method runs a constructor. • See man pages for dlopen(), dlsym() and dynamic_cast.
Unified Modeling Language (UML) Class Diagram of oo_variant print_main printmain.cxx <<interface>> printargs_interface.h printargs_interface printargs_interface.cxx printargs(outfile : file, stringv : string[], stringc : int) loadAndConstruct(path : string) : printargs_interface printargs_simpleimpl printargs_simpleimpl.h and .cxx printargs(outfile : file, stringv : string[], stringc : int) printargs_simpleimpl_factory() : printargs_interface
Sequence Diagram of oo_variant,inspect load with “pldd –F PID” printmain printargs_interface printargs_simpleimpl OS main loadAndConstruct(argv[1]) dlopen(file) shared object file handle dlsym(file handle, factoryname) *factoryFunction *factoryFunction printargs_simpleimpl_factory() printargs_simpleimpl() printargs_simpleimpl object object <dynamic_cast> printargs(file, stringv, stringc)
fork / exec / wait example code • ~parson/UnixSysProg/lecture2/forkexec • usage forkexec CMD [ CMDARGS... ] • Important points • argc / argv command parameter usage • Use C string library to parse a command parameter. • fork()’s return value indicates parent or child PID. • getpid() returns child PID to child; getppid() gets parent. • exec() returns only on failure. • Use ps –flu, pmap [ -xlF ] PID to examine both processes.
fork() and exec() • Use the POSIX fork() • Solaris fork1() is identical to fork() • Solaris forkall() (forks all threads) is not portable • There are multiple flavors of exec() • execl[e|p] takes an explicit list of argv strings to pass • execv[e|p] takes an argv array, terminated by NULL ptr. • The “e” variants pass an environment variable array. • The “p” variants use the PATH to find the executable. • Access env variables in “extern char **environ” or via getenv(3C)
Fun with fork() and exec()! • What does this do? • ./forkexecwait echo hello • ./forkexec echo hello • ./forkexecwait ./forkexecwait echo hello • Use “/etc/mknod tunnel p” to create a FIFO! • This creates a “named pipe,” used for inter-process communication (IPC). • One process can block while reading the pipe. • Another process can then write through the pipe. • Remove “tunnel” when you are done.
More fun with fork(), exec(), and a named pipe. • Try the following in two different windows. • ./forkexecwait ./forkexecwait cat tunnel • ps –flu USERNAME ; pmap [ -xlF ] PID • Try to spot a Zombie child process. • ./forkexecwait ./forkexec cat tunnel • ps –flu USERNAME • Oops, the parent is too fast recovering the zombie! • Try setting environment variable NEIGHBORGHOOD_ZOMBIE_WATCH to 10 seconds.
Programming practices • Always check and handle library return codes! • malloc() and new are exceptions that we will discuss. • Error logs, exit codes and C++ exceptions are useful. • Buffer overruns are annoying and dangerous • See man page for gets(), for example. • Make malloc/free or new/delete symmetrical. • Always use { curly braces } for control blocks. • Use both healthy and degenerate tests. • Ignoring these rules will cost you points.
open() level 2 system call for opening a file, returns an int fd • Takes a path, mode, and optional permissions • Path can be a file, a device, or a FIFO. • Modes include O_RDONLY, O_RDWR, O_WRONLY, O_TRUNC, O_APPEND, O_CREAT, O_EXCL, O_NONBLOCK, O_NDELAY, others, |’d together. • Permissions for O_CREAT are 3 3-bit octal numbers for read, write and execute, see table 4.1 on p. 105, S_I[RWX][USR][GRP][OTH], S_IRWX[UGO], S_IS[UG]ID • create(path, permissions) is a synonym for open(path, O_WRONLY | O_CREAT | O_TRUNC, permissions) • O_CREAT|O_EXCL fails on an existing file.
close() is a little simpler • It closes a file descriptor (fd) open by open(), pipe or socket functions, or other means. • lseek(int fd, int offset, int whence) • seeks within a file, offset is location to which to go • whence is one of SEEK_SET (from start), SEEK_CUR (from current), SEEK_END (from end). • dup(fd) duplicates the fd in the lowest available number • dup2(fd, fd2) duplicates fd into fd2
File descriptors from Figure 4.2, page 120 file descriptor system file table in-memory inode table table [0] [1] [2] [3] fd in user data user memory space kernel memory Open an input file, close 0, dup new fd into 0, close new fd – redirects stdin. Open an output file, close 1, dup new fd into 1, close new fd – redirects stdout.
File IO redirection example • ~parson/UnixSysProg/lecture2/redirectio • usage: redirectio path < FILEIN > FILEOUT (or >. FILEOUT) [ & ] • Important points • open() sets up input or output files for redirection. • close() of STDIN_FILENO and STDOUT_FILENO makes their file descriptor numbers available. • dup() or dup2() use the just-closed file descriptors. • This occurs after fork and before exec in the child. • exec() then starts the child program with redirected IO.
select() system call example • ~parson/UnixSysProg/lecture2/multiplex • usage: multiplex INFILE [ INFILE . . . ] INFILE0 INFILE1 … select() INFILE0 INFILEn read()/write() loop • select() can block on a SET of file IO handles (includes pipes and sockets) until some are ready for IO. There is no need to poll (yuck)!