Skip to content

Instantly share code, notes, and snippets.

@hedenface
Created March 17, 2018 15:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save hedenface/cbbba717ff2d087862190963c37810bc to your computer and use it in GitHub Desktop.
Save hedenface/cbbba717ff2d087862190963c37810bc to your computer and use it in GitHub Desktop.
Kernel Message Queue Example
/*****************************
*
* queue.c
*
* Compile:
* gcc queue.c -o queue
*
* Execute:
* ./queue
*
* Why:
* Process starts up, fork()s
* twice, and then fills up the
* kmq and exits, and then
* the other procs clear the
* queue. Used to illustrate
* that the KMQ was FIFO to a
* customer. Thought it might
* be helpful otherwise.
*
*****************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/wait.h>
#include <sys/errno.h>
// small messages
struct msg_buf {
long mtype;
char mtext[16];
} msg;
int main(int argc,char **argv)
{
int msgqid = 0;
int rc = 0;
pid_t my_pid = 0;
// just want a static key
key_t key = 343463412;
// we need three processes
pid_t pid = fork();
if (pid == 0) {
pid = fork();
}
// use this as an identifier
my_pid = getpid();
// create the queue or attach
msgqid = msgget(key, 0600 | IPC_CREAT);
if (msgqid < 0) {
perror(strerror(errno));
printf("[%d] failed to create message queue with msgqid = %d\n", my_pid, msgqid);
return 1;
}
printf("[%d] message queue %d created\n", my_pid, msgqid);
// fill the queue
// only one of the procs will have a pid of 0 at this point
if (pid == 0) {
int i = 0;
for (i = 0; i < 30; i++) {
// message to send
msg.mtype = 1;
sprintf(msg.mtext, "%s%d", "message #", (i + 1));
printf("[%d] sending msg=[%s]\n", my_pid, msg.mtext);
// send the message to queue
// the last param can be: 0, IPC_NOWAIT, MSG_NOERROR, or IPC_NOWAIT|MSG_NOERROR.
rc = msgsnd(msgqid, &msg, sizeof(msg.mtext), 0);
if (rc < 0) {
perror(strerror(errno));
printf("[%d] msgsnd failed, rc = %d\n", my_pid, rc);
exit(1);
}
}
exit(0);
}
printf("[%d] sleep(2)..\n", my_pid);
sleep(2);
while (1) {
// check if the queue exists first
msgqid = msgget(key, 0600);
if (msgqid > 0) {
// read the message from queue
rc = msgrcv(msgqid, &msg, sizeof(msg.mtext), 0, IPC_NOWAIT);
if (rc < 0) {
if (errno != ENOMSG) {
perror( strerror(errno) );
printf("[%d] msgrcv failed, rc=%d\n", my_pid, rc);
}
break;
}
printf("[%d] received msg: %s\n", my_pid, msg.mtext);
printf("[%d] sleeping...\n", my_pid);
sleep(1);
} else {
break;
}
}
// remove the queue, but check if it still exists first
msgqid = msgget(key, 0600);
if (msgqid > 0) {
rc = msgctl(msgqid, IPC_RMID, NULL);
if (rc < 0) {
perror(strerror(errno));
printf("[%d] msgctl (return queue) failed, rc=%d\n", my_pid, rc);
return 1;
}
printf("[%d] message queue %d is gone\n", my_pid, msgqid);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment