日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 默认站点!

默认站点

當(dāng)前位置: 首頁 >

IPC--消息队列

發(fā)布時(shí)間:2023/11/27 25 豆豆
默认站点 收集整理的這篇文章主要介紹了 IPC--消息队列 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

消息隊(duì)列的特點(diǎn)

消息隊(duì)列是生命周期是隨進(jìn)程的,同時(shí)消息隊(duì)列可以實(shí)現(xiàn)的是消息的傳遞方向是雙向的。接受者和發(fā)送者時(shí)通過發(fā)送一個(gè)數(shù)據(jù)塊來進(jìn)性消息傳遞的,每個(gè)消息的數(shù)據(jù)類型不一樣依次來進(jìn)行區(qū)分我們該取哪個(gè)數(shù)據(jù)。消息隊(duì)列是基于消息的,并不是像管道一樣基于字節(jié)流,因此我可以一次放入或者取出一個(gè)數(shù)據(jù)塊,另外也不是先進(jìn)先出的。但是消息隊(duì)列也有一個(gè)最大的存儲(chǔ)上限(MSGMAX)。

IPC對(duì)象 數(shù)據(jù)結(jié)構(gòu)

我們可以理解,每個(gè)消息隊(duì)列也是一個(gè)數(shù)據(jù)存儲(chǔ)空間,系統(tǒng) 為了維護(hù)這個(gè)存儲(chǔ)空間,定義了一個(gè)數(shù)據(jù)結(jié)構(gòu)用于維護(hù)它的各種信息

struct ipc_perm {
key_t __key; /* Key supplied to xxxget(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 */
};

簡單的解釋其中的幾個(gè)數(shù)據(jù)
__key:類似于內(nèi)存描述符pc一樣,__key也是一個(gè)標(biāo)志某一個(gè)消息隊(duì)列的唯一標(biāo)識(shí)符,唯一的身份ID。
cuid:創(chuàng)建用戶id
cgid:創(chuàng)建用戶組id
mode:消息隊(duì)列相關(guān)權(quán)限

消息隊(duì)列結(jié)構(gòu)(/usr/include/linux/msg.h)

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 inqueue (nonstandard) */msgqnum_t       msg_qnum;     /* Current number of messagesin queue */msglen_t        msg_qbytes;   /* Maximum number of bytesallowed in queue */pid_t           msg_lspid;    /* PID of last msgsnd(2) */pid_t           msg_lrpid;    /* PID of last msgrcv(2) */
};

我們可以看到消息隊(duì)列結(jié)構(gòu)中的第一個(gè)內(nèi)容就是IPC數(shù)據(jù)的對(duì)象結(jié)構(gòu)體,可以這樣簡單的理解,我們的所有的消息隊(duì)列用一個(gè)隊(duì)列進(jìn)行維護(hù),這個(gè)隊(duì)列中就放置了很多關(guān)于消息隊(duì)列的各個(gè)信息。

消息隊(duì)列的創(chuàng)建

#include<sys/types.h>
#include<msg.h>
#include<ipc.h>
int msgget(key_t key, int msgflg);

其中的key可以理解為一個(gè)端口號(hào),我們可以這樣理解消息隊(duì)列也是一個(gè)存儲(chǔ)空間,把它比作是一個(gè)房間,而中國key就是房間的門,就是一個(gè)端口。接下來會(huì)介紹 一個(gè)函數(shù)ftok,由他來生成key。msgflg是操作消息隊(duì)列的方式,有兩個(gè)參數(shù)IPC_CREAT和IPC_EXCL,當(dāng)我們單獨(dú)的使用IPC_CREAT如果IPC不存在創(chuàng)建一個(gè)新的IPC,如果已經(jīng)存在則打開它;通常IPC_EXCL不單獨(dú)使用,我們是結(jié)合著IPC_CREAT一起使用,這樣做的結(jié)果是保證所得的對(duì)象是新建的,而不是已經(jīng)打開的。

程序詳解

下面的這個(gè)程序,寫了一個(gè)客戶端一個(gè)服務(wù)端,然后利用消息隊(duì)列進(jìn)行進(jìn)程間通信

封裝函數(shù)

#include"comm.h"int commMsgQueue(int flag)   //這里封裝了一個(gè)關(guān)于消息隊(duì)列的一個(gè)函數(shù),通過傳入?yún)?shù)即IPC_CREAT和IPC_EXCL來完成創(chuàng)建消息隊(duì)列和得到消息隊(duì)列的操作,這里加上static只是想讓這個(gè)函數(shù)在本文件中有效
{key_t key = ftok(".",0);   //第一個(gè)參數(shù)是路徑名,第二個(gè)參數(shù)是隨意給的一個(gè),這里我如果使用的是"./queue"就錯(cuò)誤//這里一開始寫0x6666,然后錯(cuò)了if(key < 0){printf("ftok error\n");return -1;}int queue = msgget(key,flag);   //key是生成的一個(gè)端口,后面的兩個(gè)宏時(shí)固有的參數(shù),0666是訪問 的權(quán)限if(queue == -1){printf("msgget error\n");return -2;}return queue;   //這里我開始返回值是0,,這個(gè)是錯(cuò)誤的,應(yīng)該返回的是消息隊(duì)列id,因?yàn)檫@個(gè)id以后會(huì)用到
}int creatMsgQueue()
{int ret = commMsgQueue(IPC_CREAT|IPC_EXCL|0666);if(ret < 0){printf("creatMsgQueue error\n");return -1;}return ret;
}int getMsgQueue()
{int ret = commMsgQueue(IPC_CREAT);if(ret < 0){printf("getMsgQueue error\n");return -1;}return ret;
}int desMsgQueue(int id)
{int flag = msgctl(id,IPC_RMID,NULL);if(flag < 0){printf("delete error\n");return -1;}return 0;
}int rcvMsg(int id,int who,char* recbuf)  //我們需要得到某一個(gè)隊(duì)列中的消息,所以這里傳入隊(duì)列號(hào),另外我們還需要傳入一個(gè)類型,這個(gè)類型是確認(rèn)某一個(gè)類型呢的
{msginfo buf;    int ret = msgrcv(id,&buf,sizeof(buf.mtext),who,0);strcpy(recbuf,buf.mtext);if(ret < 0){printf("rcvMsg error\n");return -1;}return 0;
}int sndMsg(int id,int who,char* sndbuf)  //標(biāo)記要往哪個(gè)隊(duì)列里面發(fā),標(biāo)記發(fā)送或者是接受的數(shù)據(jù)類型,who就是相當(dāng)于標(biāo)記數(shù)據(jù)類型
{int  ret;msginfo buf;buf.mtype = who;  //who是用來標(biāo)記數(shù)據(jù)類型 的strcpy(buf.mtext,sndbuf);  //這個(gè)時(shí)候我們應(yīng)該是從外面?zhèn)魅胍粋€(gè)數(shù)據(jù)//int msqid = getMsgQueue();//這里不能這樣使用,因?yàn)槲覀円粋€(gè)消息隊(duì)列中發(fā)送數(shù)據(jù)的時(shí)候,應(yīng)該在外面把這個(gè)隊(duì)列的id傳進(jìn)來//ret = msgsnd(id,(void*)&buf,sizeof(buf.mtext),0);  //雖然在這個(gè)函數(shù)中沒有使用到who,但是who傳進(jìn)來是為了標(biāo)記//上面的那個(gè)buf.mtype的    發(fā)數(shù)據(jù)的時(shí)候只需要標(biāo)記自己的類型就好了,所以這個(gè)函數(shù)中并沒有who選項(xiàng)用來標(biāo)記數(shù)據(jù)的//類型,但是在上面的取數(shù)據(jù)的時(shí)候卻需要who這個(gè)選項(xiàng) 用來識(shí)別我應(yīng)該取什么樣子的數(shù)據(jù)類型if(ret < 0){printf("sndMsg error\n");return -1;}return 0;
}

server

#include"comm.h"
int main()
{int id = creatMsgQueue();char  sndbuf[1024];char recbuf[1024];int i = 0;  printf("%d\n",id);
//  printf("creat queue success\n");while(i++ < 10){printf("請(qǐng)輸入:");scanf("%s",sndbuf);//  sleep(1);//  rcvMsg(id,CLIENT,recbuf);//  printf("%s",recbuf);//sleep(1);     sndMsg(id,SERVER,sndbuf);rcvMsg(id,CLIENT,recbuf);printf("client say # %s\n",recbuf);}desMsgQueue(id);return 0;
}

client

#include"comm.h"
int main()
{
//  int id = creatMsgQueue();char  sndbuf[1024];char recbuf[1024];int i = 0;int id = getMsgQueue(); 
//  printf("creat queue success\n");while(i++ < 10){//printf("請(qǐng)輸入:");//scanf("%s",sndbuf);//  sleep(1);//  rcvMsg(id,CLIENT,recbuf);//  printf("%s",recbuf);//sleep(1);     //sndMsg(id,CLIENT,sndbuf);rcvMsg(id,SERVER,recbuf);printf("server say # %s\n",recbuf);printf("請(qǐng)輸入 #");scanf("%s",sndbuf);//sleep(1);sndMsg(id,CLIENT,sndbuf);}//desMsgQueue(id);return 0;
}

comm.h

#ifndef __COMM_H__
#define __COMM_H__#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<stdio.h>
#include<string.h>typedef struct _msginfo{long mtype;char mtext[1024];
}msginfo;#define CLIENT 1
#define SERVER 2int getMsgQueue();
int creatMsgQueue();
int commMsgQueue(int flag);
int desMsgQueue(int id);
int commMsg();
int sndMsg(int id,int who,char* sndbuf);
int rcvMsg(int id,int who,char* recbuf);#endif

總結(jié)

以上是默认站点為你收集整理的IPC--消息队列的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得默认站点網(wǎng)站內(nèi)容還不錯(cuò),歡迎將默认站点推薦給好友。