Hy guys i have one problem. My teacher he ask me to do a worker master program.The first conection is about to give with the msg queues ,then i msg from master to worker the key for shared memory and the key from semaphore ( here i need to creat a semaphore with key and intiliaze ). The problem is here , before write on shared memory the structure i have (file_entry) i need with the semaphore to block the worker.c and when the master has done to write the strucure on shared memory the worker.c just open again. Aslo my teacher he want my to do with no posix but with system V the semaphore .
master.c file
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <sys/sem.h>
#include <sys/types.h>
#include<unistd.h>
#include <fcntl.h>
#include <semaphore.h>
#include <errno.h>
#define size_array 8
#define id 60
// structure for message queue
struct mesg_buffer {
long mesg_type;
int shm_key;
int sem_key;
} message;
typedef struct file
{
int zero;
int p_pid;
int array_length;
int array;
} file_entry;
int main(int argc, char *argv[])
{
key_t msg_key, shm_key, sem_key;
int msgid, shmid, semid, i;
sem_t *sem;
pid_t procces_id ;
// ftok to generate unique key for msg queue
msg_key = ftok("progfile.txt", id);
if( msg_key < 0 ){
printf(" error on generate key msg queue !!\n ");
}
// msgget creates a message queue
// and returns identifier
msgid = msgget(msg_key, 0666 | IPC_CREAT );
if ( msgid < 0 ){
printf("error to identifier on msg queue !!\n");
}
shm_key = shm_key/2;
// shmget returns an identifier in shmid
shmid = shmget( shm_key, sizeof(file_entry) * 8, IPC_CREAT | 0666 );
if( shmid < 0 ){
printf("error to identifier on shm !!\n");
}
sem_key = ftok("semfile.txt", id);
if( sem_key < 0 ){
printf(" error on generate key semaphore !!\n ");
}
// create a new semaphore
sem_key=sem_key+1;
semid = semget(sem_key, 1, IPC_CREAT);
if( semid < 0 ){
printf("error to identifier on semaphore !!\n");
}
struct sembuf sbuf;
sbuf.sem_flg = 0;
sbuf.sem_num = 0;
sbuf.sem_op = 1;
int ret=semop(semid, &sbuf, 1);
printf("safas %d \n",ret);
if( ret < 0 ){
printf("error to intialize !!\n");
}
message.mesg_type = 1;
message.shm_key=shm_key;
message.sem_key=sem_key;
// msgsnd to send message
if( msgsnd(msgid, &message, sizeof(message), 0) < 0 ){
printf("errro to send !!\n");
}
// display the message
printf("Data send is : %d %d \n", message.shm_key, message.sem_key);
file_entry *entries;
entries = (file_entry *) shmat(shmid, 0, 0);
if ( entries == NULL ) {
printf("error on attachment !!\n");
}
entries->p_pid = 40022;
entries->zero = 0;
entries->array_length = 8;
for( int i = 0; i < entries->array_length; i++) {
entries[i].array = rand()%2;
}
return 0;
}
worker.c file
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <sys/sem.h>
#include <sys/types.h>
#include <semaphore.h>
#include <unistd.h>
#define size_array 8
#define id 60
// structure for message queue
struct mesg_buffer {
long mesg_type;
int shm_key;
int sem_key;
} message;
typedef struct file
{
int zero;
int p_pid;
int array_length;
int array;
} file_entry;
int main()
{
key_t msg_key,shm_key,sem_key;
int ID, msgid, shmid, semid, i=1;
sem_t *sem;
// ftok to generate unique key
msg_key = ftok("progfile.txt", id);
if( msg_key < 0 ){
printf(" error on generate key msg queue !!\n ");
}
// msgget creates a message queue
// and returns identifier
msgid = msgget(msg_key, 0666 | IPC_CREAT);
if( msgid < 0) {
printf("error to identifier on msg queue !!\n");
}
// msgrcv to receive message
if ( msgrcv(msgid, &message, sizeof(message), 1, 0) < 0 ) {
printf("error to receive !! \n");
}
// display the message
printf("Data Received is : %d %d \n",message.shm_key,message.sem_key);
shmid = shmget( message.shm_key, sizeof(file_entry) *8, IPC_CREAT | 0666);
if( shmid < 0 ){
printf("error to identifier on shm !!\n");
}
file_entry *entries;
entries = (file_entry *) shmat(shmid, 0, 0);
if ( entries == NULL ) {
printf("error on attachment !!\n");
}
printf("%d\n", entries->p_pid);
printf("%d\n", entries->zero);
printf("%d\n\n", entries->array_length);
for( int i = 0; i < entries->array_length; i++) {
printf("%d\n",entries[i].array);
}
// create a new semaphore
semid = semget(message.sem_key, 1, IPC_CREAT);
if( semid < 0 ){
printf(" error to identifier on semaphore !!\n");
}
// to destroy the message queue
msgctl(msgid, IPC_RMID, NULL);
return 0;
}
Related
The program should create 200000 integers and write 2000 to a shared memory. A forked process should read 2000 from shared memory and the parent should write the next 2000 to shared memory.
if i use the code below without sleep, the parent first creates all 200000 integers and then the child reads the same integers from shared memory.
With sleep everything looks good, but we have to use semaphore.
shm.c (parent):
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/resource.h>
#include <sys/wait.h>
#define N_DATA 200000
#define N_SHARED 2000
#define LOCK -1
#define UNLOCK 1
static struct sembuf semaphore;
char shmidArg[32];
char semidArg[32];
int *shmData;
int i, j;
int status;
char *strsignal(int sig);
pid_t pid;
static int shmid;
static int semid;
char *strsignal(int sig);
/** Semaphore Operation */
static int semaphore_operation (int op) {
semaphore.sem_num = 1;
semaphore.sem_op = op;
semaphore.sem_flg = IPC_NOWAIT;
if( semop (semid, &semaphore, 1) == -1) {
perror(" semop ");
exit (EXIT_FAILURE);
}
return 1;
}
int main(int argc, char **argv) {
/* Ein Shared-Memory-Segment einrichten */
shmid = shmget(IPC_PRIVATE, N_SHARED*sizeof(int), IPC_CREAT | SHM_R | SHM_W);
if (shmid == -1) {
perror("shmid");
exit(1);
}
printf("Shared-Memory-ID: %d\n",shmid);
/* Pointer zu Shared-Memory-Segment erhalten */
shmData = (int *)shmat(shmid,0, 0);
if (shmData == (int *)(-1)) {
perror("shmat");
exit(1);
}
/* Semaphore anlegen */
semid = semget(IPC_PRIVATE, 1, IPC_CREAT | SHM_R | SHM_W);
if (semid < 0) {
perror("semid");
exit(1);
}
printf ("Semaphor-ID : %d\n", semid);
/* Semaphor mit 1 initialisieren */
if (semctl (semid, 0, SETVAL, (int) 1) == -1) {
perror("semctl");
}
snprintf(shmidArg,32, "%d", shmid);
snprintf(semidArg,32, "%d", semid);
/** erstellen des Kindprozesses */
pid = fork();
// Kindprozess
if (pid == 0) {
execlp("./shm_child",shmidArg,semidArg,NULL);
} else if (pid < 0) {
perror("Kindprozess konnte nicht erzeugt werden!");
return 1;
}
// Elternprozess
else {
/** ininitalisieren des Zufallsgenerator durch aktuellen Zeitstempel */
srand48(time(NULL));
for(i=0;i<N_DATA;i=i+N_SHARED) {
semaphore_operation(LOCK);
for (j=0; j<N_SHARED; j++) {
shmData[j] = lrand48();
//MSZ
//printf("SHM-->%d-->%d\n",i+1,shmData[i]);
}
// if(i == 0 || i == 2000) {
printf("Parent-->%d-->0-->%d\n",i,shmData[0]);
printf("Parent-->%d-->1999->%d\n",i,shmData[1999]);
// }
semaphore_operation(UNLOCK);
//sleep(1);
}
}
//MSZ
//sleep(2);
printf("PID: %d\n", pid);
if (waitpid(pid, &status, 0) == -1) {
perror("wait konnte nicht erzeugt werden!");
return 1;
}
if (WIFEXITED(status)) {
printf("Exitcode: %d\n", WEXITSTATUS(status));
semctl (semid, 0, IPC_RMID, 0);
shmctl (shmid, IPC_RMID, NULL);
//If process terminaded by a signal
} else if (WIFSIGNALED(status)) {
printf("Signal: %d %s\n", WTERMSIG(status), strsignal(WTERMSIG(status)));
semctl (semid, 0, IPC_RMID, 0);
shmctl (shmid, IPC_RMID, NULL);
}
}
shm_child.c (Child):
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#define N_DATA 6000
#define N_SHARED 2000
#define LOCK -1
#define UNLOCK 1
int i,j;
int *shmData;
static int shmid;
static int semid;
static struct sembuf semaphore;
/** Semaphore Operation */
static int semaphore_operation (int op) {
semaphore.sem_num = 0;
semaphore.sem_op = op;
semaphore.sem_flg = SEM_UNDO;
if( semop (semid, &semaphore, 1) == -1) {
perror(" semop ");
exit (EXIT_FAILURE);
}
return 1;
}
int main(int argc, char **argv) {
shmid = atoi(argv[0]);
semid = atoi(argv[1]);
printf("\nshm_child shared memoryid:%d\n",shmid);
printf("shm_child Semaphoren-ID:%d\n",semid);
/* Pointer auf Shared-Memory erstellen */
shmData = (int *)shmat(shmid,0,0);
if (shmData == (int *)(-1)) {
perror("shmat");
exit(1);
}
for(i=0;i<N_DATA;i=i+N_SHARED) {
semaphore_operation(LOCK);
for(j=0;j<N_SHARED;j++) {
//printf("%d-->%d --> %d\n",i,j+1,shmData[j]);
}
// if(i == 0 || i == 2000) {
printf("child-->%d-->0-->%d\n",i,shmData[0]);
printf("child-->%d-->1999->%d\n",i,shmData[1999]);
// }
semaphore_operation(UNLOCK);
sleep(1);
}
return 0;
}
Please help us
Thank you guys
Edit: Thank you very much for your answers. I can't mark the right answer because i dont know what its right. But i dont want try anything more. 15 hours are enough
The writer process shall give reader a permission to read, and wait for the reading completion. After that the reader shall give writer a permission to proceed, and wait for writing completion.
This goal cannot be achieved with a single semaphore. You need two, along the lines of:
// parent aka writer
writer_barrier = semaphore(UNLOCKED);
reader_barrier = semaphore(LOCKED);
start_reader();
while(...) {
lock(writer_barrier);
write_data();
unlock(reader_barrier);
}
// child aka reader
while(....)
lock(reader_barrier);
read_data();
unlock(writer_barrier);
}
I created the two producers and two consumers, producer1 sent to consumer1 two integer number and consumer1 print the sum of numbers, and I have another consumer and producer, producer2 sent to consumer2 the path for folder and consumer2 print the all files from directory (ls command from linux). An now I want to merge together this, for example I want as all producers and consumer to use the same message queue.
This is my code for producer1:
//IPC_msgq_send.c
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXSIZE 128
struct msgbuf
{
long mtype;
char mtext[MAXSIZE];
};
int main() {
int msqid;
// int msgflg = IPC_CREAT | 0666;
key_t key;
struct msgbuf sbuf;
size_t buflen;
key = ftok(".", 'g');
//Get the message queue ID for the given key
if ((msqid = msgget(key, IPC_CREAT | 0666 )) < 0) {
perror("Could not get message queue\n");
exit(1);
}
printf("MSQID value: %d\n", msqid);
//Message Type
sbuf.mtype = 1;
printf("Enter a path for a folder : ");
scanf("%[^\n]",sbuf.mtext);
// getchar();
buflen = strlen(sbuf.mtext) + 1 ;
if (msgsnd(msqid, &sbuf, buflen, IPC_NOWAIT) < 0)
{
printf ("%d, %ld, %s, %d\n", msqid, sbuf.mtype, sbuf.mtext, (int)buflen);
perror("Could not send message!\n");
exit(1);
}
else
printf("Message Sent\n");
exit(0);
}
Consumer1:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXSIZE 128
struct msgbuf
{
long mtype;
char mtext[MAXSIZE];
};
int main() {
int msqid;
key_t key;
struct msgbuf rcvbuffer;
char pathForPrint[1024] = "";
// key = 1234;
key = ftok(".", 'g');
if ((msqid = msgget(key, 0666)) < 0) {
perror("Could not get message queue\n");
exit(1);
}
printf("MSQID value: %d\n", msqid);
// Receive an answer of message type 1.
if (msgrcv(msqid, &rcvbuffer, MAXSIZE, 1, 0) < 0) {
perror("Could not receive message!\n");
exit(1);
}
//printf("%s\n", rcvbuffer.mtext);
strcat(pathForPrint, "ls ");
strcat(pathForPrint, rcvbuffer.mtext);
system(pathForPrint);
return 0;
}
Producer2:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define VECTOR_SIZE 2
struct msgbuf
{
long mtype;
int vector[VECTOR_SIZE];
};
int main() {
int msqid;
// int msgflg = IPC_CREAT | 0666;
key_t key;
struct msgbuf sbuf;
size_t buflen;
int i;
key = ftok(".", 'g');
//Get the message queue ID for the given key
if ((msqid = msgget(key, IPC_CREAT | 0666 )) < 0) {
perror("Could not get message queue\n");
exit(1);
}
printf("MSQID value: %d\n", msqid);
//Message Type
sbuf.mtype = 1;
while(1){
printf("Enter a message to add to message queue : ");
for(i = 0; i < 2; i++){
scanf("%d",&(sbuf.vector[i]));
buflen = sizeof(sbuf.vector[i]) + 1 ;
}
// getchar();
if (msgsnd(msqid, &sbuf, buflen, IPC_NOWAIT) < 0)
{
printf ("%d, %ld, %d, %d, %d\n", msqid, sbuf.mtype, sbuf.vector[0], sbuf.vector[1], (int)buflen);
perror("Could not send message!\n");
exit(1);
}
else
printf("Message Sent\n");
sleep(3);
}
exit(0);
}
Consumer2:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 128
#define VECTOR_SIZE 2
struct msgbuf
{
long mtype;
int vector[VECTOR_SIZE];
};
int main() {
int msqid;
key_t key;
struct msgbuf rcvbuffer;
// key = 1234;
key = ftok(".", 'g');
while(1){
if ((msqid = msgget(key, 0666)) < 0) {
perror("Could not get message queue\n");
exit(1);
}
printf("MSQID value: %d\n", msqid);
// Receive an answer of message type 1.
if (msgrcv(msqid, &rcvbuffer, MAXSIZE, 1, 0) < 0) {
perror("Could not receive message!\n");
exit(1);
}
printf("%d\n", (rcvbuffer.vector[0] + rcvbuffer.vector[1]));
}
return 0;
}
For use the same queue is necessary to have the same key, but how to make it ?
Thank you!
The key is a randomly selectable integer. If you generate the key with ftok(), you get the same key as long you refer to the same path and the same id, cf. the man page. If you want the same key, it is a bad idea to use a relative path (as you did), since your programs may have different directories. Use an absolute path.
However, please consider the remark of Aconcagua. If you use a common queue, you need different type ids (you use id=1 for both).
I'm a beginner in concurrent programming and I want to implement a consumer and producer. I want to send after 3 seconds from producer two integers and I want to print the sum of numbers from producer.
After running the code I have Segmentation fault :(.
Thank you for help :D
This is my code for producer:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define VECTOR_SIZE 2
struct msgbuf
{
long mtype;
int vector[VECTOR_SIZE];
};
int main() {
int msqid;
// int msgflg = IPC_CREAT | 0666;
key_t key;
struct msgbuf sbuf;
size_t buflen;
int i;
key = ftok(".", 'g');
//Get the message queue ID for the given key
if ((msqid = msgget(key, IPC_CREAT | 0666 )) < 0) {
perror("Could not get message queue\n");
exit(1);
}
printf("MSQID value: %d\n", msqid);
//Message Type
sbuf.mtype = 1;
while(1){
for(i = 0; i < 2; i++){
printf("Enter a message to add to message queue : ");
scanf("%d",sbuf.vector[i]);
buflen = strlen(sbuf.vector[i]) + 1 ;
}
sleep(3);
}
// getchar();
if (msgsnd(msqid, &sbuf, buflen, IPC_NOWAIT) < 0)
{
printf ("%d, %ld, %d, %d\n", msqid, sbuf.mtype, sbuf.vector[0], sbuf.vector[1], (int)buflen);
perror("Could not send message!\n");
exit(1);
}
else
printf("Message Sent\n");
exit(0);
}
And here I have the code for consumer:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 128
#define VECTOR_SIZE 2
struct msgbuf
{
long mtype;
char vector[VECTOR_SIZE];
};
int main() {
int msqid;
key_t key;
struct msgbuf rcvbuffer;
// key = 1234;
key = ftok(".", 'g');
if ((msqid = msgget(key, 0666)) < 0) {
perror("Could not get message queue\n");
exit(1);
}
printf("MSQID value: %d\n", msqid);
// Receive an answer of message type 1.
if (msgrcv(msqid, &rcvbuffer, MAXSIZE, 1, 0) < 0) {
perror("Could not receive message!\n");
exit(1);
}
printf("%d\n", rcvbuffer.vector[0] + rcvbuffer.vector[1]);
return 0;
}
I am trying to implement threading, a binary semaphore, and message queues in a client and server program. Everything works, except for the reply in my server to send a response back to the client. When I uncomment the reply, the server loops infinitely after receiving a message.
They both use a message.h header file that is a struct containing:
contents (character), id(int), and mtype(int).
// server.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <errno.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#include "message.h"
int sqid, cqid, pid;
msg m, n;
sem_t sem_var;
key_t key;
void requestSem();
void setSem();
void unlockSem();
void reply();
void readQueue();
void listener(void *ptr);
int main() {
key = ftok(".", 'z');
sqid = msgget(key, IPC_CREAT | 0600);
if(sqid < 0) {
perror("Error creating the message queue.\n");
}
pthread_t thread1;
pthread_t thread2;
pthread_t thread3;
char *msg1 = "Thread 1";
char *msg2 = "Thread 2";
char *msg3 = "Thread 3";
pthread_create(&thread1, NULL, (void *) &listener, (void *) msg1);
pthread_create(&thread2, NULL, (void *) &listener, (void *) msg2);
pthread_create(&thread3, NULL, (void *) &listener, (void *) msg3);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
pthread_join(thread3, NULL);
}
// always listen for messages
void listener(void *ptr) {
while (1) {
requestSem();
setSem();
readQueue();
unlockSem();
//reply();
}
}
void readQueue()
{
// print the proccess ID and thread ID
printf("Process ID: %d, Thread ID: %d\n", getpid(), pthread_self());
// receive message
if(msgrcv(sqid,&m,sizeof(struct msg),0,0) < 0) {
perror("Error receiving a message.\n");
}
printf("Message was received...\n");
fprintf(stderr, "The contents are: %s\n", &m.contents);
fprintf(stderr, "The client's ID is: %d\n", (&m)->id);
fprintf(stderr, "The thread's ID is: %d\n", pthread_self());
}
void requestSem()
{
// request semaphore (lock)
sem_init(&sem_var, 1, 1);
printf("Semaphore requested.\n");
}
void setSem()
{
// lock semaphore
sem_wait(&sem_var);
printf("Semaphore set.\n");
}
void unlockSem()
{
// unlock semaphore
sem_post(&sem_var);
printf("Semaphore unlocked.\n");
}
void reply()
{
// send reply
printf("got here\n");
pid = (&m)->id;
cqid = msgget(pid, 0600);
n.contents = (&m)->contents;
n.mtype = 0;
n.id = getpid();
if(msgsnd(cqid, &n,sizeof(struct msg),0) < 0) {
perror("Msg send error");
}
msgctl(sqid,IPC_RMID,NULL);
}
// client.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <errno.h>
#include <pthread.h>
#include <semaphore.h>
#include "message.h"
int main() {
// initialize variables
int mqid, rqid;
msg m;
key_t key;
// initialize message
int pid;
pid = getpid();
m.id = pid;
m.mtype = 1;
// create message queue and response queue
key = ftok(".", 'z');
mqid = msgget(key, 0600);
rqid = msgget(pid, IPC_CREAT | 0600);
if(mqid < 0) {
perror("Error creating the message queue.\n");
}
if (rqid < 0)
{
perror("Error creating the message queue.\n");
}
// loop forever, can send as many messages as you want
while(1) {
fprintf(stderr, "The ID of the client is: %d\n", pid);
// prompt for user input
printf("Enter one character to send: \n");
scanf("%s", &m.contents);
// send message
if(msgsnd(mqid, &m,sizeof(struct msg), 1) < 0) {
perror("Error sending the message.");
}
//msgctl(mqid,IPC_RMID,NULL);
printf("Message was sent successfully!\n");
// receive response
printf("Waiting for a reply...\n");
if(msgrcv(rqid,&m,sizeof(msg), 0, 0) < 0)
{
perror("Error receiving a message.\n");
}
printf("Message was received.\n");
fprintf(stderr, "The contents are: %s\n", &m.contents);
}
}
Thank you in advance for any help. Everything functions as it's supposed to when reply is commented out within listener in the server. Uncommenting it creates an infinite loop.
the reason the server never exits is because each thread has a
while(1)
loop and no way to exit that loop
How do I use mqueue (message queue) in a c program on a Linux based system?
I'm looking for some good code examples that can show how this is done in a correct and proper way, maybe a howto.
The following is a simple example of a server that receives messages from clients until it receives an "exit" message telling it to stop.
The code for the server:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <mqueue.h>
#include "common.h"
int main(int argc, char **argv)
{
mqd_t mq;
struct mq_attr attr;
char buffer[MAX_SIZE + 1];
int must_stop = 0;
/* initialize the queue attributes */
attr.mq_flags = 0;
attr.mq_maxmsg = 10;
attr.mq_msgsize = MAX_SIZE;
attr.mq_curmsgs = 0;
/* create the message queue */
mq = mq_open(QUEUE_NAME, O_CREAT | O_RDONLY, 0644, &attr);
CHECK((mqd_t)-1 != mq);
do {
ssize_t bytes_read;
/* receive the message */
bytes_read = mq_receive(mq, buffer, MAX_SIZE, NULL);
CHECK(bytes_read >= 0);
buffer[bytes_read] = '\0';
if (! strncmp(buffer, MSG_STOP, strlen(MSG_STOP)))
{
must_stop = 1;
}
else
{
printf("Received: %s\n", buffer);
}
} while (!must_stop);
/* cleanup */
CHECK((mqd_t)-1 != mq_close(mq));
CHECK((mqd_t)-1 != mq_unlink(QUEUE_NAME));
return 0;
}
The code for the client:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <mqueue.h>
#include "common.h"
int main(int argc, char **argv)
{
mqd_t mq;
char buffer[MAX_SIZE];
/* open the mail queue */
mq = mq_open(QUEUE_NAME, O_WRONLY);
CHECK((mqd_t)-1 != mq);
printf("Send to server (enter \"exit\" to stop it):\n");
do {
printf("> ");
fflush(stdout);
memset(buffer, 0, MAX_SIZE);
fgets(buffer, MAX_SIZE, stdin);
/* send the message */
CHECK(0 <= mq_send(mq, buffer, MAX_SIZE, 0));
} while (strncmp(buffer, MSG_STOP, strlen(MSG_STOP)));
/* cleanup */
CHECK((mqd_t)-1 != mq_close(mq));
return 0;
}
The common header:
#ifndef COMMON_H_
#define COMMON_H_
#define QUEUE_NAME "/test_queue"
#define MAX_SIZE 1024
#define MSG_STOP "exit"
#define CHECK(x) \
do { \
if (!(x)) { \
fprintf(stderr, "%s:%d: ", __func__, __LINE__); \
perror(#x); \
exit(-1); \
} \
} while (0) \
#endif /* #ifndef COMMON_H_ */
Compiling:
gcc -o server server.c -lrt
gcc -o client client.c -lrt
#include <stdio.h>
#include <fcntl.h>
#include <mqueue.h>
int main(int argc, char *argv[])
{
mqd_t mq; // message queue
struct mq_attr ma; // message queue attributes
int status = 0;
int a = 5;
int b = 0;
printf("a = %d, b = %d\n", a, b);
// Specify message queue attributes.
ma.mq_flags = 0; // blocking read/write
ma.mq_maxmsg = 16; // maximum number of messages allowed in queue
ma.mq_msgsize = sizeof(int); // messages are contents of an int
ma.mq_curmsgs = 0; // number of messages currently in queue
// Create the message queue with some default settings.
mq = mq_open("/test_queue", O_RDWR | O_CREAT, 0700, &ma);
// -1 indicates an error.
if (mq == -1)
{
printf("Failed to create queue.\n");
status = 1;
}
if (status == 0)
{
status = mq_send(mq, (char *)(&a), sizeof(int), 1);
}
if (status == 0)
{
status = mq_receive(mq, (char *)(&b), sizeof(int), NULL);
}
if ((status == 0) && (mq_close(mq) == -1))
{
printf("Error closing message queue.\n");
status = 1;
}
if ((status == 0) && (mq_unlink("test_queue") == -1))
{
printf("Error deleting message queue.\n");
status = 1;
}
printf("a = %d, b = %d\n", a, b);
return status;
}
mq_send(mq, (char *)(&a), sizeof(int), 1) copies sizeof(int) bytes from buffer &a in this case, it does not carry the pointer of variable a, but carries the value of variable a from one process to another process. Implementation is right.
Code as below for your reference:
IPC_msgq_rcv.c
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 128
void die(char *s)
{
perror(s);
exit(1);
}
struct msgbuf
{
long mtype;
char mtext[MAXSIZE];
};
void main()
{
int msqid;
key_t key;
struct msgbuf rcvbuffer;
key = 1234;
if ((msqid = msgget(key, 0666)) < 0)
die("msgget()");
//Receive an answer of message type 1.
if (msgrcv(msqid, &rcvbuffer, MAXSIZE, 1, 0) < 0)
die("msgrcv");
printf("%s\n", rcvbuffer.mtext);
exit(0);
}
IPC_msgq_send.c
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXSIZE 128
void die(char *s)
{
perror(s);
exit(1);
}
struct msgbuf
{
long mtype;
char mtext[MAXSIZE];
};
main()
{
int msqid;
int msgflg = IPC_CREAT | 0666;
key_t key;
struct msgbuf sbuf;
size_t buflen;
key = 1234;
if ((msqid = msgget(key, msgflg )) < 0) //Get the message queue ID for the given key
die("msgget");
//Message Type
sbuf.mtype = 1;
printf("Enter a message to add to message queue : ");
scanf("%[^\n]",sbuf.mtext);
getchar();
buflen = strlen(sbuf.mtext) + 1 ;
if (msgsnd(msqid, &sbuf, buflen, IPC_NOWAIT) < 0)
{
printf ("%d, %ld, %s, %d \n", msqid, sbuf.mtype, sbuf.mtext, (int)buflen);
die("msgsnd");
}
else
printf("Message Sent\n");
exit(0);
}
Compile each of the source files, to get a writer-executable and reader-executable. As below::
gcc -o MQsender IPC_msgq_send.c
gcc -o MQreceiver IPC_msgq_rcv.c
Executing each of the binaries, you can send the message and read the message from the message queue. Also, try to see the message queue state, by running command (at different states of queue):
ipcs -q
For your linux system, you can know all the details of the IPC mechanisms and available queues etc, by using:
ipcs -a
Reference Blog