rendered paste body#include "stdio.h"#include "stdlib.h" #include "string.h"#include "time.h"#include "sys/types.h"#include "sys/ipc.h"#include "sys/msg.h"#include "sys/shm.h"#include "sys/sem.h"#define SERVER_MESSAGE_ID 1#define CLIENT_MESSAGE_ID 2// shared memory to provide the pixmap to an external programint sem_id, shm_id, msq_id;char *shmsegptr;key_t key;typedef struct mymsgbuf{ long mtype; int width; int height; };key_t create_key (){ key_t key; if ((key = ftok("/myApp", 'c')) == -1) { perror("init_semaphore: ftok() failed"); return(-1); } else return key;}// Initialize semaphore setint init_semaphore(key_t key){ int sem_id; if ((sem_id = semget(key, 1, IPC_CREAT | IPC_EXCL | 0666)) == -1) { if ((sem_id = semget(key, 1, IPC_CREAT | 0666)) == -1) { perror("init_semaphore: semget() failed"); return (-1); } } union semun { int val; }; union semun semopts; semopts.val = 1; if (semctl(sem_id, 0, SETVAL, semopts) == -1) { perror("init_semaphore: semctl() failed"); return (-1); } return sem_id;}// Lock semaphoreint semaphore_lock (int sem_id){ struct sembuf sem_lock = {0, -1, 0}; if (semop(sem_id, &sem_lock, 1) == -1) { perror("semaphore_lock:\t\tsemop() failed"); return (-1); } else return (0);}// Unlock semaphoreint semaphore_unlock (int sem_id){ struct sembuf sem_unlock = {0, 1, 0}; if (semop(sem_id, &sem_unlock, 1) == -1) { perror("semaphore_unlock:\tsemop() failed"); return (-1); } else return (0);}// Initialize shared memory segmentint init_shared_memory(key_t key, int width, int height){ int shmid; /* Open the shared memory segment - create if necessary */ if ((shmid = shmget(key, width * height * 3, IPC_CREAT|IPC_EXCL|0666)) == -1) { if ((shmid = shmget(key, width * height * 3, IPC_CREAT|0666)) == -1) { char error[100]; sprintf(error, "init_shared_memory(%d,%d): shmget failed", width, height); perror(error); return (-1); } } /* Attach (map) the shared memory segment into the current process */ if ((shmsegptr = (char *) shmat(shmid, 0, 0)) == (char *) -1) { char error[100]; sprintf(error, "init_shared_memory(%d,%d): shmat failed", width, height); perror(error); return (-1); } return shmid;}// Clear all messages from message queuevoid clear_message_queue (int qid){ struct mymsgbuf msg; int length; length = sizeof(struct mymsgbuf) - sizeof(long); // Loop 1: clear all server messages while (1) { if (msgrcv(qid, &msg, length, 0 | SERVER_MESSAGE_ID, 0 | IPC_NOWAIT) == -1) break; } // Loop 2: clear all client messages while (1) { if (msgrcv(qid, &msg, length, CLIENT_MESSAGE_ID, IPC_NOWAIT) == -1) break; }}// Initialize message queueint init_message_queue( key_t key, int width, int height){ int qid, length; struct mymsgbuf msg, ack; /* Open the message queue - create if necessary */ if ((qid = msgget(key, IPC_CREAT | IPC_EXCL | 0666)) == -1) { if ((qid = msgget(key, IPC_CREAT | 0666)) == -1) { char error[100]; sprintf(error, "init_message_queue(%d,%d): msgget failed", width, height); perror(error); return (-1); } else { /* Clear all messages from the queue, if existant */ clear_message_queue(qid); } } msg.mtype = SERVER_MESSAGE_ID; msg.width = width; msg.height = height; length = sizeof(struct mymsgbuf) - sizeof(long); /* Send a message with the first size in it */ if (msgsnd(qid, &msg, length, 0) == -1) { char error[100]; sprintf(error, "init_message_queue(%d,%d): msgsnd failed", width, height); perror(error); return (-1); } printf("Waiting for client acknowledgement ... \n"); while (1) { /* Wait for the acknowledgement */ if (msgrcv(qid, &ack, length, CLIENT_MESSAGE_ID, 0) == -1) { perror("init_message_queue: msgrcv failed"); return (-1); } printf("Got client response ...\n"); // Server and client agree on the shm size if ((msg.height == ack.height) && (msg.width == ack.width)) break; } printf("got it!\n"); return qid;}void send_update (){ struct mymsgbuf msg; msg.mtype = SERVER_MESSAGE_ID; msg.width = width; msg.height = height; int length = sizeof(struct mymsgbuf) - sizeof(long); /* Send a message with the size in it, thus letting the client know an update is abailible */ if (msgsnd(msq_id, &msg, length, 0) == -1) { char error[100]; sprintf(error, "init_message_queue(%d,%d): msgsnd failed", width, height); perror(error); }}// General IPC initialization sequencevoid initialize_ipc (int width, int height){ key = create_key(); sem_id = init_semaphore (key); semaphore_lock (sem_id); shm_id = init_shared_memory (key, width, height); printf("shmid: %d\n", shm_id); msq_id = init_message_queue (key, width, height); semaphore_unlock (sem_id); }// Mark message queue for deletionint destroy_message_queue ( int qid ){ if ( msgctl(qid, IPC_RMID, 0) == -1) return (-1); else return (0);}// Mark semaphore set for deletionint destroy_semaphore(int semid){ if (semctl(semid, 0, IPC_RMID, 0) == -1) return (-1); else return (0);}// Free and release shared memory segmentint free_shared_memory (int shmid){ struct shmid_ds shmid_struct; if (shmdt(shmsegptr) == -1) { perror("free_shared_memory(); shmdt failed"); return (-1); } if (shmctl(shmid, IPC_RMID, &shmid_struct) == -1) { perror("free_shared_memory(); shmctl remove id failed"); return (-1); } return (0);}// General IPC cleanup sequencevoid clean_ipc (){ semaphore_lock(sem_id); free_shared_memory(shm_id); destroy_message_queue(msq_id); destroy_semaphore(sem_id); semaphore_unlock(sem_id);}// Re-initialize shared memory segmentvoid reinit_shared_memory(int width, int height){ semaphore_lock(sem_id); glViewport(0,0,width,height);}void copy_image_to_shared_memory(){ // Let's see what happens if we change the window_wifth and or window_height int window_width, window_height; window_width = glutGet(GLUT_WINDOW_WIDTH); window_height = glutGet(GLUT_WINDOW_HEIGHT); czsImgClr img; czfCreateImgShm( img, window_width, window_height, shmsegptr); czsImgClr tempImg; czfCreateImg( tempImg, window_width, window_height ); tempImg.w = window_width; tempImg.h = window_height; glReadPixels(0,0, window_width, window_height, GL_RGB, GL_UNSIGNED_BYTE, (GLvoid *) tempImg.data); semaphore_lock(sem_id); for (int i = window_height - 1; i >= 0; i--) for (int j = 0; j < window_width; j++) { img.data[((window_height - 1 - i) * (window_width * 3)) + (j*3)] = tempImg.data[(window_width * i * 3) + (j*3)]; img.data[((window_height - 1 - i) * (window_width * 3)) + (j*3) + 1] = tempImg.data[(window_width * i * 3) + (j*3) + 1]; img.data[((window_height - 1 - i) * (window_width * 3)) + (j*3) + 2] = tempImg.data[(window_width * i * 3) + (j*3) + 2]; } printf("sizeof(char*): %d\n", sizeof(char*)); printf("shmsegptr: %d\n", *shmsegptr); czfWriteImgPPM(img, "test.ppm"); semaphore_unlock(sem_id);}