ftok
通过文件路径 pathname 以及 proj_id 获得键值key(键值:消息队列的标识),只要文件路径和proj_id不变,key值就不变
头文件:
#include <sys/types.h>
#include <sys/ipc.h>
原型:
key_t ftok(const char *pathname, int proj_id);
参数:
char *pathname:文件路径(目录文件或是普通文件);
int proj_id:非0参数,用户自定义;
返回值:
成功,返回key值;
失败,返回-1,更新errno;
例程:
key_t key = ftok("./", 'a');
if(key < 0)
{
perror("ftok");
return -1;
}
printf("key = %x\n", key);
msgget
创建或打开消息队列对象
头文件:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
原型:
int msgget(key_t key, int msgflg);
参数:
key_t key:键值,提前约定或ftok函数创建获得;
int shmflg:设置消息队列的访问权限,参数如下:
IPC_CREAT:若消息队列对象不存在则创建,否则打开已经存在的消息队列对象;
IPC_EXCL:只有消息队列对象不存在的时候才会创建,已存在则返回错误;
IPC_NOWAIT:(非阻塞)如果本操作需要等待,则直接返回错误;
IPC_CREAT|0666:如果内核中不存在与key值相同的消息队列,则创建消息队列,并设置8进制权限(按位或)。如果存在,则直接返回消息队列标识符msqid;
返回值:
成功,返回消息队列标识 msqid;
失败,返回-1,更新errno;
例程:
int msqid = msgget(key, IPC_CREAT|0777);
if(msqid < 0)
{
perror("msgget");
return -1;
}
printf("msqid = %d\n", msqid);
msgsnd
向消息队列中发送数据
头文件:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
原型:
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
参数:
int msqid:消息队列id;
void *msgp:要发送的数据包,指向msgbuf的结构体指针,通用格式如下:
struct msgbuf {
long mtype; /* message type, must be > 0 */消息类型,必须大于0,接收进程根据此数值来匹配想要的数据;
char mtext[1]; /* message data */消息数据;
};
size_t msgsz:消息的大小,以字节为单位,即char mtext[1]的大小;
int msgflg:发送方式:
0:阻塞方式发送,如果消息队列满了,该函数阻塞;
IPC_NOWAIT:非阻塞方式发送,如果消息队列满了,则该函数不会阻塞,立即返回,并且更新errno == EAGAIN;
返回值:
成功,返回0;
失败,返回-1,更新errno;
例程:
#define N 128
struct msgbuf
{
long mtype;
char mtext[N];
};
int main(void){
struct msgbuf snd;
snd.mtype = 100;//接收进程根据此数值来匹配队列中想要的数据
if(msgsnd(msqid, &snd, N, 0) < 0)
{
perror("msgsnd");
return -1;
}
printf("发送成功\n");
}
msgrcy
从消息队列中接收数据
头文件:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
原型:
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
参数:
int msqid:消息队列id;
void *msgp:存储获取到的数据包,这个消息包的类型必须与想要接收的消息数据类型一致;
struct msgbuf {
long mtype; /* message type, must be > 0 */消息类型,必须大于0;
char mtext[1]; /* message data */消息;
};
size_t msgsz:读取的数据大小,以字节为单位,即char mtext[1]的大小;
long msgtyp:想要接收的消息类型:
msgtyp == 0; 读取消息队列中的第一个消息,遵循先进先出的原则;
msgtyp > 0; 读取消息队列中的第一个 msgtyp == mtype的消息;
msgtyp < 0; 读取消息队列中消息类型(mtype <= |msgtyp|)中类型值最小的第一个消息;
int msgflg:读取方式:
0:阻塞方式读取,如果消息队列中没有期望的数据,则该函数阻塞;
IPC_NOWAIT:非阻塞方式接收,如果消息队列中没有期望的数据,则函数不会阻塞,立即返回,并且更新errno == ENOMSG;
返回值:
成功,返回实际读取数据的字节数,大于0;
失败,返回-1;更新errno;
例程:
#define N 128
struct msgbuf
{
long mtype;
char mtext[N];
};
int main(void){
struct msgbuf rcv;
if(msgrcv(msqid, &rcv, N, 100, 0) < 0)
{
perror("msgrcv");
return -1;
}
printf("接收到了:%s\n", rcv.mtext);
}
msgctl
消息队列的操控
头文件:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
原型:
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
参数:
int msqid:消息队列id;
int cmd:控制方式;
IPC_RMID:删除消息队列,第三个参数,填NULL;
IPC_STAT:获取消息队列对象的内核结构体值,存放在第三个参数中;
IPC_SET:设置消息队列对象的内核结构体值;
struct msqid_ds *buf:指向msqid_ds结构的指针;
返回值:
成功,返回0;
失败,返回-1,更新errno;
例程:
if(msgctl(msqid, IPC_RMID, NULL) < 0)
{
perror("msgctl");
return -1;
}
应用例程1
通过消息队列实现,对讲机版本的进程对话;A发送给B,然后B发给A,然后A发给B
A进程
#include <stdio.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <string.h>
#define N 128
#define SND 100
#define RCV 101
struct msgbuf
{
long mtype;
char mtext[N];
};
int main(int argc, const char *argv[])
{
//key
key_t key = ftok("./", 'b');
if(key < 0)
{
perror("ftok");
return -1;
}
printf("key = %x\n", key);
//创建消息队列
int msqid = msgget(key, IPC_CREAT|0777);
if(msqid < 0)
{
perror("msgget");
return -1;
}
printf("msqid = %d\n", msqid);
//发送和接收数据包
struct msgbuf snd;
snd.mtype = SND;
struct msgbuf rcv;
while(1)
{
//发送数据
bzero(snd.mtext, N);
printf("请输入>>>");
fgets(snd.mtext, N, stdin);
if(msgsnd(msqid, &snd, N, 0)<0)
{
perror("msgsnd");
return -1;
}
if(strncasecmp(snd.mtext, "quit", 4) == 0)
{
break;
}
//接收数据
bzero(rcv.mtext, N);
if(msgrcv(msqid, &rcv, N, RCV, 0)<0)
{
perror("msgrcv");
return -1;
}
printf("对方说:%s\n", rcv.mtext);
if(strncasecmp(rcv.mtext, "quit", 4) == 0)
{
//删除消息队列
msgctl(msqid, IPC_RMID, NULL);
break;
}
}
return 0;
}
B进程
#include <stdio.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <string.h>
#define N 128
#define RCV 100
#define SND 101
struct msgbuf
{
long mtype;
char mtext[N];
};
int main(int argc, const char *argv[])
{
//key
key_t key = ftok("./", 'b');
if(key < 0)
{
perror("ftok");
return -1;
}
printf("key = %x\n", key);
//创建消息队列
int msqid = msgget(key, IPC_CREAT|0777);
if(msqid < 0)
{
perror("msgget");
return -1;
}
printf("msqid = %d\n", msqid);
//接收和发送数据包
struct msgbuf rcv;
struct msgbuf snd;
snd.mtype = SND;
while(1)
{
//接收数据
bzero(rcv.mtext, N);
if(msgrcv(msqid, &rcv, N, RCV, 0)<0)
{
perror("msgrcv");
return -1;
}
printf("对方说:%s\n", rcv.mtext);
if(strncasecmp(rcv.mtext, "quit", 4) == 0)
{
//删除消息队列
msgctl(msqid, IPC_RMID, NULL);
break;
}
//发送数据
bzero(snd.mtext, N);
printf("请输入>>>");
fgets(snd.mtext, N, stdin);
if(msgsnd(msqid, &snd, N, 0)<0)
{
perror("msgsnd");
return -1;
}
if(strncasecmp(snd.mtext, "quit", 4) == 0)
{
break;
}
}
return 0;
}
应用例程2
通过消息队列实现,打电话版本的进程对话;AB进程可以随时发送,随时接收
A进程
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#define N 128
struct msgbuf{
long mtype;
char mtext[N];
};
int flag = 0;
void *handler(void *arg)
{
struct msgbuf rcvbuf;
while(1)
{
if(msgrcv(*(int*)arg,&rcvbuf,N,2,0) < 0)
{
perror("msgrcv");
break;
}
printf("B say:%s\n",rcvbuf.mtext);
if(strncasecmp(rcvbuf.mtext,"quit",4) == 0)
{
flag = 1;
break;
}
}
pthread_exit(NULL);
}
void *handler_quit(void* arg)
{
while(1)
{
if(flag)
{
printf("exit progress\n");
exit(1);
}
}
pthread_exit(NULL);
}
int main(int argc, const char *argv[])
{
key_t key = ftok("./",'a');
if(key < 0)
{
perror("ftok");
return -1;
}
int msqid = msgget(key,IPC_CREAT|0664);
if(msqid < 0)
{
perror("msgget");
return -1;
}
pthread_t tid,tid_quit;
if(pthread_create(&tid,NULL,handler,(void*)&msqid) != 0)
{
perror("pthread_create");
return -1;
}
if(pthread_create(&tid_quit,NULL,handler_quit,NULL) != 0)
{
perror("pthread_create");
return -1;
}
struct msgbuf sndbuf;
sndbuf.mtype = 1;
while(1)
{
bzero(sndbuf.mtext,sizeof(sndbuf.mtext));
//printf("please input message-->");
fgets(sndbuf.mtext,N,stdin);
if(msgsnd(msqid,&sndbuf,N,0) < 0)
{
perror("msgsnd");
return -1;
}
printf("sending successful\n");
if(strncasecmp(sndbuf.mtext,"quit",4) == 0)
{
flag = 1;
break;
}
}
pthread_join(tid,NULL);
pthread_join(tid_quit,NULL);
return 0;
}
B进程
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#define N 128
struct msgbuf{
long mtype;
char mtext[N];
};
int flag = 0;
void *handler(void *arg)
{
struct msgbuf rcvbuf;
while(1)
{
if(msgrcv(*(int *)arg,&rcvbuf,N,1,0) < 0)
{
perror("msgrcv");
break;
}
printf("A say:%s\n",rcvbuf.mtext);
if(strncasecmp(rcvbuf.mtext,"quit",4) == 0)
{
flag = 1;
break;
}
}
pthread_exit(NULL);
}
void* handler_quit(void* arg)
{
while(1)
{
if(flag)
{
printf("exit progress\n");
exit(1);
}
}
pthread_exit(NULL);
}
int main(int argc, const char *argv[])
{
key_t key = ftok("./",'a');
if(key < 0)
{
perror("ftok");
return -1;
}
int msqid = msgget(key,IPC_CREAT|0664);
if(msqid < 0)
{
perror("msgget");
return -1;
}
pthread_t tid,tid_quit;
if(pthread_create(&tid,NULL,handler,(void*)&msqid) != 0)
{
perror("pthread_create");
return -1;
}
if(pthread_create(&tid_quit,NULL,handler_quit,NULL) != 0)
{
perror("pthread_create");
return -1;
}
struct msgbuf sndbuf;
sndbuf.mtype = 2;
while(1)
{
bzero(sndbuf.mtext,sizeof(sndbuf.mtext));
//printf("please input message-->");
fgets(sndbuf.mtext,N,stdin);
if(msgsnd(msqid,&sndbuf,N,0) < 0)
{
perror("msgsnd");
return -1;
}
printf("sending successful\n");
if(strncasecmp(sndbuf.mtext,"quit",4) == 0)
{
flag = 1;
break;
}
}
pthread_join(tid,NULL);
pthread_join(tid_quit,NULL);
return 0;
}
结果
本文链接:https://shengto.top/c/msg_routine.html
转载时须注明出处及本声明