(本节笔记的实验代码,在这里)
1. 基本概念
消息队列是一个消息链表,每一条消息可看作一个记录,具有一定的格式的结构(struct)。一个进程向队列添加新消息,另一些进程可以从队列中读走消息,消息读走好就消失了。因此消息队列通讯作为IPC(进程间通信)存在。2. 函数学习
2.1 创建/打开消息队列
函数名:
msgget函数原型: man msgget
int msgget(key_t key, int msgflg);
函数功能:
打开或创建消息队列。
所属头文件:
<sys/types.h> <sys/ipc.h> <sys/msg.h>
返回值:
成功 :返回消息队列ID 失败 :返回-1
参数说明:
key :消息队列的键值。
msgflg :打开标志,如果使用了IPC_CREAT,则会新创建一个新的消息队列。
2.2 发送消息
函数名:msgsnd
函数原型: man msgsnd
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
函数功能:
往消息队列里发送消息。
所属头文件:
<sys/types.h> <sys/ipc.h> <sys/msg.h>
返回值:
成功 :返回0 失败 :返回-1
参数说明:
msqid :要发送到的消息队列的ID。
msgp :只想要发送的消息,一个结构体指针,该结构体为
struct msgbuf{
long mtype; /* 作为该消息的类型,其值>0 */
char mtext[1]; /* 该消息的内容 */
};
msgsz :消息内容的大小,特指mtext的size。
msgflag :标志位。
2.3 获取消息
函数名:msgrcv
函数原型: man msgrcv
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
函数功能:
从消息队列中取出消息。
所属头文件:
<sys/types.h> <sys/ipc.h> <sys/msg.h>
返回值:
成功 :返回实际接收的消息(mtext)数据大小 失败 :返回-1
参数说明:
msqid :要接收的消息队列的ID。
msgp :存放取出消息的指针。
msgsz :希望取出的消息的最大长度。
msgtyp :希望取出的消息类型。
若type = 0,返回队列的第一个消息;
若type > 0,返回消息类型为type的第一个消息;
若type < 0,返回队列中消息类型值小于等于type绝对值的消息,
如果这种消息有若干个,则取类型值最小的消息。
msgflag :标志位。2.4 删除消息队列
函数名:
msgctl
函数原型: man msgctl
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
函数功能:
控制消息队列。
所属头文件:
<sys/types.h> <sys/ipc.h> <sys/msg.h>
返回值:
成功 :根据的操作返回不同的值 失败 :返回-1
参数说明
msqid :要控制的消息队列的id。
cmd :要执行什么样的控制操作,如IPC_RMID表示删除。
*buf :获取Linux中描述共享内存的msqid_ds结构,该参数基本不用。
3. 综合实例
/* touch send.c */
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <stdlib.h>
#define MSG_SZ 1024
#define MSGKEYP "/arm/key_msq"
#define SHMKEYN "/arm/key_shm"
int *shm;
typedef struct msg_st{
long msg_type;
char msg_text[MSG_SZ];
}msg_ty;
int main()
{
int msqid;
int shmid;
key_t msg_key;
key_t shm_key;
long msgty;
char msgtx[MSG_SZ];
msg_ty msg_p;
/* 1.创建消息队列 */
msg_key = ftok(MSGKEYP,1);
shm_key = ftok(SHMKEYN,1);
msqid = msgget(msg_key,IPC_CREAT);
shmid = shmget(shm_key, sizeof(int), IPC_CREAT);
if(-1 == shmid)
{
printf("Creat the shm fail!\n");
exit(EXIT_FAILURE);
}
shm = (int *)shmat(shmid, NULL, 0);
*shm = 0;
/* 2.循环地从键盘中获得字符串,并把字符串发送到消息队列 */
while(1)
{
printf("Please input the text type, 0 for end!\n");
scanf("%ld", &msgty);
if(0 == msgty)
{
*shm = 1;
break;
}
printf("Please input the text content:\n");
scanf("%s", msgtx);
msg_p.msg_type = msgty;
strcpy(msg_p.msg_text,msgtx);
msgsnd(msqid, &msg_p, sizeof(msg_ty), 0);
}
/* 3.删除消息队列 */
msgctl(msqid, IPC_RMID, 0);
shmdt((const void *)shm);
sleep(10);
shmctl(shmid, IPC_RMID, 0);
return 0;
}
/* touch read.c */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/shm.h>
#define MSG_SZ 1024
#define MSGKEYP "/arm/key_msq"
#define SHMKEYN "/arm/key_shm"
int msqid;
int shmid;
int *shm;
typedef struct msg_st{
long msg_type;
char msg_text[MSG_SZ];
}msg_ty;
void child_process()
{
msg_ty msg_p;
while(1)
{
if(1 == *shm)
exit(0);
msgrcv(msqid, &msg_p, sizeof(msg_ty), 0, 0);
printf("The message is: %s\n", msg_p.msg_text);
}
}
int main()
{
int i;
int cpid;
key_t msg_key;
key_t shm_key;
long msgty;
char msgtx[MSG_SZ];
/* 1.创建消息队列 */
msg_key = ftok(MSGKEYP,1);
shm_key = ftok(SHMKEYN,1);
msqid = msgget(msg_key,IPC_EXCL);
shmid = shmget(shm_key, sizeof(int), IPC_CREAT);
if(-1 == shmid)
{
printf("Creat the shm fail!\n");
exit(EXIT_FAILURE);
}
shm = (int *)shmat(shmid, NULL, 0);
/* 2.创建三个进程,循环地从消息队列取出消息并打印 */
for(i = 0; i < 3; i++)
{
cpid = fork();
if(cpid < 0)
{
printf("Creat child process fail!\n");
}
else if(0 == cpid)
child_process();
}
return 0;
}