Sunday, July 10, 2011

Signal

A signal is a limited form of inter-process communication used in Unix, Unix-like, and other POSIX-compliant operating systems. Essentially it is an asynchronous notification sent to a process in order to notify it of an event that occurred. When a signal is sent to a process, the operating system interrupts the process's normal flow of execution. Execution can be interrupted during any non-atomic instruction. If the process has previously registered a signal handler, that routine is executed. Otherwise the default signal handler is executed.

Definition:
Signals are software interrupts, providing a means to handle asynchronous events.



Signal Categories

Signals can be classified into 5 categories.

• Process control. 
SIGHUP: hang-up, usually sent by the parent process to child   processes when terminating.
SIGKILL: kill (cannot be caught of ignored)
SIGTERM: Software termination signal from kill
SIGABRT: Process abort signal

• Job control.
SIGCHLD: Child process has stopped or terminated.
SIGSTOP: Stop signal (cannot be caught or ignored)
SIGTSTP: Interactive stop signal.
SIGCONT: Continue if stopped.
SIGTTIN: Read from control terminal attempted by a member of a background process group.
SIGTTOU Write to control terminal attempted by a member of a background process group.

• Environment change.
SIGWINCH: indicates window size change.

• Hardware exception.
SIGINT: Interrupt, generated by Ctrl-C
SIGQUIT: quit, generated by Ctrl-\ Ctrl-break
SIGILL: Illegal instruction (not reset when caught)
SIGTRAP: trace trap (not reset when caught)
SIGIOT: IOT instruction
SIGEMT: EMT instruction
SIGFPE: Floating point exception
SIGBUS: bus error
SIGPWR: power state indication
SIGIO asynchronous I/O
SIGURG urgent condition on IO channel

• Software condition.
SIGSYS: bad argument to system call
SIGPIPE: write on a pipe with no one to read it
SIGALRM: alarm clock
SIGSEGV: Segmentation violation
SIGVTALRM: virtual timer alarm
SIGPROF: profiling timer alarm

Signal Properties

Persistence
Process-persistent.

Name space
PID and signal numbers.

Permission
Processes of the same group can send each other signals. Superuser (root) can send signal to all processes.

Latency
A few hundred micro-seconds on general-purpose Unix (e.g. HP-UX, Linux) or a few micro-seconds on a RTOS (3.3 us on Pentium-166, QNX).

Limitations
A limited number of signals (normally 32). Two of them can be defined by users.

ANSI C signal()

ANSI C defines the simplest signal handling function.

#include <signal.h>
void (*signal(int sig, void (*func)(int)))(int);

signal() instantiates a signal handler for the given signal and returns the signal handler
instantiated earlier.

Example
static void signalHandler(int); /* signal handler function */
signal(SIGHUP, &signalHandler); /* instantiate signal handler */

Macros SIG_ERR, SIG_DFL and SIG_IGN.
signal(sig, SIG_DFL); /* reset to default signal handler. */
signal(sig, SIG_IGN); /* ignore the signal. */

This is normally sufficient for basic signal handling.


int receivedSignal_g = 0;
int receivedSignalNo_g = 0;
static void signalHandler(int);
int main(int argc, char* argv[])
{
     signal(SIGHUP, &signalHandler);
     while (receivedSignalNo_g != SIGTERM) {
     if (receivedSignal_g) {
           printf("Received signal: %d\n", receivedSignalNo_g);
           receivedSignal_g = 0; receivedSignalNo_g = 0;
     }
     sleep(60);
     }
}
static void signalHandler(int signalNumber) {
     signal(signalNumber, signalHandler); /* re-establish the  signal handler. */
     receivedSignal_g = 1;
     receivedSignalNo_g = signalNumber;
}


Related System Calls
 
//Sending a signal
#include <signal.h>
int raise(int sig); /* send a signal to itself */
int kill(pid_t pid, int sig); /* send a signal to process PID */
 
kill() can be used to determine whether a process has terminated.
kill(aPid, 0);
 
If kill() returns -1 and errno is set to ESRCH, the aPid process is no longer around.
 
System call abort() is implemented with raise(SIGABRT), sending SIGABRT to itself.
//Waiting for a signal
#include <unistd.h>
unsigned int alarm(unsigned int seconds);
int pause(void);

System call sleep() is implemented with alarm() and pause().

System Commands

kill() - sends a signal to a process, or by default, terminates a process.
 
kill [-s signame] pid ...
kill [-s signum] pid ...
kill -l // list all signal values.

Obsolescent Versions:
kill -signame pid ...
kill -signum pid ...

Sample Signal C code
/*
 * signal.c, communication between
 * child and parent processes using kill() and signal().
 * fork() creates the child process from the parent. The pid can be checked to decide
 * whether it is the child (== 0) * or the parent (pid = child process id).
 * The parent can then send messages to child using the pid and kill().
 * The child picks up these signals with signal() and calls appropriate functions.
 * An example of communicating process using signals is signal.c:
 * signal.c --- Example of how 2 processes can talk
 * to each other using kill() and signal()
 * We will fork() 2 process and let the parent send a few
 * signals to it`s child
 * gcc signal.c -o signal
 */

#include <stdio.h>
#include <signal.h>

void sighup(); /* routines child will call upon sigtrap */
void sigint();
void sigquit();

void main() {
    int pid;
    /*
     * get child process
     */
     if ((pid = fork()) < 0) {
        perror("fork");
        exit(1);
    }
   
    if (pid == 0) { /* child */
        signal(SIGHUP,sighup); /* set function calls */
        signal(SIGINT,sigint);
        signal(SIGQUIT, sigquit);
        for(;;); /* loop for ever */
    } else { /* parent */
    /*
     * pid hold id of child
     */
        printf("\nPARENT: sending SIGHUP\n\n");
        kill(pid,SIGHUP);
        sleep(3); /* pause for 3 secs */
        printf("\nPARENT: sending SIGINT\n\n");
        kill(pid,SIGINT);
        sleep(3); /* pause for 3 secs */
        printf("\nPARENT: sending SIGQUIT\n\n");
        kill(pid,SIGQUIT);
        sleep(3);
    }
}

void sighup(){ 
   signal(SIGHUP,sighup); /* reset signal */
   printf("CHILD: I have received a SIGHUP\n");
}

void sigint() {
    signal(SIGINT,sigint); /* reset signal */
    printf("CHILD: I have received a SIGINT\n");
}

void sigquit() {
    printf("My DADDY has Killed me!!!\n");
    exit(0);
}

No comments:

Post a Comment