The Raspberrypi is a board actually designed for helping computer education for remote schools but it is a good platform for programmers especially beginners to explore various coding techniques. Linux operating systems especially Ubuntu is preferred for all kind of programming and development. The Raspberrypi is a mini-computer board which is powerful enough to run large operating systems like Linux, Mac and Windows. The Linux operating systems like Archlinux ARM, OpenELEC, Pidora, Raspbmc, RISC OS and the Raspbian and also Ubuntu versions are available for the Raspberrypi board.
In a multi-tasking environment of the Operating System several processes executes at the same time and the Signals provide an Inter-Process Communication (IPC) method. The Operating System sends signals to the process to notify them about the events occurred and to control them. A Parent process can create another process, which are called the Child process and the Parent process can use signals to control the Child process. The Child can also send a signal back to the Parent process.
The signal is also a means of passing message between independent processes. A signal Handler function inside the process will always get the signal number of the received signals. The Signal Handler function can be set up in such a way that it can receive value or messaged passed along with the signals by the other processes. This article discusses how to send a message along with a signal from one process to another and how to set up the signal handler in such a way that it can get the information including the message from the received signal.
A signal is a software interrupt that can be sent to a process which is currently executing in the Operating System. The list of all the available signals in the OS and their signal numbers can be obtained using the following command;
The following table gives a list of the most common signals that a process might encounter in an Operating System:
|SIGHUP||1||Linux sends a process this signal when it becomes disconnected from a terminal.|
|SIGINT||2||Linux sends a process this signal when the user tries to end it by
|SIGILL||4||Linux sends a process this signal when it attempts to execute an illegal instruction.|
|SIGABRT||6||Linux sends a process this signal to the process when the process calls the ‘abort ()’ function|
|SIGFPE||8||Linux sends a process this signal when it has executed an invalid floating-point math instruction|
|SIGKILL||9||Linux sends a process this signal to end it immediately|
|SIGUSR1||10||User programs can send this signal to other process|
|SIGUSR2||12||User programs can send this signal to other process|
|SIGSEGV||11||Linux sends a process this signal when the program has attempted an invalid memory access|
|SIGPIPE||13||Linux sends a process this signal when the program has attempted to access a broken data stream, such as a socket connection that has been already closed|
|SIGALRM||14||A process can receive this signal from the Linux using the function alarm (), after a time period mentioned in its argument.|
|SIGTERM||15||Linux sends a process this signal requesting it to terminate|
|SIGCHLD||17||Linux sends a process this signal when a child process exits|
|SIGXCPU||24||Linux sends a process this signal when it exceeds the limit of
CPU time that it can consume.
|SIGVTALRM||26||A process can receive this signal from the Linux using the function setitimer (), after a time period mentioned in its argument.|
Most of the time the Operating system send signals to the processes, but process can also send signals to each other. Much like hardware interrupts it is a mechanism to notify a process that an event has occurred. Different signals are available which can be used to notify different events and as given in the above table these signals are differentiated by their signal numbers.
The user programs should always try to use only the signals which are reserved for them, SIGUSR1 and SIGUSR2 to communicate between the processes. The steps which a process performs corresponding to a received signal are called ‘Signal Handling’. There should be a function called ‘Signal Handler’ inside the process which can perform the necessary things in response to a signal received.
A signal can be send to a process from another process using the using kill () function. But the kill () function is not able to send any values or message along with the signals. A function called ‘sigqueue ()’ is available in the <signal.h> which can be used to send values or messages along with the signals. Sending a signal with message using this function is a bit complex task especially for the beginners and hence for the ease of programming a new function is written based on the ‘sigqueue ()’ to send value along with signals to another process. The function that is written in this project to send messages between two process is called ‘sig_send_val ()’ and the details are discussed in the following section. In this project the Raspberrypi board is loaded with Ubuntu and is remotely accessed using VNC by attaching the Raspberrypi board through a LAN cable at the Ethernet port of the PC. The coding is done from the command line using the ‘vim’ editor and is compiled using ‘cc’ compiler.
This function can be used to send a particular signal to a particular process along with a message and hence the function has three arguments, one for the process id, one for the signal number and the other for the value to be sent. The prototype of the function is given below;
void sig_send_msg ( pid_t id, int signo, char *msg );
The first argument is the process id of the process to which the signal needs to be send and the second argument is the signal number of the signal to be send and the third argument is the pointer to the message that needs to be send along with the signal. As an example to send the signal ‘SIGUSR1’ to a process with a process id 2107 along with a message “hello_world”, use the following statement;
sig_send_msg ( getppid (), SIGUSR1, c );
where ‘c’ is the pointer to the string “hello_world” declared as;
char *c = “hello_world”;
Incase to get values or messages that are send along with the signals the function ‘sigaction ()’ can be used other than signal () defined in the header file <signal.h>. The signal () can pass only the signal number to the Signal Handler function whereas the function ‘sigaction ()’ has a third argument which is a structure holding the details of the received signal that can be passed on to the Signal Handler function.
This advantage of the ‘sigaction ()’ function comes at a cost of increasing code complexity and since the audience of this article are expected to be mostly beginners, a separate function has been written which uses the ‘sigaction ()’ function to set a particular function as Signal Handler. The function that can be set as a Signal Handler should have the same set of arguments and return value as shown in the following function prototype;
void signal_handler ( int sig, siginfo_t *siginfo, void *context );
In this project the function written to set the required function as Signal Handler using the ‘sigaction ()’ is named as ‘sig_set_handler ()’ and the details of the same are discussed below;
This function can be used to set a particular function as the Signal Handler for a particular signal number and hence the function has only two arguments, one for the signal number and the other for the function that need to be set as the Signal Handler. The prototype of the function is given below;
void sig_set_handler ( int signo, void *handler );
The first argument is the signal number that needs to be handled and the second argument is the pointer to the function that needs to be set as the Signal Handler. For example to set the following function as the Signal Handler using the ‘sig_set_handler ()’ for a signal ‘SIGUSR1’
void signal_handler ( int sig, siginfo_t *siginfo, void *context );
use the following statement in the code;
sig_set_handler ( SIGUSR1, &signal_handler );
To retrieve the message send along with the signal inside the receiving function the structure pointer “siginfo -> si_value” can be used. For example the following statements of the Signal Handler function will print the message string that passed on by the received signal.
void signal_handler ( int sig, siginfo_t *siginfo, void *context )
printf ( “\nmessage = %s\n”, siginfo -> si_value );
For more detail: How to Send Message between Processes using Signal in Raspberry Pi