- 一、相关函数
- 1.1、创建:msgget()
- 1.2、发送:msgsend()
- 1.3、接收:msgrcv()
- 1.4、操作:msgctl()
- 二、简单测试
- 2.1、用单进程来测试消息队列的所有操作
- 头文件
#include1.1、创建:msgget()#include #include
功能:返回与键值对应的消息队列id,若没有则创建新的消息队列
int msgget(key_t key, int msgflg); key_t ftok(const char *pathname, int proj_id);
msgget
- key:消息队列的键值
可以自定义(>0),也可以由ftok生成
key 为 IPC_PRIVATE时将创建新的消息队列,且只能创建- msgflg:消息队列的权限
IPC_CREAT:创建新的消息队列
IPC_EXCL:与IPC_CREAT一同使用,表示如果要创建的消息队列已经存在,则返回 -1。
IPC_NOWAIT:读写消息队列要求无法满足时,不阻塞。
- 返回值
成功:消息队列id (msqid)
失败:-1
ftok:返回消息队列键值
- pathname:文件名
- projid:项目ID,必须为非0整数(0-255).
pathname通常设置为当前目录“.” ,若projid为’a’,则为"./a"文件
创建新的消息队列会初始化msqid_ds结构体
1.2、发送:msgsend()功能:往消息队列发送数据
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
- msqid:消息队列的id
- msgp:要发送消息的指针
- msgsz:消息的长度
- msgflg:当消息队列已满时的处理方式
IPC_NOWAIT:若消息队列已满,使用msgsend直接返回-1
0:若消息队列已满,则调用msgsend被挂起,直到可写入
- 返回值:
0 成功
-1 失败
msgp指向的结构为
struct msgbuf {
long mtype;
char mtext[1];
};
1.3、接收:msgrcv()
功能:从消息队列读取一个消息。如果读取成功,队列中的该消息将被删除。
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
- msqid:消息队列id
- msgp:要存放消息的指针
- msgsz:消息内容的长度(字节)
- msgtyp:消息的读取类型
0:返回队列中的第一个消息
>0:返回队列中种类(mtype)为msgtyp的第一个消息
<0:返回队列中小于等于负msgtyp类型值最小的一个- msgflg:消息不存在时的处理方式
IPC_NOWAIT:若没有符合的消息,则返回-1
MSG_NOERROR:若返回的消息比msgsz多,则消息就会截短,且不通知消息发送进程.
0:挂起调用进程直到有对应的消息
1.4、操作:msgctl()
- 返回值:
-1 失败
> -1 返回成功读出消息的字节数
功能·:控制消息队列
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
- msqid:消息队列id
- cmd:要执行的操作
IPC_STAT:将当前队列msqid_ds的结构存放在buf所指向的结构中
IPC_SET:按buf所指向的结构设置当前队列的msqid_ds
IPC_RMID:删除消息队列和其中的数据.- buf:存放消息队列属性
- 返回值
-1 失败
0 成功
- struct msqid_ds
struct msqid_ds {
struct ipc_perm msg_perm;
time_t msg_stime;
time_t msg_rtime;
time_t msg_ctime;
unsigned long __msg_cbytes;
msgqnum_t msg_qnum;
msglen_t msg_qbytes;
pid_t msg_lspid;
pid_t msg_lrpid;
};
- struct ipc_perm
struct ipc_perm {
key_t __key;
uid_t uid;
gid_t gid;
uid_t cuid;
gid_t cgid;
unsigned short mode;
unsigned short __seq;
};
二、简单测试
2.1、用单进程来测试消息队列的所有操作
#include#include #include #include #include #include #include typedef struct MsgBuf{ long mtype; char mtext[10]; }MsgBuf; void MsgStat(int, struct msqid_ds,char *);//打印消息队列属性 int main() { pid_t pid; key_t key; int ret; int msg_id,msg_flg; struct msqid_ds msginfo; MsgBuf msgbuf; key = ftok(".",'a'); printf("key = %dn",key); printf("pid = %dn",getpid()); msg_flg = IPC_CREAT|IPC_EXCL; msg_id = msgget(key,msg_flg|0666); if(msg_id == -1){ printf("msgget errorn"); return 0; } printf("msgid = %dn",msg_id); memset(&msginfo,0, sizeof(struct msqid_ds)); MsgStat(msg_id,msginfo,"msgget"); memset(&msgbuf,0, sizeof(MsgBuf)); msgbuf.mtype = 16; memcpy(msgbuf.mtext,"abcde",5); msg_flg = IPC_NOWAIT; ret = msgsnd(msg_id,&msgbuf, sizeof(msgbuf.mtext),msg_flg); if(ret == -1){ printf("msgsnd errorn"); msgctl(msg_id,IPC_RMID,NULL); return 0; } MsgStat(msg_id,msginfo,"msgsnd"); memset(&msgbuf,0, sizeof(MsgBuf)); msg_flg = MSG_NOERROR|IPC_NOWAIT; ret = (int)msgrcv(msg_id,&msgbuf,4,16,msg_flg); if(ret == -1){ printf("msgrcv errorn"); msgctl(msg_id,IPC_RMID,NULL); return 0; } else{ printf("从消息队列读到 %d 个字节t",ret); printf("消息是:%sn",msgbuf.mtext); } MsgStat(msg_id,msginfo,"msgrcv"); msginfo.msg_perm.uid = 8; msginfo.msg_perm.gid = 8; msginfo.msg_qbytes = 16386; ret = msgctl(msg_id,IPC_SET,&msginfo); if(ret == -1){ printf("msgctl errorn"); msgctl(msg_id,IPC_RMID,NULL); return 0; } MsgStat(msg_id,msginfo,"msgctl"); ret = msgctl(msg_id,IPC_RMID,NULL); return 0; } void MsgStat(int msg_id, struct msqid_ds msg_info,char *buf){ int ret; sleep(2);//方便观察 printf("n******************************************n"); printf("after %s: nn",buf); ret = msgctl(msg_id,IPC_STAT,&msg_info); if(ret == -1){ printf("get msg info errorn"); printf("******************************************n"); return; } printf("msg uid:%dt",msg_info.msg_perm.uid); printf("msg gid:%dn",msg_info.msg_perm.gid); printf("上一次使用msgsnd时间:%s",ctime(&(msg_info.msg_stime))); printf("上一次使用msgrcv时间:%s",ctime(&(msg_info.msg_rtime))); printf("上一次修改时间:%s",ctime(&(msg_info.msg_ctime))); printf("当前队列里的字节数为:%ldn",msg_info.msg_cbytes); printf("当前队列里的消息数量:%ldn",msg_info.msg_qnum); printf("队列的最大容量(字节数):%ldn",msg_info.msg_qbytes); printf("上次使用msgsnd的进程pid:%dn",msg_info.msg_lspid); printf("上次使用msgrcv的进程pid:%dn",msg_info.msg_lrpid); printf("******************************************n"); }
参考:man手册、《高质量嵌入式Linux C编程》梁庚 陈明 马小陆 编著 第265 -273页



