Another method of IPC is software signals. Signals are similar to hardware interrupts in that they are asynchronous; that is, a process receiving a signal does not have to be in a special mode, does not have to wait for it. Also like hardware interrupts, a process can install signal handlers to take special action when a signal arrives. Unlike hardware interrupts, signals are defined and handled entirely through software.
Signals are generally used to tell a process of some event that has occurred. Between the system-defined and user-defined signals, there is a lot of things you can do. GNO/ME currently defines 32 different signals. A list of signals and their codes can be found in signal(2) and the header file <gno/signal.h>.
There are three types of default actions that occur upon receipt of a signal. The process receiving the signal might be terminated, or stopped; or, the signal might be ignored. The default action of any signal can be changed by a process, with some exceptions. Not all of the defined signals are currently used by GNO/ME, as some are not applicable to the Apple IIgs, or represent UNIX features not yet implemented in GNO/ME . Here is a list of the signals that are used by GNO/ME.
As you can see, signals are used by many aspects of the system. For detailed information on what various signals mean, consult the appropriate electronic manual page — see tty(4), wait(2), and signal(2).
For an example of signal usage, consider a print spooler. A print spooler takes files that are put in the spool directory on a disk and sends the data in the files to a printer. There are generally two parts to a print spooler: The daemon, a process that resides in memory and performs the transfer of data to the printer in the background; and the spooler. There can be many different types of spoolers, say one for desktop printing, one for printing source code, etc. To communicate to the daemon that they have just placed a new file in the spool directory, the spoolers could send the daemon SIGUSR. The daemon will have a handler for SIGUSR, and that handler will locate the file and set things up so the print will begin. Note that the actual implementation of the print spooling system in GNO/ME, lpr(1) and lpd(8), is somewhat more complex and uses messages and ports instead of signals. However, an earlier version of the spooler software did use signals for communication.
Signals should not be sent from inside an interrupt handler, nor from inside a GS/OS or Toolbox call. Window Manager update routines are a prime example of code that should not send signals; they are executed as part of a tool call. The GS/OS aspect of this limitation is a little harder to come up against. GS/OS does maintain a software signal facility of it's own, used to notify programs when certain low-level events have occurred. Do not confuse these GS/OS signals with GNO/ME signals, and above all, don't send a GNO/ME signal from a GS/OS signal handler.
When a process receives a signal for which it has installed a handler, what occurs is similar to a context switch. The process' context is saved on the stack, and the context is set so that the signal handler routine will be executed. Since the old context is stored on the stack, the signal handler may if it wishes return to some other part of the program. It accomplishes this by setting the stack pointer to a value saved earlier in the program and jumping to the appropriate place. Jumps like this can be made with C's setjmp(3) and longjmp (3) functions. The following bit of code demonstrates this ability.
void sighandler (int sig, int code) { printf("Got a signal!"); longjmp(jmp_buf); } void routine(void) { signal(SIGUSR, sighandler); if (setjmp(jmp_buf)) { printf("Finally done! Sorry for all that...\n"); } else { while(1) { printf("While I wait I will annoy you!\n"); } } }
This program basically prints an annoying message over and over until SIGUSR is received. At that point, the handler prints “Got a Signal!” and jumps back to the part of the if statement that prints an apology. If the signal handler hadn't made the longjmp, when the handler exited control would have returned to the exact place in the while loop that was interrupted.
Similar techniques can be applied in assembly language.
Feedback