March 29, 2006
Coverage: [USP] Chapters
8
and 9
Sophisticated Program Control: sigsetjmp and siglongjmp
- consider the following control flow problems:
- if blocking a ctrl-c during a complex calculation,
where to transfer program control when the calculation is complete?
- how to restart a dialog when the user enters
an erroneous response somewhere several nested-menus deep?
- C programs use signals (indirectly or directly) to address these
situations
- resembles exception-handling in OO languages and systems
- also similar to the call/cc construct of Scheme
- indirect approach
- signal handler sets a flag
- program tests that flag in strategic places
- complex: program might have to return through several layers of
functions
- direct approach: use sigsetjmp and siglongjmp
- sigsetjump is like a statement label
- siglongjmp is like a goto
- difference is that this pair of functions cleans up (unravels) the
program stack and signal states in addition to transferring control
- sigsetjump takes an env parameter of type
sigjmp_buf to store the context
- siglongjump takes env to restore the context
and an int val to simulate the return of sigsetjump
Overview of Using Asynchronous I/O
- recall system calls block the current process
- e.g., read and write usually block a process
until the i/o completes (synchronous)
- what if we want to continue executing?
- use POSIX:AIO Asynchronous I/O Extension
- relevant functions
- aio_read
- aio_write
- aio_return
- aio_error
- aio_cancel
- main idea is that a signal notifies the process when
the i/o is complete
- struct aiocb (asynchronous i/o control block)
contains
- fields which specify how to read/write (these are
the same as the parameters to read and write)
- int aio_fildes
- volatile void *aio_buf
- size_t aio_nbytes
- a field (struct sigevent aio_sigevent) to
specify the signal number and handler used during the notification
of i/o completion
- aio_sigevent.sigev_notify
- if this variable contains SIGEV_NONE,
then the OS does not generate a signal when i/o
completes (use polling instead; see below)
- aio_sigevent.sigev_signo
- example: consider a program that
reads from a pipe and writes to an ordinary file
- may want to use asynchronous i/o for the pipe since
since it might block for a long time
- may want to use regular i/o (with blocking) for the write to the file
- see asynsignalmain.c ([USP] Program 8.13) and
asyncmonitorsignal.c ([USP] Program 8.14)
- another example (courtesy [USP] §8.10, pp. 299-300):
reading from a disk file and writing to a slow device
- main calls aio_read
- read signal handler calls aio_write
- write signal handler calls aio_read
- can we do asynchronous i/o without signals?
- sure, use what is called polling
- break up other work into small pieces
- call aio_error after each piece
to check if the i/o operation completed
- what should we do if the i/o is
still not finished, yet we have no more work to do?
- there are several options (see bottom of [USP] p. 297)
- involving functions like select, pause,
sigsuspend, and sigwait
- use aio_suspend
Introduction to POSIX Times
- Epoch: 00:00 (midnight), January 1, 1970,
Coordinated Universal Time
- also called UTC, Greenwich Mean Time or GMT
- time: returns time (in seconds) since Epoch
- difftime
- other functions for manipulating times
- localtime
- asctime
- e.g., asctime (localtime (time (NULL))
- ctime
- e.g., ctime (time (NULL))
- same as asctime (localtime (time (NULL))
- be careful, ctime uses static storage to hold the string
struct tm
References
[USP] K. A. Robbins and S. Robbins. UNIX Systems Programming: Concurrency,
Communication, and Threads. Prentice Hall, 2003