Linux进程间通信——使用消息队列
(1)消息队列要发送和接收的结构体是有具体要求的,不是任何数据类型都可以,
struct msgbuf { long mtype; /* message type, must be > 0 */ char mtext[1]; /* message data */ };
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
结构体的第一个字节必须是 long型,发送时mtype必须大于0。后面字节类型可以自定义。
msgsnd:向msgid指定的消息队列末尾追加一个由msgp指向的消息,消息内容大小为msgsz。通常消息通过一个结构体进行描述,一般形式如下:
这个结构体可分为2个部分,mtype用以标识消息类型,mtext这个部分就是消息的内容,可以是你想要的描述消息内容的任何形式如数组,结构体等等。msgsnd,msgrcv里面所指定的消息大小msgsz指的是消息结构体内容mtext部分的长度,不包括mtype!消息类型必须大于0,至于为什么,看到msgrcv函数时就可以知道。
msgrcv:从msgid指定的消息队列里面取出由msgtyp指定类型的消息存放于msgp指向的空间。取出的消息数据大小由msgsz指定。成功时,返回拷贝到mtext中实际的字节数。
msgtyp有3种情况,用以控制取出消息的方式:
等于0:取出队列中的第一个消息,这样可以以先进先出的方式取消息(因为msgsnd都是把消息添加到消息队列的最后面)。
大于0:取出mtype于msgtyp相同的消息。
小于0:取出消息队列中mtype值小于等于msgtyp绝对值的所有消息中mtype值最小的那个消息。(假设mtype设定为消息的优先级,这种方式可以用于控制消息队列取消息的优先级)
从上面的描述可以看出这就是为什么消息结构体中mtype值为什么一定要大于0的原因。
(2)#define TEST_MSG_KEY 0x2FF
关于KEY,
linux输入命令:ipcs -q
打印出使用消息队列进行进程间通信的信息,打印一下看到下面的key值已经被占用,就不能用下面这些key
------ Message Queues --------
key msqid owner perms used-bytes messages
0x40000001 131072 root 666 16 2
0x000003ff 32769 root 666 8 1
0x000002fe 65538 root 666 0 0
0x000002fd 98307 root 666 0 0
(3) msgrcv时如果msgtyp置0,则只读取一次消息 等于0:取出队列中的第一个消息,这样可以以先进先出的方式取消息
#define TEST_SEM_KEY 0x30000001
#define TEST_MSG_KEY 0x2FF
typedef struct
{
int num;
int count;
}ShmData;
char *shmaddr;
char new_create=0;
int shm_id=-1;
ShmData *pData;
int sem_id=-1;
int sig_id=-1;
int main(int argc,char *argv[] )
{
int i=0;
int ret=-1;
int size_tmp;
size_tmp=sizeof(ShmData)*64;
int count=0;
/* 消息结构体 */
typedef struct _MSG
{
long mType;
int taskId; /* 消息内容 */
}MsgForm;
MsgForm Msg;
Msg.mType=01;
Msg.taskId=22;
sig_id=ipc_init_msgq(TEST_MSG_KEY);
if(sig_id<0)
{
printf("测试用例15:**********************消息队列创建失败**********\n");
}
else
{
printf("测试用例15:******消息队列创建成功*****sig_id=%d*****\n",sig_id);
}
{
ret=ipc_msgsnd(sig_id,&Msg,sizeof(Msg));
if(ret<0)
{
printf("测试用例16:**********************消息队列发送失败**********\n");
}
else
{
printf("测试用例16:**********************消息队列发送成功:mType=%dtaskId=%d\n",Msg.mType,Msg.taskId);
}
sleep(40);
}
int main(int argc,char *argv[] )
{
int i=0;
int ret=-1;
int size_tmp;
/* 消息结构体 */
typedef struct _MSG
{
long mType;
int taskId; /* 消息内容 */
}MsgForm;
MsgForm Msg;
//while(1)
{
sig_id=ipc_init_msgq(TEST_MSG_KEY);
if(sig_id<0)
{
printf("测试用例15:**********************消息队列创建失败**********\n");
}
else
{
printf("测试用例15:**********************消息队列创建成功sig_id=%d**********\n",sig_id);
}
while(1)
{
ret=ipc_msgrcv(sig_id,&Msg,sizeof(Msg));
if(ret<0)
{
printf("测试用例17:**********************消息队列接收失败*******ret=%d\n",ret);
}
else
{
printf("测试用例17:**********************消息队列接收成功=taskId=%dn",Msg.taskId);
}
sleep(1);
}
{
if(id<0)
{
return -1;
}
return msgsnd(id, msg, msglen, IPC_NOWAIT);
//if (msgsnd(msgQid, &msg, sizeof(MsgForm), IPC_NOWAIT) < 0)
}
int ipc_msgrcv(int id,char *msg,int msglen)
{
if(id < 0)
{
return -1;
}
return msgrcv(id, msg, msglen, 0, IPC_NOWAIT);
//msgrcv(g_taskd_info.taskMsgQid, &msg, sizeof(MsgForm), 0, IPC_NOWAIT)
}
- int msgget(key_t, key, int msgflg);
- int msgsend(int msgid, const void *msg_ptr, size_t msg_sz, int msgflg);
- struct my_message{
- long int message_type;
- /* The data you wish to transfer*/
- };
- int msgrcv(int msgid, void *msg_ptr, size_t msg_st, long int msgtype, int msgflg);
- int msgctl(int msgid, int command, struct msgid_ds *buf);
- struct msgid_ds
- {
- uid_t shm_perm.uid;
- uid_t shm_perm.gid;
- mode_t shm_perm.mode;
- };
- #include <unistd.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <errno.h>
- #include <sys/msg.h>
- struct msg_st
- {
- long int msg_type;
- char text[BUFSIZ];
- };
- int main()
- {
- int running = 1;
- int msgid = -1;
- struct msg_st data;
- long int msgtype = 0; //注意1
- //建立消息队列
- msgid = msgget((key_t)1234, 0666 | IPC_CREAT);
- if(msgid == -1)
- {
- fprintf(stderr, "msgget failed with error: %d\n", errno);
- exit(EXIT_FAILURE);
- }
- //从队列中获取消息,直到遇到end消息为止
- while(running)
- {
- if(msgrcv(msgid, (void*)&data, BUFSIZ, msgtype, 0) == -1)
- {
- fprintf(stderr, "msgrcv failed with errno: %d\n", errno);
- exit(EXIT_FAILURE);
- }
- printf("You wrote: %s\n",data.text);
- //遇到end结束
- if(strncmp(data.text, "end", 3) == 0)
- running = 0;
- }
- //删除消息队列
- if(msgctl(msgid, IPC_RMID, 0) == -1)
- {
- fprintf(stderr, "msgctl(IPC_RMID) failed\n");
- exit(EXIT_FAILURE);
- }
- exit(EXIT_SUCCESS);
- }
- #include <unistd.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <sys/msg.h>
- #include <errno.h>
- #define MAX_TEXT 512
- struct msg_st
- {
- long int msg_type;
- char text[MAX_TEXT];
- };
- int main()
- {
- int running = 1;
- struct msg_st data;
- char buffer[BUFSIZ];
- int msgid = -1;
- //建立消息队列
- msgid = msgget((key_t)1234, 0666 | IPC_CREAT);
- if(msgid == -1)
- {
- fprintf(stderr, "msgget failed with error: %d\n", errno);
- exit(EXIT_FAILURE);
- }
- //向消息队列中写消息,直到写入end
- while(running)
- {
- //输入数据
- printf("Enter some text: ");
- fgets(buffer, BUFSIZ, stdin);
- data.msg_type = 1; //注意2
- strcpy(data.text, buffer);
- //向队列发送数据
- if(msgsnd(msgid, (void*)&data, MAX_TEXT, 0) == -1)
- {
- fprintf(stderr, "msgsnd failed\n");
- exit(EXIT_FAILURE);
- }
- //输入end结束输入
- if(strncmp(buffer, "end", 3) == 0)
- running = 0;
- sleep(1);
- }
- exit(EXIT_SUCCESS);
- }