- 一、相关函数
- 1.1、创建:msgget()
- 1.2、发送:msgsend()
- 1.3、接收:msgrcv()
- 1.4、 *** 作:msgctl()
- 二、简单测试
- 2.1、用单进程来测试消息队列的所有 *** 作
- 头文件
#include
#include
#include
1.1、创建:msgget()
功能:返回与键值对应的消息队列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; /* message type, must be > 0 */
char mtext[1]; /* message data 不是真的为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; /* Ownership and permissions */
time_t msg_stime; /* Time of last msgsnd(2) */
time_t msg_rtime; /* Time of last msgrcv(2) */
time_t msg_ctime; /* Time of last change */
unsigned long __msg_cbytes; /* Current number of bytes in
queue (nonstandard) */
msgqnum_t msg_qnum; /* Current number of messages
in queue */
msglen_t msg_qbytes; /* Maximum number of bytes
allowed in queue */
pid_t msg_lspid; /* PID of last msgsnd(2) */
pid_t msg_lrpid; /* PID of last msgrcv(2) */
};
- struct ipc_perm
struct ipc_perm {
key_t __key; /* Key supplied to msgget(2) */
uid_t uid; /* Effective UID of owner */
gid_t gid; /* Effective GID of owner */
uid_t cuid; /* Effective UID of creator */
gid_t cgid; /* Effective GID of creator */
unsigned short mode; /* Permissions */
unsigned short __seq; /* Sequence number */
};
二、简单测试
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 = %d\n",key);
printf("pid = %d\n",getpid());
/*获取消息队列id*/
msg_flg = IPC_CREAT|IPC_EXCL;
msg_id = msgget(key,msg_flg|0666);
if(msg_id == -1){
printf("msgget error\n");
return 0;
}
printf("msgid = %d\n",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 error\n");
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 error\n");
msgctl(msg_id,IPC_RMID,NULL);
return 0;
}
else{
printf("从消息队列读到 %d 个字节\t",ret);
printf("消息是:%s\n",msgbuf.mtext);
}
MsgStat(msg_id,msginfo,"msgrcv");
/*修改消息队列最大容量 执行时需要加sudo提权*/
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 error\n");
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: \n\n",buf);
ret = msgctl(msg_id,IPC_STAT,&msg_info);
if(ret == -1){
printf("get msg info error\n");
printf("******************************************\n");
return;
}
printf("msg uid:%d\t",msg_info.msg_perm.uid);
printf("msg gid:%d\n",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("当前队列里的字节数为:%ld\n",msg_info.msg_cbytes);
printf("当前队列里的消息数量:%ld\n",msg_info.msg_qnum);
printf("队列的最大容量(字节数):%ld\n",msg_info.msg_qbytes);
printf("上次使用msgsnd的进程pid:%d\n",msg_info.msg_lspid);
printf("上次使用msgrcv的进程pid:%d\n",msg_info.msg_lrpid);
printf("******************************************\n");
}
参考:man手册、《高质量嵌入式Linux C编程》梁庚 陈明 马小陆 编著 第265 -273页
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)