Linux进程学习之:消息队列
消息队列是一个链式队列
创建消息队列需要用到msgget函数,函数声明在“sys/msg.h”头文件里
函数声明如下:
int msgget(key_t key, int msgflg);
msgget 函数有两个参数,第一个是key,可以传入宏 IPC_PRIVATE或者有ftok函数生成的key值,如果传入的是IPC_PRIVATE宏,消息队列将用于具有亲缘关系的进程间通信,如果是ftok函数生成的key值,则可以用于非亲缘关系的进程间通信,第二个参数是生成的消息队列的读写权限,一般使用0777
下面贴一段生成消息队列的代码
#include <iostream>
#include <sys/msg.h>
#include <stdlib.h>
using namespace std;
int main() {
int msgid = msgget(IPC_PRIVATE, 0777);
if ( msgid == -1) {
cout << "Create msgid failed ..." << endl;
return -1;
}
else
cout << "Create msgid successfully ..." << endl;
system("ipcs -q");
return 0;
}
最后的system(“ipcs -q”)的作用是将系统中所有的消息的队列信息打印出来,包括刚才创建的消息队列
删除消息队列用的msgctl函数,同样声明在“sys/msg.h”头文件中
声明如下:
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
第一个参数是告诉函数要操作的msg对象的id,第二个参数是告诉函数要怎么做,因为我们要删除创建的消息队列,所以传入的IPC_RMID宏,第三个参数直接传入空就可以
贴一个创建之后又删除消息队列的问题
#include <iostream>
#include <sys/msg.h>
#include <stdlib.h>
using namespace std;
int main() {
int msgid = msgget(IPC_PRIVATE, 0777);
if ( msgid == -1) {
cout << "Create msgid failed ..." << endl;
return -1;
}
else
cout << "Create msgid successfully, msgid = " << msgid <<endl;
system("ipcs -q");
// do something ...
//delete msg
int ret = msgctl(msgid, IPC_RMID, NULL);
if (ret == -1) {
cout << "delete msg failed ..." << endl;
return -2;
}
else
cout << "delete msg successfully ..." << endl;
system("ipcs -q");
return 0;
}
接下来说消息队列的消息发送和接受,消息发送用的msgsnd函数,接受用的是msgrcv函数,两个函数声明分别如下:
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);
1、msgsnd函数第一个参数是消息队列的id,第二个参数是一个指向用户自定义结构体的指针,不过这个结构体必须具有如下格式,第一个是参数类型,必须大于0,第二个是一个字符数组,大小可以自己定,不过也必须大于0:
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[1]; /* message data */
};
msgsnd函数的第三个参数是阻塞标志,0表示阻塞,还有其他的各种标志,可以自己去看
2、msgrcv函数和msgsnd函数的区别是只有第四个参数不一样,第四个参数是意思是当前队列消息的类型,需要明确才可以,如果输入的消息类型有误,程序就会被阻塞
接下来贴一个消息队列发送和接受消息的代码:
#include <iostream>
#include <sys/msg.h>
#include <stdlib.h>
#include <string.h>
using namespace std;
struct msgBuff {
long type;
char voltage[124];
};
int main() {
int msgid = msgget(IPC_PRIVATE, 0777);
if ( msgid == -1) {
cout << "Create msgid failed ..." << endl;
return -1;
}
else
cout << "Create msgid successfully, msgid = " << msgid <<endl;
system("ipcs -q");
msgBuff sendBuf, rcvBuf;
sendBuf.type = 100;
cout << "please input message: ";
cin >> sendBuf.voltage;
msgsnd(msgid, (void *)&sendBuf, sizeof(sendBuf.voltage), 0);
memset(rcvBuf.voltage, 0, sizeof(rcvBuf.voltage));
int ret = msgrcv(msgid, (void *)&rcvBuf, sizeof(rcvBuf.voltage), 100, 0);
if (ret == -1){
cout << "read rcvBuf failed ..." << endl;
}
else {
cout << "read rcvBuf successfully, rcvBuf = " << rcvBuf.voltage << endl;
}
//delete msg
ret = msgctl(msgid, IPC_RMID, NULL);
if (ret == -1) {
cout << "delete msg failed ..." << endl;
return -2;
}
else
cout << "delete msg successfully ..." << endl;
system("ipcs -q");
return 0;
}
运行以上代码,可以实现先往消息队列写入信息,接着从消息队列读取信息
接下来贴一个两个无亲缘关系的进程间通过消息队列通信的代码:
首先是写进程代码:
#include <iostream>
#include <sys/msg.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
using namespace std;
struct msgBuff {
long type;
char voltage[124];
};
int main() {
int key = ftok("./a", 1);
if (key < 0) {
cout << "Create key failed" << endl;
return -1;
}
else
cout << "Create key successfully, key = " << key << endl;
int msgid = msgget(key, IPC_CREAT | 0777);
if ( msgid == -1) {
cout << "Create msgid failed ..." << endl;
return -1;
}
else
cout << "Create msgid successfully, msgid = " << msgid <<endl;
system("ipcs -q");
msgBuff sendBuf;
sendBuf.type = 100;
while(1) {
cout << "please input message: ";
cin >> sendBuf.voltage;
msgsnd(msgid, (void *)&sendBuf, sizeof(sendBuf.voltage), 0);
}
int ret = msgctl(msgid, IPC_RMID, NULL);
if (ret == -1) {
cout << "delete msg failed ..." << endl;
return -2;
}
else
cout << "delete msg successfully ..." << endl;
system("ipcs -q");
return 0;
}
然后是读进程的代码
#include <iostream>
#include <sys/msg.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
using namespace std;
struct msgBuff {
long type;
char voltage[124];
};
int main() {
int key = ftok("./a", 1);
if (key < 0) {
cout << "Create key failed" << endl;
return -1;
}
else
cout << "Create key successfully, key = " << key << endl;
int msgid = msgget(key, IPC_CREAT | 0777);
if ( msgid == -1) {
cout << "Create msgid failed ..." << endl;
return -1;
}
else
cout << "Create msgid successfully, msgid = " << msgid <<endl;
system("ipcs -q");
msgBuff rcvBuf;
while(1) {
memset(rcvBuf.voltage, 0, sizeof(rcvBuf.voltage));
msgrcv(msgid, (void *)&rcvBuf, sizeof(rcvBuf.voltage), 100, 0);
cout << "read buff:" << rcvBuf.voltage << endl;
}
int ret = msgctl(msgid, IPC_RMID, NULL);
if (ret == -1) {
cout << "delete msg failed ..." << endl;
return -2;
}
else
cout << "delete msg successfully ..." << endl;
system("ipcs -q");
return 0;
}
运行以上代码:可以实现在写进程写入消息,在读进程读取信息的功能
接下里贴一个可以在server进程和client进程双向通信的代码:
首先是server代码:
#include <iostream>
#include <sys/msg.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <unistd.h>
using namespace std;
struct msgBuff {
long type;
char voltage[124];
};
int main() {
int key = ftok("./a", 1);
if (key < 0) {
cout << "Create key failed" << endl;
return -1;
}
else
cout << "Create key successfully, key = " << key << endl;
int msgid = msgget(key, IPC_CREAT | 0777);
if ( msgid == -1) {
cout << "Create msgid failed ..." << endl;
return -1;
}
else
cout << "Create msgid successfully, msgid = " << msgid <<endl;
system("ipcs -q");
int pid = fork();
if (pid > 0) {
msgBuff sendBuf;
sendBuf.type = 100;
while(1) {
cout << "please input message: ";
cin >> sendBuf.voltage;
msgsnd(msgid, (void *)&sendBuf, sizeof(sendBuf.voltage), 0);
}
}
else if (pid == 0){
msgBuff rcvBuf;
while(1) {
memset(rcvBuf.voltage, 0, sizeof(rcvBuf.voltage));
msgrcv(msgid, (void *)&rcvBuf, sizeof(rcvBuf.voltage), 200, 0);
cout << "server recive: " << rcvBuf.voltage << endl;
}
}
int ret = msgctl(msgid, IPC_RMID, NULL);
if (ret == -1) {
cout << "delete msg failed ..." << endl;
return -2;
}
else
cout << "delete msg successfully ..." << endl;
system("ipcs -q");
return 0;
}
然后是client代码:
#include <iostream>
#include <sys/msg.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <unistd.h>
using namespace std;
struct msgBuff {
long type;
char voltage[124];
};
int main() {
int key = ftok("./a", 1);
if (key < 0) {
cout << "Create key failed" << endl;
return -1;
}
else
cout << "Create key successfully, key = " << key << endl;
int msgid = msgget(key, IPC_CREAT | 0777);
if ( msgid == -1) {
cout << "Create msgid failed ..." << endl;
return -1;
}
else
cout << "Create msgid successfully, msgid = " << msgid <<endl;
system("ipcs -q");
int pid = fork();
if (pid > 0) {
msgBuff sendBuf;
sendBuf.type = 200;
while(1) {
cout << "please input message: ";
cin >> sendBuf.voltage;
msgsnd(msgid, (void *)&sendBuf, sizeof(sendBuf.voltage), 0);
}
}
else if (pid == 0){
msgBuff rcvBuf;
while(1) {
memset(rcvBuf.voltage, 0, sizeof(rcvBuf.voltage));
msgrcv(msgid, (void *)&rcvBuf, sizeof(rcvBuf.voltage), 100, 0);
cout << "server recive: " << rcvBuf.voltage << endl;
}
}
int ret = msgctl(msgid, IPC_RMID, NULL);
if (ret == -1) {
cout << "delete msg failed ..." << endl;
return -2;
}
else
cout << "delete msg successfully ..." << endl;
system("ipcs -q");
return 0;
}
运行以上代码,可以实现两个非亲缘关系进程间的双向通信,其中server进程写入消息的类型是100,读取消息的类型是200,而client进程读取消息的类型是100,写入消息的类型是200,这样双方就可以正常通信了。
还没有评论,来说两句吧...