消息发送/接收API
msgsnd函数
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
参数
msgid: 由msgget函数返回的消息队列标识码, 也可以是通过ipcs命令查询出来的一个已经存在的消息队列的ID号
msgp:是一个指针,指针指向准备发送的消息,
msgsz:是msgp指向的消息长度, 注意:这个长度不含保存消息类型的那个long int长整型
msgflg:控制着当前消息队列满或到达系统上限时将要发生的事情,如果msgflg = IPC_NOWAIT表示队列满不等待,返回EAGAIN错误。
消息结构在两方面受到制约: (1)它必须小于系统规定的上限值(MSGMAX); (2)它必须以一个long int长整数开始,接收者函数将利用这个长整数确定消息的类型;
//消息结构参考形式如下:
struct msgbuf
{
long mtype; /* message type, must be > 0 */
char mtext[1]; /* message data, 可以设定为更多的字节数 */
};
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[1]; /* message data */
};
int main(int argc, char *argv[])
{
if (argc != 3)
{
fprintf(stderr, "Usage: %s <bytes> <type>\n", argv[0]);
exit(EXIT_FAILURE);
}
int len = atoi(argv[1]);
int type = atoi(argv[2]);
int msgid;
msgid = msgget(1234, 0);
if (msgid == -1)
ERR_EXIT("msgget");
struct msgbuf *ptr;
ptr = (struct msgbuf*)malloc(sizeof(long) + len);
ptr->mtype = type;
/*
if (msgsnd(msgid, ptr, len, IPC_NOWAIT) < 0)//非阻塞
ERR_EXIT("msgsnd");
*/
if (msgsnd(msgid, ptr, len, 0) < 0)//阻塞
ERR_EXIT("msgsnd");
return 0;
}
msgrcv函数
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
参数
msgid: 由msgget函数返回的消息队列标识码
msgp:是一个指针,指针指向准备接收的消息;
msgsz:是msgp指向的消息长度,这个长度不含保存消息类型的那个long int长整型
msgtype:它可以实现接收优先级的简单形式(见下图)
msgflg:控制着队列中没有相应类型的消息可供接收时将要发生的事(见下图)
返回值:
成功->返回实际放到接收缓冲区里去的字节数(注意: 此处并不包含msgbuf中的mtype的长度);
失败->返回-1;
msgtyp参数 | |
msgtyp=0 | 返回队列第一条信息 |
msgtyp>0 | 返回队列第一条类型等于msgtype的消息 |
msgtyp<0 | 返回队列第一条类型小于等于(<=)msgtype绝对值的消息,并且是满足条件的消息类型最小的消息(按照类型进行排序的顺序进行接收消息) |
msgflg参数 | |
msgflg=IPC_NOWAIT | 队列没有可读消息不等待,返回ENOMSG错误。 |
msgflg=MSG_NOERROR | 消息大小超过msgsz(msgrcv 函数的第三个参数)时被截断, 并且不会报错 |
msgtyp>0且msgflg=MSG_EXCEPT | 接收类型不等于msgtype的第一条消息 |
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[1]; /* message data */
};
#define MSGMAX 8192
int main(int argc, char *argv[])
{
int flag = 0;
int type = 0;
int opt;
while (1)
{
opt = getopt(argc, argv, "nt:");
if (opt == '?')
exit(EXIT_FAILURE);
if (opt == -1)
break;
switch (opt)
{
case 'n':
/*printf("AAAA\n");*/
flag |= IPC_NOWAIT;
break;
case 't':
/*
printf("BBBB\n");
int n = atoi(optarg);
printf("n=%d\n", n);
*/
type = atoi(optarg);
break;
}
}
int msgid;
msgid = msgget(1234, 0);
if (msgid == -1)
ERR_EXIT("msgget");
struct msgbuf *ptr;
ptr = (struct msgbuf*)malloc(sizeof(long) + MSGMAX);
ptr->mtype = type;
int n = 0;
if ((n = msgrcv(msgid, ptr, MSGMAX, type, flag)) < 0)
ERR_EXIT("msgsnd");
printf("read %d bytes type=%ld\n", n, ptr->mtype);
return 0;
}
getopt用法是解析命令行参数
#include <unistd.h>
int getopt(int argc, char * const argv[],
const char *optstring);
extern char *optarg;
extern int optind, opterr, optopt;
//示例: 解析 ./main -n -t 3 中的参数选项
//t后面的:表示t后面可以跟参数 参数保存在optarg中
int main(int argc, char *argv[])
{
while (true)
{
int opt = getopt(argc, argv, "nt:");
if (opt == '?')
exit(EXIT_FAILURE);
else if (opt == -1)
break;
switch (opt)
{
case 'n':
cout << "-n" << endl;
break;
case 't':
int n = atoi(optarg);
cout << "-t " << n << endl;
break;
}
}
}