Signal Handlign Examples
1. Capturing SIGINT
This program demonstrates capturing the SIGINT signal (Ctrl+C) with a custom handler.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
void sigint_handler(int sig_num) {
if (sig_num == SIGINT) {
printf("Ctrl+C was pressed.\n");
}
}
int main() {
if (signal(SIGINT, sigint_handler) == SIG_ERR) {
perror("Failed to set signal handler");
exit(EXIT_FAILURE);
}
while (1) {
printf("Program is running...\n");
sleep(2);
}
return 0;
}
2. Hanlding SIGCHLD to Prevent Zombie Processes
This example shows how to handle SIGCHLD signals to reap terminated child processes.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/types.h>
void child_handler(int sig_num) {
if (sig_num == SIGCHLD) {
while (waitpid(-1, NULL, WNOHANG) > 0);
}
}
int main() {
if (signal(SIGCHLD, child_handler) == SIG_ERR) {
perror("Failed to set SIGCHLD handler");
exit(EXIT_FAILURE);
}
for (int idx = 0; idx < 5; ++idx) {
pid_t child_pid = fork();
if (child_pid == 0) {
sleep(1);
exit(0);
}
}
while (1) {
pause();
}
return 0;
}
3. Using SIGALRM for Periodic Actions
This program uses SIGALRM to trigger periodic events, simulating a card game.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
void alarm_handler(int sig_num) {
if (sig_num == SIGALRM) {
printf("A random card has been drawn.\n");
alarm(3);
}
}
int main() {
if (signal(SIGALRM, alarm_handler) == SIG_ERR) {
perror("Failed to set alarm handler");
exit(EXIT_FAILURE);
}
alarm(3);
char user_input;
while (1) {
printf("Enter your card: ");
scanf(" %c", &user_input);
printf("You played: %c\n", user_input);
alarm(3);
}
return 0;
}
4. Custom Signal Communication Between Processes
This example shows a child process sending a custom signal (SIGUSR1) to its parent.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
void custom_signal_handler(int sig_num) {
if (sig_num == SIGUSR1) {
printf("Received custom signal. Terminating.\n");
raise(SIGTERM);
}
}
int main() {
if (signal(SIGUSR1, custom_signal_handler) == SIG_ERR) {
perror("Failed to set custom signal handler");
exit(EXIT_FAILURE);
}
pid_t process_id = fork();
if (process_id > 0) {
while (1) {
printf("Parent process is alive.\n");
sleep(1);
}
} else if (process_id == 0) {
sleep(2);
printf("Child process sending signal.\n");
kill(getppid(), SIGUSR1);
while (1) {
printf("Child process continues.\n");
sleep(1);
}
} else {
perror("Fork failed");
exit(EXIT_FAILURE);
}
return 0;
}
Message Queue Communication
Basic Message Queue Implementation
This section demonstrates a simple client-server model using System V message queues.
Message Sender Program
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>
struct Message {
long msg_type;
char msg_content[256];
};
#define MSG_DATA_SIZE (sizeof(struct Message) - sizeof(long))
int main() {
key_t queue_key = ftok("/tmp", 'A');
if (queue_key == -1) {
perror("ftok failed");
exit(EXIT_FAILURE);
}
int queue_id = msgget(queue_key, IPC_CREAT | 0666);
if (queue_id == -1) {
perror("msgget failed");
exit(EXIT_FAILURE);
}
struct Message outgoing_msg;
while (1) {
memset(outgoing_msg.msg_content, 0, sizeof(outgoing_msg.msg_content));
printf("Enter message type: ");
scanf("%ld", &outgoing_msg.msg_type);
getchar();
printf("Enter message text: ");
fgets(outgoing_msg.msg_content, sizeof(outgoing_msg.msg_content), stdin);
outgoing_msg.msg_content[strlen(outgoing_msg.msg_content) - 1] = '\0';
if (msgsnd(queue_id, &outgoing_msg, MSG_DATA_SIZE, 0) == -1) {
perror("msgsnd failed");
exit(EXIT_FAILURE);
}
printf("Message sent.\n");
if (strcmp(outgoing_msg.msg_content, "exit") == 0) {
break;
}
}
return 0;
}
Message Receiver Program
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>
struct Message {
long msg_type;
char msg_content[256];
};
#define MSG_DATA_SIZE (sizeof(struct Message) - sizeof(long))
int main() {
key_t queue_key = ftok("/tmp", 'A');
if (queue_key == -1) {
perror("ftok failed");
exit(EXIT_FAILURE);
}
int queue_id = msgget(queue_key, IPC_CREAT | 0666);
if (queue_id == -1) {
perror("msgget failed");
exit(EXIT_FAILURE);
}
struct Message incoming_msg;
while (1) {
memset(incoming_msg.msg_content, 0, sizeof(incoming_msg.msg_content));
if (msgrcv(queue_id, &incoming_msg, MSG_DATA_SIZE, 1, 0) == -1) {
perror("msgrcv failed");
exit(EXIT_FAILURE);
}
printf("Received: %s\n", incoming_msg.msg_content);
if (strcmp(incoming_msg.msg_content, "exit") == 0) {
break;
}
}
if (msgctl(queue_id, IPC_RMID, NULL) == -1) {
perror("Failed to remove message queue");
exit(EXIT_FAILURE);
}
return 0;
}
Bidirectional Communication with Forked Processes
This example creates a bidirectional communication channel using a single message queue and forked processes.
Process A (Handles Type 1 Messages, Sends Type 2)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <sys/wait.h>
struct MessagePacket {
long packet_type;
char packet_data[256];
};
#define PACKET_SIZE (sizeof(struct MessagePacket) - sizeof(long))
int main() {
key_t queue_key = ftok("/tmp", 'B');
if (queue_key == -1) {
perror("ftok error");
exit(EXIT_FAILURE);
}
int queue_id = msgget(queue_key, IPC_CREAT | 0666);
if (queue_id == -1) {
perror("msgget error");
exit(EXIT_FAILURE);
}
pid_t child_pid = fork();
if (child_pid > 0) {
struct MessagePacket send_packet;
while (1) {
memset(send_packet.packet_data, 0, sizeof(send_packet.packet_data));
printf("Enter type for outgoing message: ");
scanf("%ld", &send_packet.packet_type);
getchar();
printf("Enter message: ");
fgets(send_packet.packet_data, sizeof(send_packet.packet_data), stdin);
send_packet.packet_data[strlen(send_packet.packet_data) - 1] = '\0';
if (msgsnd(queue_id, &send_packet, PACKET_SIZE, 0) == -1) {
perror("msgsnd error");
exit(EXIT_FAILURE);
}
printf("Message dispatched.\n");
if (strcmp(send_packet.packet_data, "stop") == 0) {
break;
}
}
wait(NULL);
} else if (child_pid == 0) {
struct MessagePacket receive_packet;
while (1) {
memset(receive_packet.packet_data, 0, sizeof(receive_packet.packet_data));
if (msgrcv(queue_id, &receive_packet, PACKET_SIZE, 2, 0) == -1) {
perror("msgrcv error");
exit(EXIT_FAILURE);
}
printf("Incoming message: %s\n", receive_packet.packet_data);
if (strcmp(receive_packet.packet_data, "stop") == 0) {
break;
}
}
if (msgctl(queue_id, IPC_RMID, NULL) == -1) {
perror("msgctl error");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
} else {
perror("fork error");
exit(EXIT_FAILURE);
}
return 0;
}
Process B (Handles Type 2 Messages, Sends Type 1)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <sys/wait.h>
struct MessagePacket {
long packet_type;
char packet_data[256];
};
#define PACKET_SIZE (sizeof(struct MessagePacket) - sizeof(long))
int main() {
key_t queue_key = ftok("/tmp", 'B');
if (queue_key == -1) {
perror("ftok error");
exit(EXIT_FAILURE);
}
int queue_id = msgget(queue_key, IPC_CREAT | 0666);
if (queue_id == -1) {
perror("msgget error");
exit(EXIT_FAILURE);
}
pid_t child_pid = fork();
if (child_pid > 0) {
struct MessagePacket receive_packet;
while (1) {
memset(receive_packet.packet_data, 0, sizeof(receive_packet.packet_data));
if (msgrcv(queue_id, &receive_packet, PACKET_SIZE, 1, 0) == -1) {
perror("msgrcv error");
exit(EXIT_FAILURE);
}
printf("Received: %s\n", receive_packet.packet_data);
if (strcmp(receive_packet.packet_data, "stop") == 0) {
break;
}
}
wait(NULL);
} else if (child_pid == 0) {
struct MessagePacket send_packet;
while (1) {
memset(send_packet.packet_data, 0, sizeof(send_packet.packet_data));
printf("Enter type for response: ");
scanf("%ld", &send_packet.packet_type);
getchar();
printf("Enter response: ");
fgets(send_packet.packet_data, sizeof(send_packet.packet_data), stdin);
send_packet.packet_data[strlen(send_packet.packet_data) - 1] = '\0';
if (msgsnd(queue_id, &send_packet, PACKET_SIZE, 0) == -1) {
perror("msgsnd error");
exit(EXIT_FAILURE);
}
printf("Response sent.\n");
if (strcmp(send_packet.packet_data, "stop") == 0) {
break;
}
}
exit(EXIT_SUCCESS);
} else {
perror("fork error");
exit(EXIT_FAILURE);
}
return 0;
}