Signal Handling Mechanisms
Default, Ignore, and Custom Signal Handlers
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
void custom_signal_handler(int sig_num) {
if (sig_num == SIGINT) {
printf("Received SIGINT signal (Ctrl+C)\n");
}
}
int main() {
// Ignore SIGINT signal
if (signal(SIGINT, SIG_IGN) == SIG_ERR) {
perror("signal configuration failed");
return EXIT_FAILURE;
}
/*
// Restore default SIGINT handler
if (signal(SIGINT, SIG_DFL) == SIG_ERR) {
perror("signal configuration failed");
return EXIT_FAILURE;
}
// Set custom SIGINT handler
if (signal(SIGINT, custom_signal_handler) == SIG_ERR) {
perror("signal configuration failed");
return EXIT_FAILURE;
}
*/
while (1) {
printf("Running...\n");
sleep(1);
}
return EXIT_SUCCESS;
}
SIGCHLD Signal for Zombie Process Cleanup
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/types.h>
void child_signal_handler(int sig_num) {
if (sig_num == SIGCHLD) {
while (waitpid(-1, NULL, WNOHANG) > 0) {
// Child process reaped
}
}
}
int main() {
// Configure SIGCHLD handler
if (signal(SIGCHLD, child_signal_handler) == SIG_ERR) {
perror("signal configuration failed");
return EXIT_FAILURE;
}
// Create child processes
for (int i = 0; i < 5; i++) {
pid_t child_pid = fork();
if (child_pid == 0) {
// Child process
sleep(1);
exit(EXIT_SUCCESS);
}
}
// Parent process continues
while (1) {
pause();
}
return EXIT_SUCCESS;
}
Timer-Based Signal Simulatoin
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
void timer_handler(int sig_num) {
if (sig_num == SIGALRM) {
printf("System generated a card\n");
alarm(5); // Reset timer
}
}
int main() {
// Set SIGALRM handler
if (signal(SIGALRM, timer_handler) == SIG_ERR) {
perror("signal configuration failed");
return EXIT_FAILURE;
}
alarm(5); // Start initial timer
char user_input;
while (1) {
printf("Enter your card: ");
scanf("%c", &user_input);
getchar(); // Clear newline
printf("You played: %c\n", user_input);
alarm(5); // Reset timer after user action
}
return EXIT_SUCCESS;
}
Inter-Process Signal Communication
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
void user_signal_handler(int sig_num) {
if (sig_num == SIGUSR1) {
printf("Dynasty has fallen\n");
raise(SIGKILL);
}
}
int main() {
// Configure SIGUSR1 handler
if (signal(SIGUSR1, user_signal_handler) == SIG_ERR) {
perror("signal configuration failed");
return EXIT_FAILURE;
}
pid_t process_id = fork();
if (process_id > 0) {
// Parent process
while (1) {
printf("This is my kingdom\n");
sleep(1);
}
} else if (process_id == 0) {
// Child process
sleep(3);
printf("I am the true emperor\n");
kill(getppid(), SIGUSR1);
while (1) {
printf("Now it's my turn\n");
sleep(1);
}
} else {
perror("fork failed");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
Message Queue Implementation
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_structure {
long message_type;
char message_content[1024];
};
#define MESSAGE_CONTENT_SIZE (sizeof(struct message_structure) - sizeof(long))
int main() {
// Generate key
key_t queue_key;
if ((queue_key = ftok("/", 'm')) == -1) {
perror("ftok failed");
return EXIT_FAILURE;
}
printf("Generated key: 0x%x\n", queue_key);
// Create message queue
int queue_id;
if ((queue_id = msgget(queue_key, IPC_CREAT | 0664)) == -1) {
perror("msgget failed");
return EXIT_FAILURE;
}
printf("Queue ID: 0x%x\n", queue_id);
struct message_structure outgoing_message;
while (1) {
memset(outgoing_message.message_content, 0, sizeof(outgoing_message.message_content));
printf("Enter message type: ");
scanf("%ld", &outgoing_message.message_type);
getchar();
printf("Enter message content: ");
fgets(outgoing_message.message_content, sizeof(outgoing_message.message_content), stdin);
outgoing_message.message_content[strlen(outgoing_message.message_content) - 1] = '\0';
// Send message
if (msgsnd(queue_id, &outgoing_message, MESSAGE_CONTENT_SIZE, 0) == -1) {
perror("msgsnd failed");
return EXIT_FAILURE;
}
printf("Message sent successfully\n");
if (strcmp(outgoing_message.message_content, "quit") == 0) {
break;
}
}
return EXIT_SUCCESS;
}
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_structure {
long message_type;
char message_content[1024];
};
#define MESSAGE_CONTENT_SIZE (sizeof(struct message_structure) - sizeof(long))
int main() {
// Generate key
key_t queue_key;
if ((queue_key = ftok("/", 'm')) == -1) {
perror("ftok failed");
return EXIT_FAILURE;
}
printf("Generated key: 0x%x\n", queue_key);
// Access message queue
int queue_id;
if ((queue_id = msgget(queue_key, IPC_CREAT | 0664)) == -1) {
perror("msgget failed");
return EXIT_FAILURE;
}
printf("Queue ID: 0x%x\n", queue_id);
struct message_structure incoming_message;
while (1) {
memset(incoming_message.message_content, 0, sizeof(incoming_message.message_content));
// Receive message
if (msgrcv(queue_id, &incoming_message, MESSAGE_CONTENT_SIZE, 0, 0) == -1) {
perror("msgrcv failed");
return EXIT_FAILURE;
}
printf("Received message: %s\n", incoming_message.message_content);
if (strcmp(incoming_message.message_content, "quit") == 0) {
break;
}
}
// Remove message queue
if (msgctl(queue_id, IPC_RMID, NULL) == -1) {
perror("msgctl failed");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
Bidirectional Process Communication Using Message Queues
Process A: Type 1 Messages
#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 message_structure {
long message_type;
char message_content[1024];
};
#define MESSAGE_CONTENT_SIZE (sizeof(struct message_structure) - sizeof(long))
int main() {
key_t queue_key = ftok("/", 'b');
if (queue_key == -1) {
perror("ftok failed");
return EXIT_FAILURE;
}
int queue_id = msgget(queue_key, IPC_CREAT | 0664);
if (queue_id == -1) {
perror("msgget failed");
return EXIT_FAILURE;
}
pid_t child_pid = fork();
if (child_pid > 0) {
// Parent sends type 1 messages
struct message_structure outgoing_msg;
outgoing_msg.message_type = 1;
while (1) {
memset(outgoing_msg.message_content, 0, sizeof(outgoing_msg.message_content));
printf("Send message: ");
fgets(outgoing_msg.message_content, sizeof(outgoing_msg.message_content), stdin);
outgoing_msg.message_content[strlen(outgoing_msg.message_content) - 1] = '\0';
msgsnd(queue_id, &outgoing_msg, MESSAGE_CONTENT_SIZE, 0);
printf("Message sent\n");
if (strcmp(outgoing_msg.message_content, "quit") == 0) {
break;
}
}
wait(NULL);
} else if (child_pid == 0) {
// Child receives type 2 messages
struct message_structure incoming_msg;
while (1) {
memset(incoming_msg.message_content, 0, sizeof(incoming_msg.message_content));
msgrcv(queue_id, &incoming_msg, MESSAGE_CONTENT_SIZE, 2, 0);
printf("Received: %s\n", incoming_msg.message_content);
if (strcmp(incoming_msg.message_content, "quit") == 0) {
break;
}
}
exit(EXIT_SUCCESS);
} else {
perror("fork failed");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
Process B: Type 2 Messages
#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 message_structure {
long message_type;
char message_content[1024];
};
#define MESSAGE_CONTENT_SIZE (sizeof(struct message_structure) - sizeof(long))
int main() {
key_t queue_key = ftok("/", 'b');
if (queue_key == -1) {
perror("ftok failed");
return EXIT_FAILURE;
}
int queue_id = msgget(queue_key, IPC_CREAT | 0664);
if (queue_id == -1) {
perror("msgget failed");
return EXIT_FAILURE;
}
pid_t child_pid = fork();
if (child_pid > 0) {
// Parent receives type 1 messages
struct message_structure incoming_msg;
while (1) {
memset(incoming_msg.message_content, 0, sizeof(incoming_msg.message_content));
msgrcv(queue_id, &incoming_msg, MESSAGE_CONTENT_SIZE, 1, 0);
printf("Received: %s\n", incoming_msg.message_content);
if (strcmp(incoming_msg.message_content, "quit") == 0) {
break;
}
}
wait(NULL);
} else if (child_pid == 0) {
// Child sends type 2 messages
struct message_structure outgoing_msg;
outgoing_msg.message_type = 2;
while (1) {
memset(outgoing_msg.message_content, 0, sizeof(outgoing_msg.message_content));
printf("Send message: ");
fgets(outgoing_msg.message_content, sizeof(outgoing_msg.message_content), stdin);
outgoing_msg.message_content[strlen(outgoing_msg.message_content) - 1] = '\0';
msgsnd(queue_id, &outgoing_msg, MESSAGE_CONTENT_SIZE, 0);
printf("Message sent\n");
if (strcmp(outgoing_msg.message_content, "quit") == 0) {
break;
}
}
exit(EXIT_SUCCESS);
} else {
perror("fork failed");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}