/*
轮询实现。
因为消息队列和文件描述符没有关联,利用unix域套接字的作为中间层。
*/
#include <unistd.h>
#include <pthread.h>
#include <poll.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/socket.h>
#include <sys/msg.h>
const int NQ = 3;
const int MAXSZ = 512;
const int KEY = 0x1230;
// 线程函数参数结构体
struct threadinfo
{
int qid;
int fd;
};
// 消息队列结构体,XSI消息的固定结构方式
struct mymesg // message list's data struct , must be it.
{
long mbyte;
char text[MAXSZ];
};
// extern "C"
// {
// int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
// void *(*start_routine) (void *), void *arg);
// }
void *procmsg(void *p)
{
struct mymesg m;
struct threadinfo *ti = (struct threadinfo *)p;
int nRead;
for (;;)
{
memset(&m, 0, sizeof(m));
// 从指定ID的队列中获取一个消息,一直阻塞到有消息到
if ((nRead = msgrcv(ti->qid, &m, MAXSZ, 0, MSG_NOERROR)) < 0)
{
write(STDERR_FILENO, "msgrcv error", 12);
exit(-1);
}
// 向套接字写,通知父线程
if ((nRead = write(ti->fd, m.text, nRead)) < 0)
{
write(STDERR_FILENO, "write error", 11);
exit(-1);
}
}
}
int main(int argc, char *argv[])
{
int fd[2];
struct threadinfo ti[NQ];
pthread_t tid[NQ];
struct pollfd pollfd[NQ];
char buf[MAXSZ];
for (int i = 0; i < NQ;++i)
{
// 创建消息队列,KEY随机指定
if ((ti[i].qid = msgget(KEY+i, IPC_CREAT | 0666)) < 0)
{
write(STDERR_FILENO, "msgget error", 12);
exit(-1);
}
memset(buf, 0, MAXSZ);
sprintf(buf, "[%d]queue:%d\n", i, ti[i].qid);
write(STDOUT_FILENO, buf, strlen(buf));
// fd[0],fd[1]可读可写
if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd) < 0)
{
write(STDERR_FILENO, "socketpair error", 16);
exit(-1);
}
ti[i].fd = fd[0];
pollfd[i].fd = fd[1];
pollfd[i].events = POLLIN;
if (pthread_create(&tid[i], NULL, procmsg, &ti[i]) != 0)
{
write(STDERR_FILENO, "pthread_create error", 20);
exit(-1);
}
}
char qbuf[MAXSZ];
for (;;)
{
if (poll(pollfd, NQ, -1) < 0) // INFTIM
{
write(STDERR_FILENO, "poll error", 10);
exit(-1);
}
for (int i = 0; i < NQ; ++i)
{
if (pollfd[i].revents & POLLIN)
{
int nRead = read(pollfd[i].fd, buf, MAXSZ);
if (nRead < 0)
{
write(STDERR_FILENO, "read error", 10);
exit(-1);
}
buf[nRead] = '\0';
memset(qbuf, 0, sizeof(qbuf));
sprintf(qbuf, "[%d]queue recv:%s\n", ti[i].qid, buf);
write(STDOUT_FILENO, qbuf, strlen(qbuf));
}
}
}
return 0;
}
/*
测试文件。
*/
#include <sys/socket.h>
#include <poll.h>
#include <sys/msg.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
const int MAXSZ = 512;
struct mymesg
{
long mbyte;
char text[MAXSZ];
};
int main(int argc, char *argv[])
{
key_t key;
long qid;
if (argc != 3)
{
write(STDERR_FILENO, "Usage:./exe [keyid] [msg]\n", 26);
exit(-1);
}
key = strtol(argv[1], NULL, 0);
if ((qid = msgget(key, 0)) < 0)
{
write(STDERR_FILENO, "msgget error\n", 13);
exit (-1);
}
struct mymesg m;
memset(&m, 0, sizeof(m));
strncpy(m.text, argv[2], strlen(argv[2]));
m.mbyte = 1;
if (msgsnd(qid, &m, strlen(m.text), 0) < 0)
{
write(STDERR_FILENO, "msgsnd error\n", 12);
exit(-1);
}
return 0;
}