Created
March 17, 2018 15:47
-
-
Save hedenface/cbbba717ff2d087862190963c37810bc to your computer and use it in GitHub Desktop.
Kernel Message Queue Example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/***************************** | |
* | |
* 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