Embry-Riddle Real-Time Laboratory Experiment
Experiment #8
Signals
Introduction
A signal is a software notification to a task or a process of an event. A
signal is generated when the event that causes the signal occurs. A signal is
delivered when a task or a process takes action based on that signal.
The lifetime of a signal is the interval between its generation and its
delivery. A signal that has been generated but not yet delivered is
pending. There may be considerable time between signal generation and
signal delivery.
VxWorks supports a software signal facility. The signals asynchronously alter
the control flow of task. Any task can raise a signal for a particular task.
The task being signaled immediately suspends its current thread of execution
and the task specified signal handler routine is executed the next time the
task is scheduled to run. The signal handler gets invoked even if the task is
blocked on some action or event. The signal handler is a user supplied routine
that is bound to a specific signal and performs whatever actions are necessary
whenever the signal is received. Signals are most appropriate for error and
exception handling, rather than general intertask communication.
The Wind kernel has both BSD 4.3 and POSIX signal interface. The POSIX
interface provides a standardized interface which is more functional than BSD 4.3
interface. Your application should use only one interface and not mix the two.
Objectives
The following are the primary objectives of this experiment:
- To demonstrate VxWorks' implementation of POSIX signal routines.
Description
The signal facility provides a set of 31 distinct signals(see VxWorks Manual).
A signal can be raised by calling kill(), which is analogous to
an interrupt or hardware exception. A signal is bound to a particular signal
with sigaction(). While the signal handler is running, other
signals are blocked from delivery. Tasks can block the occurence of certain
signals with sigprocmask(); if a signal is blocked when it is
raised, its handler routine will be called when the signal becomes unblocked.
Signal handlers are typically defined as:
void sigHandlerFunction(int signalNumber)
{
.............. /* signal handler code */
..............
..............
}
where signalNumber is the signal number for which sigHandlerFunction is
to be invoked for.
The sigaction function installs signal handlers for a task:
- int sigaction(int signo, const struct sigaction *pAct, struct sigaction *pOact)
A data structure of type struct sigaction holds the handler information. The sigaction
call has three parameters: the signal number to be caught, a pointer to the new
handler structure(of type struct sigaction), and a pointer to the old
structure(also of type struct sigaction). If the program does not need
the value of the old handler(*pOact), pass a NULL pointer for *pOact.
To direct a specific signal to a specific task, the kill(int, int) call is
made where the first argument the task id to send signal to, and the second argument
is the signal to send to the task .
1. Example:
In the example below, the "sigGenerator" function generates the SIGINT or Ctrl-C
signal, and directs the signal to the "sigCatcher" task. When "sigCatcher" receives
the signal, it suspends its normal execution and branches to a signal hander that
it has installed(catchSIGINT function).
------------------------------------------------------------------------------------
/* includes */
#include "vxWorks.h"
#include "sigLib.h"
#include "taskLib.h"
#include "stdio.h"
/* function prototypes */
void catchSIGINT(int);
void sigCatcher(void);
/* globals */
#define NO_OPTIONS 0
#define ITER1 100
#define LONG_TIME 1000000
#define HIGHPRIORITY 100
#define LOWPRIORITY 101
int ownId;
void sigGenerator(void) /* task to generate the SIGINT signal */
{
int i, j, taskId;
STATUS taskAlive;
if((taskId = taskSpawn("signal",100,0x100,20000,(FUNCPTR)sigCatcher,0,0,0,0,0,0,0,
0,0,0)) == ERROR)
printf("taskSpawn sigCatcher failed\n");
ownId = taskIdSelf(); /* get sigGenerator's task id */
taskDelay(30); /* allow time to get sigCatcher to run */
for (i=0; i < ITER1; i++)
{
if ((taskAlive = taskIdVerify(taskId)) == OK)
{
printf("+++++++++++++++++++++++++++++++SIGINT sinal generated\n");
kill(taskId, SIGINT); /* generate signal */
/* lower sigGenerator priority to allow sigCatcher to run */
taskPrioritySet(ownId,LOWPRIORITY);
}
else /* sigCatcher is dead */
break;
}
printf("\n***************sigGenerator Exited***************\n");
}
void sigCatcher(void) /* task to handle the SIGINT signal */
{
struct sigaction newAction;
int i, j;
newAction.sa_handler = catchSIGINT; /* set the new handler */
sigemptyset(&newAction.sa_mask); /* no other signals blocked */
newAction.sa_flags = NO_OPTIONS; /* no special options */
if(sigaction(SIGINT, &newAction, NULL) == -1)
printf("Could not install signal handler\n");
for (i=0; i < ITER1; i++)
{
for (j=0; j < LONG_TIME; j++);
printf("Normal processing in sigCatcher\n");
}
printf("\n+++++++++++++++sigCatcher Exited+++++++++++++++\n");
}
void catchSIGINT(int signal) /* signal handler code */
{
printf("-------------------------------SIGINT signal caught\n");
/* increase sigGenerator priority to allow sigGenerator to run */
taskPrioritySet(ownId,HIGHPRIORITY);
}
------------------------------------------------------------------------------------
Procedures
1. Copy the source code in the example and compile it.
2. Load the object file onto the target machine.
3. Run the examples by executing the main routine("sigGenerator") of the
example on WindSh terminal.
Note: Make sure you have redirected I/O, otherwise you won't see the results
of the printf commands.
Follow On Experiment
Experiment 1. Modify the program above so that there is no signal handler associated
with "sigCatcher." What happens when the SIGINT signal is now delivered to "sigCatcher?"
Experiment 2. Modify the program above so that the SIGINT signal is blocked(i.e.
"sigCatcher" is prevented from receiving the SIGINT signal).
Additional Information
Refer to VxWorks User's Manual and Reference Manual.
Last Updated: 4 April 1997
Created by: Dan Eyassu
eyassud@db.erau.edu