TOC PREV NEXT INDEX

POSIX 1.b Migration Guide


Real-Time Signals

There are three basic types of signal functions available under LynxOS:

It is important to note that real-time signals may be thought of as an inter-process communication (IPC) tool. Real-time signals are only one possible IPC mechanism made available in POSIX.1b (e.g., messages, semaphores, and shared memory are also considered IPC mechanisms). Different IPC functions vary in functionality and performance.

Real-time signals are often not the best choice for IPC.

Normal Signals Versus Events

From one point of view, signals and events are slightly different user interfaces layered on top of the same underlying LynxOS support. In both cases, sigaction() notifies the operating system that the process is using a signal/event handler. A difference is that the signal handler and the event handler do not have the same calling sequence. The words "signal" and "event" are used almost interchangeably because the two interfaces are nearly identical.

There are a couple of key differences between events and signals. The default action for a signal is specified on the signal()man page. Most of the signals have already-defined names and functionality, such as SIGKILL and SIGCORE. Only a few user-defined signals are available. The events facility adds more "signals" to the list of possible signals, and all of these new signals are available for user-defined functions.

Events can also carry data; the event handler receives the event number and a small amount of data. The signal handler and event handler have different parameters. The main difference between Draft 9 and Draft 10 events is the handling function's calling sequence. Thus, signals, Draft 9 events, and Draft 10 events all have different-looking handlers.

Events are queued. Normal signals are not queued under LynxOS; the POSIX.1b standard does not define any particular queueing behavior for normal signals.

Events Versus Real-Time Signals

Events and real-time signals differ primarily in their default functionality. For Drafts 9 and 10, the default action for an event is for the process to ignore them. For POSIX.1b, the default action is to terminate the process.

Once again, the handler's calling sequence has changed. And as with all POSIX.1b functions, the functions and compile-time constants have new names. There are minor changes in the data structures, as well.

For real-time signals, users must call sigaction() to notify the operating system that a signal handler is being used. Events implementation requires a call to sigaction(); LynxOS users with applications coded under Drafts 9 and 10 already call sigaction().

Both events and real-time signals are queued in FIFO order, and are delivered in that order.

The sigaction Structure

In order to add real-time signal handling to the pre-existing POSIX.1 sigaction structure, a new flag, SA_SIGINFO, is defined by POSIX.1b. This flag is in the sa_flags member of the sigaction structure.

The SA_SIGINFO flag specifies the signal handler that is desired. If SA_SIGINFO is set, it is possible to pass a small amount of data to the signal handler (see signal handler synopses below). If SA_SIGINFO is not set, then the signal handler does not receive data.

A new member, sa_sigaction, has been added to the sigaction structure. At signal delivery time, the sa_sigaction member is called if the SA_SIGINFO flag is set in sa_flags, otherwise sa_handler is called.

sigaction Structure Contents

The sigaction POSIX.1 structure contains at least the following members:

void (*sa_handler)();
sigset_t sa_mask;
int sa_flags;

The sigaction POSIX.1b structure now contains at least the
following members:

void (*sa_sigaction)(); /* SA_SIGINFO set */
void (*sa_handler)(); /* SA_SIGINFO NOT set */
sigset_t sa_mask;
int sa_flags;
/* NEW: set SA_SIGINFO flag if */
/* you want signals to have the */
/* data queued and retrieved */

Note: LynxOS does not implement the Draft 9 and 10 specification for the event handler. Instead, users are required to call sigaction to set up the event handler. LynxOS customers with existing Drafts 9 and 10 applications need not add the sigaction call; it should be in the application where needed.

Note: The default functionality for LynxOS is Draft 10 events. To use Draft 9 events, the user needs to set the SA_D9EV flag in the sa_flags member of the sigaction structure. When the SA_D9EV flag is set, be sure to remove it when porting an application to POSIX.1b.

The Event Structure

The new name of the event structure is now sigevent. The fields are similar. In both cases, a signal's value is an application-defined value, which is passed to the signal-catching function at the time of signal delivery (allowing the signal to pass a small amount of data).

event Structure Contents

The Drafts 9 and 10 event structure must include at least the following members:

evt_class_t evt_class; /* signal number */
void *evt_value; /* signal value */
void *evt_handler (); /* signal handler; not used by LynxOS*/
evtset_t evt_classmask; /* signal handler; not used by LynxOS*/

Note: evt_handler and evt_classmask are not used by LynxOS; the user is required to call sigaction.

The sigevent POSIX.1b structure must include at least the following members:

int sigev_signo; /* signal number */
union sigval sigev_value; /* signal value */
int sigev_notify; /* notification type*/

The sigval union must contain at least the following members:

int sival_int; /* integer signal value */
void *sival_ptr; /* pointer signal value */

The sigval union allows the user more flexibility in using the value passed by the signal sending code, because it is guaranteed to be large enough for an integer or a pointer, whichever is larger. The Draft 9 and 10 event handlers do not allow an integer, if it happens to be larger than a pointer on a given implementation.

The values for the sigev_notify member in the sigval union above are
as follows:

SIGEV_NONE no signal will be sent

SIGEV_SIGNAL signal will be sent

This member has been added to the sigevent structure by POSIX.1b to allow different implementation-defined notification mechanisms.

Note: If the value in this field is not set to SIGEV_SIGNAL, the process does not receive a signal.

signal and event Handler Synopses

For reference, the following POSIX versions have the signal and event handler calling sequences listed below:

signal_handler(int signo);
event_handler(void *sigdata, int signo);
event_handler(int signo, void *sigdata);

(Please note the reversal of the signo and sigdata arguments.)

- If SA_SIGINFO is not set in sa_flags
signal_handler(int signo);
- If SA_SIGINFO is set in sa_flags
signal_handler(int signo, siginfo_t *info, void *context);

siginfo_t Structure

The siginfo_t structure must include at least these members:

int si_signo; /* signal number */
int si_code; /* cause of signal */
union sigval si_value; /* signal value */

For both events and real-time signals, it is possible to pass a small amount of data along with the signal to the handler.

For Drafts 9 and 10, the data was put into the event structure as void *evt_value and received by the event handler as void *sigdata.

In POSIX.1b, the data is put into the sigevent structure as sigev_value. This value is received by the signal handler via the new siginfo_t structure.

The sigaction flag SA_SIGINFO must be set to access the data, because the signal handler used if SA_SIGINFO is not set, does not include siginfo_t.

Additionally, si_signo has the same value as the first argument, signo, in the signal_handler structure does.

siginfo_t.si_code  
Value
Meaning
SI_USER
Due to kill() function
SI_QUEUE
Due to sigqueue() function
SI_TIMER
Due to timer expiration
SI_ASYNCIO
Due to completion of asynchronous I/O
SI_MESGQ
Due to arrival of message on an empty message queue

The signal handler parameter, context, is not used in the
LynxOS implementation.

- The signal number must be in the range of SIGRTMIN through SIGRTMAX.
- A real-time signal is sent.

Queued data is passed to the signal handler if the cause of the signal (passed in si_code) is due to one of any of the following members being called: SI_QUEUE, SI_TIMER, SI_ASYNCIO, or SI_MESGQ.

The signal handler is the function specified in sa_sigaction.

The signal handler calling sequence is as follows:

signal_handler(int signo, siginfo_t *info, void *context);
- A normal style signal is sent
- No data is passed to the signal handler.
- The signal handler is the function specified in sa_handler

The signal handler calling sequence is as follows:

signal_handler(int signo);

Note: If sigqueue() is called to send a signal that is not within the range of SIGRTMIN to SIGRTMAX, the data is discarded, and the signal posts to the receiving process. If the signal is already pending, the process does not necessarily receive it more than once.

The events facility from Draft 9 (and Draft 10, which LynxOS also supports) is replaced by real-time signals in POSIX.1b. Draft 9 events and real-time signals are distinctly different. Real-time signals are integrated with user (non-real-time) signals. The primary distinction between Draft 9 events and real-time signals is the default behavior; events are ignored while real-time signals terminate the process.

Data Structures

The event structure from Drafts 9 and 10 is replaced by the sigevent structure in POSIX.1b with the following members:

sigevent Structure  
Type
Name
Description
int
sigev_signo
Signal number
union sigval
sigev_value
Signal value
int
sigev_notify
Notification type

The sigev_signo member specifies the signal to be generated. The sigev_value member is the application-defined value, which is passed to the signal-catching function at the time of signal delivery. This is a part of the siginfo_t structure in the signal-catching function, which is described
in the table entitled "siginfo_t".

sigval Union  
Type
Name
Description
int
sival_int
Integer signal value
void *
sival_ptr
Pointer signal value

Either an application-defined value of the type int or a pointer can be passed through the sigval union. The sigev_notify member can have either of two values: SIGEV_SIGNAL or SIGEV_NONE. SIGEV_SIGNAL queues a signal when the event occurs. SIGEV_NONE delivers no asynchronous notification when the event occurs.

For the sigaction structure defined by POSIX.1, a new flag, SA_SIGINFO, is defined by POSIX.1b for the sa_flags member. This flag must be used when setting up a handler to queue a real-time signal from POSIX.1b.

Also, under POSIX.1b, a new member, sa_sigaction, is defined for the sigaction structure. This new member must be used for the signal handler instead of sa_handler whenever the SA_SIGINFO flag is set.

sa_handler and sa_sigaction should not be set simultaneously.

The following table shows the various cases of the sa_flags members and the features associated with them; the SA_NOCLDSTOP flag does not affect the flags in this table.

sa_sigaction.sa_flags  
Flag
Feature
None (with a valid POSIX.1 signal value)
POSIX.1 signal
SA_D9EV set
Draft 9 event
None (with signal number between EVTCLASS_MIN and EVTCLASS_MAX)
Draft 10 event
SA_SIGINFO
POSIX.1b real-time signal

POSIX.1b defines another structure, siginfo_t, which is used to contain code that identifies the cause of a signal. The address of this structure is used as an argument to the signal-catching function.

siginfo_t  
Type
Name
Description
int
si_signo
Signal number
int
si_code
Cause of signal
union sigval
si_value
Signal value

The si_signo member contains the signal number. It is the same as the signal number argument of the signal-catching function. The si_code member encodes the cause of the signal.

The si_value member is the same as the application-specified signal value when the si_code member is one of SI_QUEUE, SI_TIMER, SI_ASYNCIO, or SI_MESGQ; see the table entitled "siginfo_t.si_code".

Signal Handlers

The signal handler synopsis for POSIX.1b is different from what it was in Draft 9.

Signal Handlers  
Draft
Handler Synopses
Draft 9
event_handler(void *sigdata, int signo)
Draft 10
event_handler(int signo, void *sigdata)
POSIX.1b
signal_handler(int signo)
if SA_SIGINFO not set in sa_flags for signo
signal_handler(int signo, siginfo_t *info, void *context)
if SA_SIGINFO set in sa_flags for signo

POSIX.1b Signal Handlers
Argument
Meaning
int signo
Signal number of the signal being delivered
siginfo_t *info
Pointer to a siginfo_t structure that encodes the signal number, the cause of the signal, and an application-specified signal value. This data structure is
explained above.
void *context
Unused in the LynxOS implementation

Use of the sigqueue Function

Under Drafts 9 and 10, there is no explicit mechanism to send an event to a process. Events were generated as a result of a timer expiration, completion of asynchronous I/O, etc.

LynxOS provides a proprietary ekill() function to explicitly send an event to a process. POSIX.1b provides a sigqueue() function to explicitly queue a real-time signal to a specific process.

The following program illustrates the use of this function and signal handlers from POSIX.1b; the use of the siginfo_t structure in the signal handler informs the process of the cause of the signal:

#include <signal.h>

void signal_handler(int signo, siginfo_t *info, void *context);

main()
{
struct sigaction sa;
union sigval sig_value;
:
sa.sa_sigaction = signal_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_SIGINFO;

/* SIGRTMIN is chosen more or less randomly,
but it's in the required range */
sigaction(SIGRTMIN, &sa, NULL);

sig_value.sival_int = 1000;
sigqueue(getpid(), SIGRTMIN, sig_value);
:
}

void signal_handler(signo, info, context)
int signo;
siginfo_t *info;
void *context;
{
:
printf("In signal handler!!\n");
printf("Signal number = %d\n", signo);
printf("Signal value (int) = %d\n",
info->si_value.sival_int);

switch(info->si_code) {
case SI_USER:
printf("Here due to a kill() function!\n");
break;
case SI_QUEUE:
printf("Here due to a sigqueue() function!\n");
break;
case SI_TIMER:
printf("Here due to a timer expiration!\n");
break;
case SI_ASYNCIO:
printf("Here due to completion of asynch I/O!\n");
break;
case SI_MESGQ:
printf("Here due to arrival of a message!\n");
break;
default:
printf("No idea why here!!\n");
}
:
}

Sending a Real-Time Signal to a Process

Drafts 9 and 10 provide an evtraise() function to generate an event for a process. This can be migrated to POSIX.1b with the sigqueue() function:

Draft 9 Code

#include <sys/events.h>

void event_handler(void *evt_value,
evt_class_t evt_class, evtset_t evt_mask);

main()
{
struct event ev;
:
ev.evt_handler = event_handler;
ev.evt_value = NULL;
ev.evt_class = EVTCLASS_MIN;
evtemptyset(&ev.evt_classmask);

evtraise(&ev);
:
}

void event_handler(evt_value, evt_class, evt_mask)
void *evt_value;
evt_class_t evt_class;
evtset_t evt_mask;
{
:
:
}

Equivalent POSIX.1b Code

#include <signal.h>

void signal_handler(int signo, siginfo_t *info,
void *context);

main()
{
struct sigaction sa;
union sigval value;
:
sa.sa_sigaction = signal_handler;
sa.sa_flags = SA_SIGINFO;
sigemptyset(&sa.sa_mask);

sigaction(SIGRTMIN, &sa, NULL);

value.sival_ptr = NULL;
sigqueue(getpid(), SIGRTMIN, value);
:
}

void signal_handler(signo, info, context)
int signo;
siginfo_t *info;
void *context;
{
:
:
}

Polling for a Real-Time Signal

The evtpoll() function from Drafts 9 and 10 is superseded by the sigwaitinfo() and sigtimedwait() functions. The following example illustrates a conversion of the evtpoll() facility to POSIX.1b:

Draft 9 Code

#include <sys/events.h>
#include <sys/timers.h>

main()
{
evtset_t set;
struct timespec timeout;
void *value;
evt_class_t class;
:
evtemptyset(&set);
evtaddset(&set, EVTCLASS_MIN);
evtaddset(&set, EVTCLASS_MAX);

timeout.tv_sec = 2;
timeout.tv_nsec = 0;

if (evtpoll(&set, &timeout, &value, &class) != -1) {
printf("Received event no. %d\n", *class);
printf("Pointer to value = %d\n",
(int *) *value);
}
:
evtpoll(&set, NULL, &value, &class);
printf("Received event no. %d\n", *class);
printf("Pointer to value = %d\n", (int *) *value);
:
}

Equivalent POSIX.1b Code

#include <signal.h>

main()
{
sigset_t set;
siginfo_t info;
struct timespec timeout;
:
sigemptyset(&set);
sigaddset(&set, SIGRTMIN);
sigaddset(&set, SIGRTMAX);

timeout.tv_sec = 2;
timeout.tv_nsec = 0;

if (sigtimedwait(&set, &info, &timeout) != -1) {
printf("Dequeued signal no. %d\n",\
info->si_signo);
printf("Pointer to value = %d\n",
(int *) *info->si_value.sival_ptr);
}
:
sigwaitinfo(&set, &info);
printf("Dequeued signal no. %d\n",\
info->si_signo);
printf("Pointer to value = %d\n",
(int *) *info->si_value.sival_ptr);
:
}

Equivalence for Other Draft 9 Event Functions

There is no equivalent to the evtsigclass() function from Drafts 9 and 10 in POSIX.1b because there is no longer a need for it. Most of the other event-related functions have no specific equivalents in POSIX.1b. However, their functionality is provided by the appropriate signal functions from POSIX.1; refer to "Changes from Draft 9 to POSIX.1b"," for more information, including differences between evtsuspend() of Drafts 9 and 10 and sigsuspend()
of POSIX.1.

Timers, Message Queues, and Asynchronous I/O

With Drafts 9 and 10, it is possible to send events after a timer has expired, and when asynchronous I/O is completed. In POSIX.1b, real-time signals can be sent to a process without explicitly queuing them with a sigqueue() call. This can happen when a timer expires (see Chapter 6, "Clocks and Timers" on page 57), a message arrives on an empty message queue (see Chapter 4, "Message Queues" on page 37), or asynchronous I/O completion (see Chapter 9, "Asynchronous I/O" on page 79).

To use POSIX.1b real-time signals, the sigevent structure must be used, and the handlers must be set up according to POSIX.1b specification. The sa_flags for the sigaction structure must be set to SA_SIGINFO, and the sigev_notify member for the sigevent structure must be set to SIGEV_SIGNAL.

Changes from Draft 9 to POSIX.1b

The final interface for real-time extended signals differs from the events facility in Draft 9 (and Draft 10, which LynxOS also supports) as follows:

Extended Signal Interface  
Drafts 9 & 10
POSIX.1b
Default action: Ignore the event
Default action: Terminate the process
<sys/events.h>
<signal.h>
EVTCLASS_MIN
SIGRTMIN
EVTCLASS_MAX
SIGRTMAX
struct event
struct sigevent
No Equivalent
struct siginfo_t
32 event values
RTSIG_MAX signals
No Equivalent
sigqueue()
evtraise()
sigqueue(getpid(),....)
evtpoll()
sigwaitinfo(),
sigtimedwait()
evtsigclass()
No Equivalent

The following are important points about POSIX.1b interface:

Data Structures

The event structure from Drafts 9 and 10 is replaced by one of the following sigevent POSIX.1b structures:

sigevent Structures
Type
Name
Description
int
sigev_signo
Signal number
union sigval
sigev_value
Signal value
int
sigev_notify
Notification type

The sigev_signo member specifies the signal to be generated. The sigev_value member is the application-defined value to be passed to the
signal-catching function at the time of signal delivery. This is a part of the siginfo_t structure in the signal-catching function detailed in the table "siginfo_t Structure".

sigval Union
Type
Name
Description
int
sival_int
Integer signal value
void *
sival_ptr
Pointer signal value

Either an application-defined value of type int or a pointer can be passed through the sigval union. The sigev_notify member can have either of two values: SIGEV_SIGNAL or SIGEV_NONE. SIGEV_SIGNAL queues a signal when the event occurs. SIGEV_NONE delivers no asynchronous notification when the event occurs.

For the sigaction structure (from POSIX.1), a new flag, SA_SIGINFO, is defined by POSIX.1b for the sa_flags member. This flag must be used when setting up a handler to queue a real-time signal from POSIX.1b.

Also, under POSIX.1b, a new member, sa_sigaction, is defined for the sigaction structure. This new member must be used for the signal handler instead of sa_handler whenever the SA_SIGINFO flag is set.

sa_handler and sa_sigaction should not be set simultaneously

sa_sigaction.sa_flags  
Flag
Feature
None (and signal no. with a valid value)
POSIX.1 signal
SA_D9EV set
Draft 9 event
None (and signal no. between EVTCLASS_MIN and EVTCLASS_MAX)
Draft 10 event
SA_SIGINFO
POSIX.1b real-time signal

The table above does not consider the SA_NOCLDSTOP flag. It may or may not be set; but that does not affect this table.

Under POSIX.1b siginfo_t (a new structure) contains the code identifying the cause of the signal. The address of this structure is used as an argument to the signal-catching function.

siginfo_t Structure  
Type
Name
Description
int
si_signo
Signal number
int
si_code
Cause of signal
union sigval
si_value
Signal value

The si_signo member contains the signal number. It is the same as the signal number argument of the signal-catching function. The si_code member encodes the cause of the signal.

siginfo_t.si_code  
Value
Meaning
SI_USER
Due to kill() function
SI_QUEUE
Due to sigqueue() function
SI_TIMER
Due to timer expiration
SI_ASYNCIO
Due to completion of asynchronous I/O
SI_MESGQ
Due to arrival of message on an empty message queue

The si_value member is the same as the application-specified signal value, when the si_code member is one of SI_QUEUE, SI_TIMER, SI_ASYNCIO,
or SI_MESGQ.

Note: The signal handler synopsis for POSIX.1b is different than Draft 9. LynxOS supports Draft 10 event handlers by default.

Signal Handlers  
Draft
Handler Synopses
Draft 9
event_handler(void *sigdata, int signo)
Draft 10
event_handler(int signo, void *sigdata)
POSIX.1b
signal_handler(int signo)
if SA_SIGINFO not set in sa_flags for signo. This is the same as POSIX.1 signal handler
signal_handler(int signo, siginfo_t *info, void *context)
if SA_SIGINFO set in sa_flags for signo

POSIX.1b Signal Handlers  
Arguments
POSIX.1b Meanings
int signo
Signal number of the signal being delivered
siginfo_t *info
Pointer to a siginfo_t structure that encodes the signal number, cause of the signal and an application-specified signal value
void *context
Unused in the LynxOS implementation

Indefinite/Timed Wait

In Drafts 9 and 10 one function, evtpoll(), waits for events with and without a timeout. POSIX.1b provides a separate interface for these two operations - sigwaitinfo() and sigtimedwait().

Ability to Send Arbitrary Data

The sigevent structure from POSIX.1b contains a sigev_value entry, which is a union. With this entry, it is possible to send either an integer value or a pointer to arbitrary data along with the signal.

Drafts 9 and 10 Event Functions

Functions evtemptyset(), evtfillset(), evtaddset(), evtdelset(), evtismember(), evtprocmask(), evtsuspend(), evtsetjmp(), and evtlongjmp() have no equivalents in POSIX.1b. The POSIX.1 signal functions (sigemptyset(), sigfillset(), etc.) provide corresponding functionality. However, there are slight differences. Drafts 9 and 10 evtsuspend() takes two arguments. The second argument is a timespec structure, which allows a timed wait. The POSIX.1 sigsuspend() takes only one argument; a timed wait is not possible. The effect of an evtsuspend() with a timed wait can be simulated with the new sigtimedwait() function from POSIX.1b. However, this is not a true equivalence. It is not possible to invoke a signal handler with sigtimedwait(); it can only return values.

Interoperability

Events and real-time signals are not inter-operable between Drafts 9, 10, and POSIX.1b. Users should not try to catch a Draft 9 or 10 event with a signal handler from POSIX.1b, or vice versa. The effects of such behavior are undefined.



LynuxWorks, Inc.
855 Branham Lane East
San Jose, CA 95138
http://www.lynuxworks.com
1.800.255.5969
TOC PREV NEXT INDEX