individual char extraction in c while using messages and msgsnd - c

This is bugging me for days.
The problem is my not so good understanding of pointers and addresses in c so i hope someone will be able to help me out.
I need to pass some strings as input parameters and create as much producer processes + one consumer process.
Producers should take the string apart and send each letter as message to queue. At the end it should send NULL("").
The consumer should wait for messages and print them out.
The whole code and output is below. By looking at the output i'd say that the problem is somewhere in the producer. To be more precise it is in the first line of te for loop but i can not get it right.
manager.c - This is the main program that operates processes
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/msg.h>
int main( int argc, char *argv[], char *envp[] ) {
printf("Starting %d processes \n", argc);
putenv("MSG_KEY=12345");
for (int i = 1; i < argc; i++) {
printf("argv[%d] = %s \n", i, argv[i]);
pid_t producer = fork();
if (producer == 0) {
printf("producer pid - %d\n", getpid());
execl("./producer", "producer", argv[i], NULL);
}
}
pid_t consumer = fork();
if (consumer == 0) {
printf("consumer pid - %d\n", getpid());
execl("./consumer", "consumer", NULL);
exit(0);
} else {
printf("manager pid - %d\n", getpid());
wait(NULL);
}
int status;
while(waitpid(consumer, &status, 0) == -1);
printf("DONE consumer\n");
printf("DONE manager\n");
return 0;
}
producer.c
/*
** writes to message queue
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
struct my_msgbuf {
long mtype;
char mtext[1];
};
int main( int argc, char *argv[], char *envp[] ) {
struct my_msgbuf buf;
int msqid;
key_t key = atoi(getenv("MSG_KEY"));
if ((msqid = msgget(key, 0600 | IPC_CREAT)) == -1) {
perror("msgget");
exit(1);
}
buf.mtype = getpid();
// I believe the error is in this for loop or to be more precise in the first line of the for loop.
// takes the first argument and sends characters in separate messages
for (int i = 0; i < strlen(argv[1]); ++i) {
char c = argv[1][i];
strcpy(buf.mtext, &c);
printf ("Sending -%s-\n", buf.mtext);
if (msgsnd(msqid, (struct msgbuf *)&buf, strlen(buf.mtext)+1, 0) == -1)
perror("msgsnd");
}
// send NULL at the end
memcpy(buf.mtext, "", strlen("")+1);
if (msgsnd(msqid, (struct msgbuf *)&buf, strlen("")+1, 0) == -1)
perror("msgsnd");
return 0;
}
consumer.c
/*
** reads from message queue
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
struct my_msgbuf {
long mtype;
char mtext[1];
};
int main( int argc, char *argv[], char *envp[] ) {
struct my_msgbuf buf;
int msqid;
key_t key = atoi(getenv("MSG_KEY"));
if ((msqid = msgget(key, 0600 | IPC_CREAT)) == -1) {
perror("msgget");
exit(1);
}
int flag = 0;
int wait_counter = 0;
while (wait_counter < 10) {
msgrcv(msqid, (struct msgbuf *)&buf, sizeof(buf)-sizeof(long), 0, flag);
if (errno == ENOMSG){
wait_counter++;
printf ("Sleaping for one second...zzzZZZzzz...%d\n", wait_counter);
usleep(1000 * 1000);
} else {
printf("Received:\n\ttype: -%ld- \n\tchar: -%s- \n", buf.mtype, buf.mtext);
int compare = strcmp(buf.mtext, "");
if(compare == 0){
printf("NULL received\n");
flag = IPC_NOWAIT;
} else {
flag = 0;
}
wait_counter = 0;
}
errno = 0;
}
if (msgctl(msqid, IPC_RMID, NULL) == -1) {
perror("msgctl");
exit(1);
} else {
printf("Message queue removed\n");
}
return 0;
}
Output - i have to give you the screenshot here because c/p deletes the problem and everything looks ok
Any help will be much appreciated! Thank you!
Error when used as suggested in the #sergeya answer below
*buf.mtext = c;

Your problem (one of them, at least) is here:
char c = argv[1][i];
strcpy(buf.mtext, &c);
strcpy() will try to copy as many characters as there are until nul-terminator '\0' is encountered, starting from c. You need to copy one character exactly, so you just need
*buf.mtext = c;

As i said, the problem was in the producer inside the for loop. I will put the change here. Hope it helps anyone with the similar problem.
#SergeyA gave me excellent clue where the problem is so i switched from "strcpy" to "memcpy" and i have copied just the first character and not the nul-terminator.
Also i have changed the "strlen" to "sizeof" and removed the +1.
Producer.c
...
for (int i = 0; i < strlen(argv[1]); ++i) {
char c = argv[1][i];
memcpy(buf.mtext, &c, sizeof(&c)+1);
printf ("Sending -%c-\n", buf.mtext);
if (msgsnd(msqid, (struct msgbuf *)&buf, sizeof(buf.mtext), 0) == -1)
perror("msgsnd");
}
...

Related

How to keep program unclosed after ctr+c in named pipe?

I have 2 programs.
One is server one is client. The Client sending string to the server, the server is swapping the string and return to the client.
the problems I have is when I pressing ctr+c the program(client) closed.(I'm using threads because I have been asking for.)
So how can I keep the program unclosed after ctr+c?
when clicking enter this is the right result and waiting for the server.
when entering ctl+c the program closed and cannot running server.c
The client.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <time.h>
#define MAX_BUF 1024
// client
int main()
{
int fd;
char *myfifo = "myfifo";
char str[MAX_BUF];
printf("Input string: ");
fgets(str, MAX_BUF, stdin);
str[strlen(str) - 1] = '\0';
if (mkfifo("myfifo", 0777) == -1)
{
if (errno != EEXIST)
{
printf("Could not create fifo file\n");
return 1;
}
}
/* create the FIFO (named pipe) */
fd = open(myfifo, O_WRONLY);
if (fd == -1)
return 2;
if (write(fd, str, MAX_BUF) == -1)
return 3;
close(fd);
fd = open(myfifo, O_RDONLY);
read(fd, str, MAX_BUF);
printf("%s\n", str);
/* remove the FIFO */
unlink(myfifo);
return 0;
}
The server
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <time.h>
#include <pthread.h>
#define MAX_BUF 1024
// server
// creatring struct for saving data
typedef struct thread_data
{
char str[MAX_BUF];
int result;
} thread_data;
// the
void *routine(void *arg)
{
int fd[2];
char *myfifo = "myfifo";
thread_data *tdata = (thread_data *)arg;
if (!(strcmp(tdata->str, "exit")))
tdata->result = 1; // is exit
else
tdata->result = 0; // not exit
if (tdata->result == 1)
{
fd[1] = open(myfifo, O_WRONLY);
write(fd[1], "Done", sizeof(MAX_BUF));
close(fd[1]);
}
else
{
char string[MAX_BUF] = {0};
char c = 0;
int length = 0, i = 0;
length = strlen(tdata->str);
printf("\nBefore Swap : %s\n", tdata->str);
for (i = 0; i < length / 2; i++)
{
c = tdata->str[i];
tdata->str[i] = tdata->str[length - 1 - i];
tdata->str[length - 1 - i] = c;
}
printf("\nAfter Swap String : %s\n", tdata->str);
fd[1] = open(myfifo, O_WRONLY);
write(fd[1], tdata->str, sizeof(MAX_BUF));
close(fd[1]);
}
pthread_exit(NULL);
}
int Calculation()
{
int fd[2];
// fd[0] read
// fd[1] write
char *myfifo = "myfifo";
char buf[MAX_BUF];
/* open, read, and display the message from the FIFO */
fd[0] = open(myfifo, O_RDONLY);
if(fd[0]==-1)
return 4;
if(read(fd[0], buf, MAX_BUF)==-1)
return 5;
close(fd[0]);
// res
int result;
thread_data tdata;
strcpy(tdata.str, buf);
pthread_t t1;
if (pthread_create(&t1, NULL, &routine, (void *)&tdata) != 0)
{
return 1;
}
if (pthread_join(t1, NULL) != 0)
{
return 2;
}
}
int main()
{
int res = Calculation();
return res;
}
To avoid closing a program you should capture and
manage the signal sent by CTRL + C, that is SIGINT, I have modified the code so that it captures the signal CTRL + C
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <time.h>
#define MAX_BUF 1024
// client
int main()
{
signal(SIGINT,SIG_IGN); // Register signal handler for ignoring the signal
int fd;
char *myfifo = "myfifo";
char str[MAX_BUF];
printf("Input string: ");
fgets(str, MAX_BUF, stdin);
str[strlen(str) - 1] = '\0';
if (mkfifo("myfifo", 0777) == -1)
{
if (errno != EEXIST)
{
printf("Could not create fifo file\n");
return 1;
}
}
/* create the FIFO (named pipe) */
fd = open(myfifo, O_WRONLY);
if (fd == -1)
return 2;
if (write(fd, str, MAX_BUF) == -1)
return 3;
close(fd);
fd = open(myfifo, O_RDONLY);
read(fd, str, MAX_BUF);
printf("%s\n", str);
/* remove the FIFO */
unlink(myfifo);
return 0;
}

Handler for SIGCHLD signals

The code doesn't work and it goes in loop. I think the error is in the gestore method, that is a handler for SIGCHLD signals. This is the first time I use a handler to capture SIGCHLD signals.
This program continue to casually extracts from 0 to argv[1] until a number appears argv[1] times.
If it's not clear you can test my old program that I put at the end of question.
Can you help me finding the error?
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
int a;
void gestore(int segnale);
int main(int argc, char * argv[]){
int n = atoi(argv[1]), i, pid;
int * vec;
vec = malloc((n+1)*sizeof(*vec));
memset (vec, 0, sizeof(*vec));
char * newargv[] = {argv[0], argv[1] , NULL};
for(i = 0; i < n; i++){
pid = fork();
if (pid == 0)
execve("./throw-dice", newargv, NULL);
signal(SIGCHLD, gestore);
vec[WEXITSTATUS(a)]++;
}
while(vec[i] != n){
for(i = 1; i < n+1 && vec[i] != n; i++){
if(vec[i] != 0){
pid = fork();
if (pid == 0)
execve("./throw-dice", newargv, NULL);
signal(SIGCHLD, gestore);
vec[WEXITSTATUS(a)]++;
}
}
}
printf("The value %d is appeared %d times!\n", i, vec[i]);
while (wait(&a) != -1);
free(vec);
}
void gestore(int segnale){
signal(segnale, SIG_IGN);
waitpid(WAIT_ANY, &a, WNOHANG);
signal(segnale, gestore);
}
My goal was to modify my old program (that works) changing the way I capture the exit status of childs. From syncronically with "wait" to asyncronically with a gestore method that handle SIGCHLD signals.
This is my old program:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char * argv[]){
int n = atoi(argv[1]), a, i, pid;
int * vec;
vec = malloc((n+1)*sizeof(*vec));
memset (vec, 0, sizeof(*vec));
char * newargv[] = {argv[0], argv[1] , NULL};
for(i = 0; i < n; i++){
pid = fork();
if (pid == 0)
execve("./throw-dice", newargv, NULL);
wait(&a);
vec[WEXITSTATUS(a)]++;
}
while(vec[i] != n){
for(i = 1; i < n+1 && vec[i] != n; i++){
if(vec[i] != 0){
pid = fork();
if (pid == 0)
execve("./throw-dice", newargv, NULL);
wait(&a);
vec[WEXITSTATUS(a)]++;
}
}
}
printf("The value %d is appeared %d times\n", i, vec[i]);
while (wait(&a) != -1);
free(vec);
}
//throw-dice.c
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char * argv[]) {
int n, val;
// Must have an argument
if (argc < 2) {
exit(-1);
}
// the 1st argument must be a positive number
if ((n = atoi(argv[1])) <= 0) {
exit(-1);
}
// sleep(1); // sleep a bit
srand(getpid()); // initialize the random seed with PID
val = rand() % n + 1;
printf("(PID=%d): got number %d\n", getpid(), val);
exit(val);
}

IPC Message queue not works with forked process

I'm trying to use IPC message queue with a forked process, passing a pointer to a dynamically allocated string, but it doesn't work.
This is a simple test that I made. It doesn't print the string received from the queue. But if I try to remove the fork() it works perfectly.
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MSGSZ 128
typedef struct msgbuf {
long mtype;
char *mtext;
} message_buf;
int
main ()
{
int msqid;
char *p;
key_t key = 129;
message_buf sbuf, rbuf;
p = (char *) malloc(sizeof(char) * MSGSZ);
if ((msqid = msgget(key, IPC_CREAT|0666)) < 0) {
perror("msgget");
exit(1);
}
if (fork() == 0) {
strcpy(p, "Did you get this?");
sbuf.mtype = 1;
sbuf.mtext = p;
if (msgsnd(msqid, &sbuf, MSGSZ, IPC_NOWAIT) < 0) {
perror("msgsnd");
exit(1);
}
}
else {
sleep(1);
if (msgrcv(msqid, &rbuf, MSGSZ, 0, 0) < 0) {
perror("msgrcv");
exit(1);
}
printf("Forked version: %s\n", rbuf.mtext);
msgctl(msqid, IPC_RMID, NULL);
}
}
The problem is that you are sending a pointer across process boundaries. Pointers are only valid within the same process and are meaningless when sent/used in another process. In fact, you are sending the pointer value followed by a whole bunch of garbage bytes as themsgbuf.mtext is in fact not MSGSZ bytes in size (so technically invoking Undefined Behaviour).
What you need to do is to declare the buffer inline in the message. That is, change the message_buf definition to be:
typedef struct msgbuf {
long mtype;
char mtext[MSGSZ];
} message_buf;
And then strcpy straight into mtext:
strcpy(sbuf.mtext, "Did you get this?");
For clarity, below is the full program with the changes described:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MSGSZ 128
typedef struct msgbuf {
long mtype;
char mtext[MSGSZ];
} message_buf;
int
main (void)
{
int msqid;
key_t key = 129;
message_buf sbuf, rbuf;
if ((msqid = msgget(key, IPC_CREAT|0666)) < 0) {
perror("msgget");
exit(1);
}
if (fork() == 0) {
strcpy(sbuf.mtext, "Did you get this?");
sbuf.mtype = 1;
if (msgsnd(msqid, &sbuf, MSGSZ, IPC_NOWAIT) < 0) {
perror("msgsnd");
exit(1);
}
}
else {
sleep(1);
if (msgrcv(msqid, &rbuf, MSGSZ, 0, 0) < 0) {
perror("msgrcv");
exit(1);
}
printf("Forked version: %s\n", rbuf.mtext);
msgctl(msqid, IPC_RMID, NULL);
}
}

Working with semaphores and shared memory under Linux

I need to write a program that is creating a N amount of sub processes and every single one of them adds one to a shared memory variable. My idea is to use semaphores and shared memory, but the processes are not waiting for each other and the shared memory variable is also not working as I want it.
mydefs.h
#ifndef __MYDEFS__H__
#define __MYDEFS__H__
// Includes
#include <stdio.h>
#include <unistd.h>
#include <semaphore.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <memory.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <sys/shm.h>
#endif // __MYDEFS__H__
main.c
#include "mydefs.h"
#define PROC_COUNT 3
#define INITAL_MARKER_VALUE 0
#define PID_LEN 32
char mypid[PID_LEN];
int main()
{
int i, shm_id;
sem_t mutex;
if(sem_init(&mutex,1,1) < 0)
{
perror("semaphore initilization");
exit(0);
}
shm_id = shmget(IPC_PRIVATE, 4*sizeof(int), IPC_CREAT | 0666);
if (shm_id < 0) {
printf("shmget error\n");
}
int *shmpointer = shmat(shm_id,0,0);
memset(mypid, 0, sizeof(mypid));
sprintf(mypid, "%06d", getpid());
for(i = 0; i < PROC_COUNT; i++)
{
if (fork() == 0)
{
while(sem_wait(&mutex)!=0);
execl("slaveproc", "slaveproc", mypid, (char *)0);
shmpointer += 1;
sem_post(&mutex);
perror("\n Can't exec slave program. Cause ");
exit(1);
}
}
sleep(1);
printf("%d\n", *shmpointer);
return 0;
}
slaveproc.c
#include "mydefs.h"
int marker; // Marker value
int main(int argc, char *argv[])
{
master_pid = atoi(argv[1]);
printf("\n --------------------------------------");
printf("\n I'm the slave proc!");
printf("\n My pid: %d", getpid());
printf("\n My master's pid: %d", master_pid);
printf("\n --------------------------------------");
for(;;) pause();
return 0;
}
The problem (or at least "a problem") is that mutex is not in shared memory: it's allocated on the stack. When you fork(), the new process will have a completely separate copy from the old process, so calling sem_wait(&mutex) on one process will not affect the other process's mutex at all.
You should put mutex in the shared memory:
int main()
{
int i, shm_id;
shm_id = shmget(IPC_PRIVATE, sizeof(sem_t) + 4*sizeof(int), IPC_CREAT | 0666);
if (shm_id < 0) {
printf("shmget error\n");
}
int *shmpointer = shmat(shm_id,0,0);
sem_t *mutex = shmpointer;
shmpointer = (void*)shmpointer + sizeof(sem_t);
if(sem_init(mutex,1,1) < 0)
{
perror("semaphore initilization");
exit(0);
}
memset(mypid, 0, sizeof(mypid));
sprintf(mypid, "%06d", getpid());
for(i = 0; i < PROC_COUNT; i++)
{
if (fork() == 0)
{
while(sem_wait(mutex)!=0);
execl("slaveproc", "slaveproc", mypid, (char *)0);
shmpointer += 1;
sem_post(mutex);
perror("\n Can't exec slave program. Cause ");
exit(1);
}
}
sleep(1);
printf("%d\n", *shmpointer);
return 0;
}
You're also never writing to the memory in shmpointer (perhaps you meant (*shmpointer) += 1?), but I'll let you figure that out on your own.

How do I use mqueue in a c program on a Linux based system?

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

Resources