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-->