Shared Memory and Message Queues in C
This code demonstrates inter-process communication (IPC) using shared memory and message queues in C. It also handles signals and finds perfect numbers.
Code Snippet:
st_shmem *shmem; <br>
st_msg msg;
<br><br>
int shmem_id;
<br>
int msg_id;
<br><br>
<!-- Handler for signal actions -->
<h3>Signal Handler</h3>
void handler(int signo) {
<br>
printf("\nTerminated compute PID = (%d)\n", getpid());
<br>
shmem->process[getpid()].pid = 0;
<br>
shmem->process[getpid()].skipped = 0;
<br>
shmem->process[getpid()].tested = 0;
<br>
shmem->process[getpid()].perfect = 0;
<br>
<br>
switch(signo)
<br>
{
<br>
case SIGINT:
<br>
printf("SIGINT (%d)\n", signo);
<br>
break;
<br>
case SIGQUIT:
<br>
printf("SIGQUIT (%d)\n", signo);
<br>
break;
<br>
case SIGHUP:
<br>
printf("SIGHUP (%d)\n", signo);
<br>
break;
<br>
default:
<br>
printf("Signal (%d)\n", signo);
<br>
}
<br>
exit(0);
<br>
} <!-- end handler -->
<br><br>
<h3>Bitmap Operations</h3>
<p>These functions manage a bitmap in shared memory.</p>
<h4>Test Bit</h4>
<pre>int test_bit(int n) {
<br>
int t_bit = shmem->bitmap[n / 32];
<br>
if((t_bit & (1 << n % 32)) != 0)
<br>
{
<br>
return 1;
<br>
}
<br>
else
<br>
{
<br>
return 0;
<br>
}
<br>
}<br>
<h4>Set Bit</h4>
<pre>void set_bit(int n) {
<br>
shmem->bitmap[n / 32] |= (1 << n % 32);
<br>
}<br>
<h3>Main Function</h3>
<pre>int main(int argc, char *argv[]) {
<br>
<!-- SIGNAL -->
<br>
static struct sigaction act;
<br>
void int_handle(int);
<br>
<br>
<!-- Empty signal set -->
<br>
sigemptyset(&(act.sa_mask));
<br>
<br>
<!-- Add signals to the set that will be used -->
<br>
sigaddset(&(act.sa_mask), SIGINT);
<br>
sigaddset(&(act.sa_mask), SIGQUIT);
<br>
sigaddset(&(act.sa_mask), SIGHUP);
<br>
<br>
<!-- Register signal handler -->
<br>
act.sa_handler = handler;
<br>
<br>
<!-- Take an action if one of these signals happen -->
<br>
sigaction(SIGINT, &act, NULL);
<br>
sigaction(SIGQUIT, &act, NULL);
<br>
sigaction(SIGHUP, &act, NULL);
<br>
<br>
printf("Process (%d)\n", getpid());
<br>
int n = atoi(argv[1]);
<br>
<br>
<!-- SHARED MEMORY INITIALIZATION -->
<br>
shmem_id = shmget(KEY, sizeof(st_shmem), IPC_CREAT | 0666);
<br>
shmem = shmat(shmem_id, NULL, 0);
<br>
<br>
if(shmem_id == -1)
<br>
{
<br>
perror("ERROR(shmget()): ");
<br>
exit(1);
<br>
}
<br>
if(shmem == (st_shmem*) - 1)
<br>
{
<br>
perror("ERROR(shmget()): ");
<br>
exit(1);
<br>
}
<br>
<br>
<!-- MESSAGE QUEUE INITIALIZATION -->
<br>
msg_id = msgget(MSGKEY, IPC_CREAT | 0666);
<br>
if(msg_id == - 1)
<br>
{
<br>
perror("ERROR(msgget()): ");
<br>
exit(1);
<br>
}
<br>
<br>
msg.mtype = COMPUTE_INIT_MSG;
<br>
msg.mdata = getpid();
<br>
<br>
int msg_size = sizeof(msg) - sizeof(msg.mtype);
<br>
<!-- Send process pid to manage -->
<br>
msgsnd(msg_id, &msg, msg_size, 0);
<br>
<br>
<!-- Receive the process id assigned by the manage -->
<br>
msgrcv(msg_id, &msg, msg_size, MANAGE_ALLOCATE_MSG, 0);
<br>
<br>
<!-- Get process index from the msg received from the manage -->
<br>
int index = msg.mdata;
<br>
<br>
for(int i = n; i <= sizeof(shmem->bitmap) * 8; i++)
<br>
{
<br>
<!-- If bit == 1 skip -->
<br>
if(test_bit(i) == 1)
<br>
{
<br>
shmem->process[index].skipped++;
<br>
}
<br>
<br>
<!-- If bit == 0 -->
<br>
else
<br>
{
<br>
set_bit(i);
<br>
<!-- Find the perfect number -->
<br>
int sum_divisors = 1;
<br>
for(int j = 2; j < i; j++)
<br>
{
<br>
if(i % j == 0)
<br>
sum_divisors += j;
<br>
}
<br>
shmem->process[index].tested++;
<br>
if(sum_divisors == i && i != 1)
<br>
{
<br>
shmem->process[index].perfect++;
<br>
msg.mtype = PERFECT_MSG;
<br>
msg.mdata = i;
<br>
int msg_size = sizeof(msg) - sizeof(msg.mtype);
<br>
msgsnd(msg_id, &msg, msg_size, 0);
<br>
}
<br>
} <!-- end if-else -->
<br>
} <!-- end for -->
<br>
} <!--end main-->