Lecture13.Pdf

Lecture13.Pdf

3/1/2011 Overview Real-time Systems D0003E • Posix signals Lecture 13: • Posix timers More on inter-process communication • timers in cygwin (lab environment) (Burns & Wellings ch. 8, 11 & 10.6) • event-loop pattern • semaphores POSIX signals Generation of signals A signal can be sent to a process by executing A group of threads executing in a protected virtual address space forms the POSIX notion of a process kill(pid, sig); where pid is process number (0 means self) A process can thus be though of as a virtual computer The POSIX signal concept is analogous to a virtual ... or by interrupt to such a virtual computer dividing by zero (equals kill(0, SIGFPE); ) Signals predate threads and shared memory addressing outside your address space ( SIGSEGV ) communication in Unix, although they are now etc... standardized by POSIX This actually mimics the interrupt sources on most The default handling of most signals is to kill the real architectures: receiving process, but user-defined handler can be •external hardware signals installed to override this behavior •internal hardware misuse Some predefined signals Handling signals •SIGINT "interrupt" (Control-C) To install a handler for signal X: #include <signal.h> •SIGILL illegal instruction (internal) •SIGKILL kill process (can't be ignored) void handler(int signo) { /* Your signal handling code here */ •SIGALRM timer alarm } •SIGCHLD child process terminated •SIGTSTP terminal stop (Control-Z) struct sigaction act; act.sa_handler = handler; // your handler function •SIGUSR1 .. SIGUSR2 act.sa_flags = 0; // extras, normally 0 • user defined sigemptyset( &act.sa_mask ); // signals to block while running handler •SIGRTMIN .. SIGRTMAX sigaction ( X, &act, NULL ); • user defined (with extra data payload) 1 3/1/2011 Masking a signal Synchronizing with signals To wait for the handling of a signal: To temporarily mask (disable) signal handling: sigset_t ignore; // signals to ignore sigset_t sigs; sigemptyset(&sigs); sigemptyset( &ignore ); sigaddset( &sigs, SIGINT ); sigaddset( &ignore, SIGINT ); sigprocmask ( SIG_BLOCK, &sigs, NULL ); sigsuspend ( &ignore ); // return after handler has run once To unmask (enables handling of pending signals): sigprocmask ( SIG_UNBLOCK, &sigs, NULL ); Note: sigsuspend stops execution until a signal not mentioned in the argument has arrived and the [C.f. the macros that enable or disable interrupts for corresponding handler has run, just as if it were various devices on the AVR] implemented as a busy-wait loop Alternatively POSIX timers To wait for a signal that doesn't have a handler: OS abstraction built on top of the system ticks sigset_t accept; signalled by the clock hardware int received; sigemptyset( &accept ); To create a new timer abstraction: sigaddset( &accept, SIGALRM ); #include <time.h> sigaddset( &accept, ... ); timer_t tmr; How alarms should be delivered sigprocmask( SIG_BLOCK, &accept, NULL ); struct sigevent ev; — doesn’t have to be SIGALRM sigwait ( &accept, &received ); SIGEV_SIGNAL( &ev, signo ); timer_create ( CLOCK_REALTIME, &ev, &tmr ); That is, sigwait stops execution until one of the signals in These commands amount to "buying" a new alarm its first argument has arrived. Note that these signals clock, aligning it with real time, and configuring it must be blocked when sigwait is called (so that a handler with a certain alarm signal won’t interfere) Setting the alarm time More timer settings A timer is armed by supplying a single alarm time and To set a timer to ring just once, set the it_interval to 0 an optional repetition period spec.it_value.tv_sec = 1; The alarm time can be relative (to the time of the spec.it_value.tv_nsec = 0; call), or absolute spec.it_interval.tv_sec = 0; To set a timer to ring in one second, and thereafter spec.it_interval.tv_nsec = 0; every 50 milliseconds, write timer_settime ( tmr, 0, &spec, NULL ); struct itimerspec spec; To temporarily disable a timer, set the it_value to 0 spec.it_value.tv_sec = 1; spec.it_value.tv_sec = 0; spec.it_value.tv_nsec = 0; spec.it_value.tv_nsec = 0; spec.it_interval.tv_sec = 0; spec.it_interval.tv_sec = 0; spec.it_interval.tv_nsec = 50000000; spec.it_interval.tv_nsec = 50000000; timer_settime ( tmr, 0, &spec, NULL ); timer_settime ( tmr, 0, &spec, NULL ); 2 3/1/2011 A cyclic POSIX thread C.f. the periodic reactive object void *proc (void *arg) { int m( Class *self, int arg ) { timer_t tmr; // do periodic action sigset_t accept; AFTER( MILLISEC(500), self, m, exp ); struct sigevent ev; } int sig_received; struct itimerspec spec = {{0,50000000}, {0,50000000}}; SIGEV_SIGNAL( &ev, SIGALRM ); Apart from the obvious differences in size, there’s another, timer_create ( CLOCK_REALTIME, &ev, &tmr ); more fundamental, difference in structure as well: timer_settime ( tmr, 0, &spec, NULL ); N.B.: signals are global within a sigemptyset( &accept ); Reactive POSIX process, and not tied to a etc. sigaddset( &accept, SIGALRM ); object: m m m specific thread. This means that sigprocmask ( SIG_BLOCK, &accept, NULL ); for this example to work, no while (1) { other thread should use this sigwait ( &sigset, &sig_received ); POSIX etc. signal (SIGALRM) for any other // do... sigwait // do... sigwait // do... sigwait // do periodic action purpose thread: } } Cygwin timers A cyclic POSIX thread (2) void *fun( void *arg ) { sigset_t accept; As it happens, Cygwin – the PC side lab programming Like an itimerspec, but units are struct itimerval x; environment – doesn’t support timer_create() and seconds and micro seconds x.it_value.tv_sec = 0; timer_settime() (so much for POSIX compatibility!) x.it_value.tv_usec = 1000; Instead, a predefined interval timer for each process x.it_interval.tv_sec = 0; is offered, in the older style of BSD Unix x.it_interval.tv_usec = 1000; setitimer ( ITIMER_REAL, &x, NULL); This timer always generates the signal SIGALRM , Older name for sigemptyset( &accept ); CLOCK_REALTIME and is configured via the system call setitimer() sigaddset( &accept, SIGALRM ); [ Actually, one such interval timer can be configured for each sigprocmask ( SIG_BLOCK, &accept, NULL ); thread, but since they all use SIGALRM for output, using multiple while (1) { interval timers in a process is a little tricky and not recommended int sig_received; ] sigwait ( &accept, &sig_received ); // do periodic action } } Handling multiple events The event-loop pattern int m( Class *self, int arg ) { int m2( Class *self, int x ) { A standard pattern for encoding reactions in terms of a // do periodic action // update self continuous (POSIX) thread: AFTER( MILLISEC(500), self, m, exp ); } } void *fun( void *arg ) { Indefinite length INITIALIZE; while (1) { Reactive etc. PARK; PAR m m m2 m INITIALIZE REACT object: REACT; K } } POSIX etc. thread: // do... sigwait // do... sigwait ? // do... sigwait The “parking” operation is at the core of this pattern – it causes the thread to stop execution indefinitely How do we tell a POSIX thread to wait for a timer signal Implicit side-condition: neither INITIALIZE nor REACT and be prepared to update its state at the same time? must call any parking operation 3 3/1/2011 Parking operations (def) The multi-event-loop pattern Ideally we would like a parking operation that waits for In principle : any operation implemented by busy-waiting exactly those events a thread is interested in: on an external state change void *fun( void *arg ) { In practice : an operation provided by the underlying INITIALIZE; while (1) { PAR INITIALIZE REACT0 operating system that behaves as if it were implemented x = PARK; K by busy-waiting on an external state change switch (x) { case 0: REACT0; break; REACT1 Core questions regarding a parking op: what events does case 1: REACT1; break; it wait for? Just one? Many? Is it extensible? ... ... case n: REACTn; break; REACTn Example: sigwait waits for a defineable set of POSIX } signals (but not for keyboard entry, for example) to analogous thread A object! reactive a } } Example: getchar waits for data from one input source only (the keyboard), but not for any signals Unfortunately, a truly generic parking op doesn’t exist... POSIX select() Semaphores A way to wait for input on multiple files (keyboard, pipes, network sockets, etc) simultaneously Original process synchronization device (due to Dijkstra 1965) Returns info on which file descriptor data arrived first Supports two operations: wait and signal (signal is called Also supports an optional timeout value, equivalent to a post in POSIX) multiple wait that includes a delay wait: if value >0: decrease; if =0: block! Syntax: Sets of files that signal: increase value have pending The general semaphore is counting ; i.e., it remembers can be read can be written exceptions number of bits in sets the number of signal calls, and allows the same number of wait calls to succeed without stopping int select( int nfds, fd_set *r, fd_set *w, fd_set *e, A counting semaphore must be initialized with its struct timeval *t ) optional timeout starting value (the number of initially allowed wait calls) number of ready descriptors Note: select still doesn’t wait for signals or internal events Semaphore vs. mutex A semaphore Bounded Buffer #include <semaphore.h> sem_t mut; sem_t space, items; int head = 0, tail = 0; T buf[SIZE]; ... Notice the A mutex is a semaphore that is sem_init ( &mut, 0, 1 ); lock/unlock • sem_init ( &items, 0, 0 ); pattern binary (only distinguishes between the values 0 and 1) sem_init ( &space, 0, SIZE ); • automatically initialized to 1 • restricted so that signal/post can only be called

View Full Text

Details

  • File Type
    pdf
  • Upload Time
    -
  • Content Languages
    English
  • Upload User
    Anonymous/Not logged-in
  • File Pages
    5 Page
  • File Size
    -

Download

Channel Download Status
Express Download Enable

Copyright

We respect the copyrights and intellectual property rights of all users. All uploaded documents are either original works of the uploader or authorized works of the rightful owners.

  • Not to be reproduced or distributed without explicit permission.
  • Not used for commercial purposes outside of approved use cases.
  • Not used to infringe on the rights of the original creators.
  • If you believe any content infringes your copyright, please contact us immediately.

Support

For help with questions, suggestions, or problems, please contact us