Inter Process Communication – Signals

Inter Process Communication – Signals

INTRODUCTION

In the realm of Inter Process Communication (IPC), signals serve as a fundamental mechanism for delivering asynchronous notifications to processes. A signal is essentially a software interrupt sent to a process to inform it of an event such as a segmentation fault, termination request, or an external interrupt. Signals play a crucial role in UNIX and Linux systems, allowing the kernel, user, or even other processes to influence a program’s behavior at runtime. By default, each signal has a predefined action, but developers can intercept and customize the response using signal handling mechanisms. This ability to override or ignore signal behavior (except for a few critical ones like SIGKILL and SIGSTOP) provides greater control over process execution. In this context, system calls such as signal() and sigaction() are used to define how a process should react when it receives specific signals, offering both basic and advanced capabilities for managing these asynchronous events.

  1. A signal is a notification to a process indicating the occurrence of an event. It is also called a software interrupt and is not predictable, making it an asynchronous event.
  2. A signal can be specified with a number or a name, typically starting with SIG. The available signals can be listed using the command kill -l.

Inter Process Communication – Signals

Whenever a signal is raised (either programmatically or by the system), a default action is performed. But what if you don’t want to perform the default action and instead want to perform your own actions upon receiving the signal? Yes, it is possible to handle the signal, but not for all signals. What if you want to ignore the signal? Yes, it is possible to ignore the signal, which means neither performing the default action nor handling the signal. It is possible to ignore or handle almost all signals, except for SIGSTOP and SIGKILL, which cannot be ignored or handled.

In summary, the actions performed for the signals are as follows –

  • Default Action:
    When a signal is raised, the operating system performs a predefined action associated with the signal.
  • Handle the Signal:
    You can define custom behavior when a signal is received, overriding the default action. This is possible for most signals.
  • Ignore the Signal:
    It is possible to ignore a signal, meaning neither the default action is performed nor any custom handling occurs. Most signals can be ignored, except for SIGSTOPand SIGKILL.

As discussed the signal can be handled altering the execution of default action. Signal handling can be done in either of the two ways i.e., through system calls, signal() and sigaction().

#include 

typedef void (*sighandler_t)(int);

 sighandler_tsignal(int signum, sighandler_t handler);

  1. The system call signal()registers a signal handler that is called when the signal, specified by signum, is generated. The handler can be one of the following:
    • SIG_IGN: To ignore the signal.
    • SIG_DFL: To restore the default action for the signal.
    • User-defined handler: A function or address defined by the user to handle the signal.
  2. On success, the signal()system call returns the address of a function that takes an integer argument and has no return value. If there is an error, it returns SIG_ERR.
  3. While signal()allows you to register a handler for signals, it doesn’t provide advanced functionalities like masking signals to block them, modifying signal behavior, or other fine-tuning options. These features can be achieved using the sigaction() system call.

#include 

int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact)

This system call is used to either examine or change a signal action. If the act is not null, the new action for signal signum is installed from the act. If oldact is not null, the previous action is saved in oldact.

The sigaction structure contains the following fields –

Field 1: Handler – This specifies the signal handler, which is either defined in sa_handler (for simpler signal handling) or sa_sigaction (for more advanced signal handling with additional information about the signal).

void (*sa_handler)(int);

void (*sa_sigaction)(int, siginfo_t *, void *);

  • Handler for sa_handler:
    The sa_handlerspecifies the action to be performed based on the signal number (signum). It can be one of the following:
    • SIG_DFL: Default action for the signal.
    • SIG_IGN: Ignore the signal.
    • Pointer to a custom signal handling function.
  • Handler for sa_sigaction:
    The sa_sigactionspecifies a more detailed handler. It takes three arguments:
    • signal number: First argument.
    • siginfo_t structure: Second argument, providing detailed signal information.
    • user context: Third argument, a pointer to user context (as returned by getcontext()or setcontext()).

The siginfo_t structure contains information like:

  • Signal number.
  • Signal value.
  • Process ID of the sending process.
  • Real user ID of the sending process, etc.
  • Field 2 – Set of signals to be blocked:
    • int sa_mask: Specifies the set of signals that should be blocked during the execution of the signal handler.
  • Field 3 – Special flags:
    • int sa_flags: A set of flags that modify the behavior of the signal handling.
  • Field 4 – Restore handler:
  • void (*sa_restorer) (void): This field is used for restoring the previous signal handler after the execution of the custom handler.

For a comparison between signal-based IPC and other methods like sockets, read this overview on Linux IPC.

New IoT Internship with Project Batch Starts on 19th May!
Seats are filling fast — don’t miss your chance to join!

✅ Work on real-time IoT projects
✅ Gain hands-on experience

📞 For more details & registration, contact us now!

Contact no:9886920008

Limited seats available — Hurry!