linux进程间通信之消息队列 – David

ftok()

#include<sys/types.h>

#include<sys/ipc.h>

函数原型:

key_tftok(constchar*pathname,intproj_id);

参数:

pathname就是你指定的文件名(该文件必须是存在而且可以访问的),id是子序号,虽然为int,但是只有8个比特被使用(0-255)。

返回值:成功时候返回key_t类型的key值,失败返回-1

msgget

#include<sys/types.h>

#include<sys/ipc.h>

#include<sys/msg.h>

函数原型:intmsgget(key_tkey,intmsgflg);

函数描述:建立消息队列

参数:

msgget()函数的第一个参数是消息队列对象的关键字(key),函数将它与已有的消息队列对象的关键字进行比较来判断消息队列对象是否已经创建。而函数进行的具体操作是由第二个参数,msgflg控制的。它可以取下面的几个值:IPC_CREAT:如果消息队列对象不存在,则创建之,否则则进行打开操作;IPC_EXCL:和IPC_CREAT一起使用(用”|”连接),如果消息对象不存在则创建之,否则产生一个错误并返回。

返回值:

成功时返回队列ID,失败返回-1,错误原因存于error中

EEXIST(Queueexists,cannotcreate)EIDRM(Queueismarkedfordeletion)ENOENT(Queuedoesnotexist)ENOMEM(Notenoughmemorytocreatequeue)ENOSPC(Maximumqueuelimitexceeded)

msgsnd函数:将消息送入消息队列

#include<sys/types.h>

#include<sys/ipc.h>

#include<sys/msg.h

函数原型:intmsgsnd(intmsgid,structmsgbuf*msgp,intmsgsz,intmsgflg);

参数说明:

传给msgsnd()函数的第一个参数msqid是消息队列对象的标识符(由msgget()函数得到),第二个参数msgp指向要发送的消息所在的内存,第三个参数msgsz是要发送信息 的长度(字节数),可以用以下的公式计算:msgsz=sizeof(structmymsgbuf)-sizeof(long);第四个参数是控制函数行为的标志,可以取以下的值:0,忽略标志位;IPC_NOWAIT,如果消息队列已满,消息将不被写入队列,控制权返回调用函数的线程。如果不指定这个参数,线程将被阻塞直到消息被可以被写入。

smgbuf结构体定义如下:

structsmgbuf

{

longmtype;

charmtext[x];//长度由msgsz决定

}

msgflg可设置为IPC_NOWAIT。如果消息队列已满或其他情况无法送入消息,则立即返回EAGIN

返回:0onsuccess

-1onerror:errno=EAGAIN(queueisfull,andIPC_NOWAITwasasserted)EACCES(permissiondenied,nowritepermission)EFAULT(msgpaddressisn’taccessable–invalid)EIDRM(Themessagequeuehasbeenremoved)EINTR(Receivedasignalwhilewaitingtowrite)EINVAL(Invalidmessagequeueidentifier,nonpositivemessagetype,orinvalidmessagesize)ENOMEM(Notenoughmemorytocopymessagebuffer)

msgrcv函数:从消息队列中读取消息

#include<sys/types.h>

#include<sys/ipc.h>

#include<sys/msg.h>

函数定义:intmsgrcv(intmsgid,structmsgbuf*msgp,intmsgsz,longmsgtyp,intmsgflg);

参数:

函数的前三个参数和msgsnd()函数中对应的参数的含义是相同的。第四个参数mtype指定了函数从队列中所取的消息的类型。函数将从队列中搜索类型与之匹配的消息并将之返回。不过这里有一个例外。如果mtype的值是零的话,函数将不做类型检查而自动返回队列中的最旧的消息。第五个参数依然是是控制函数行为的标志,取值可以是:0,表示忽略;IPC_NOWAIT,如果消息队列为空,则返回一个ENOMSG,并将控制权交回调用函数的进程。如果不指定这个参数,那么进程将被阻塞直到函数可以从队列中得到符合条件的消息为止。如果一个client正在等待消息的时候队列被删除,EIDRM就会被返回。如果 进程在阻塞等待过程中收到了系统的中断信号,EINTR就会被返回。MSG_NOERROR,如果函数取得的消息长度大于msgsz,将只返回msgsz长度的信息,剩下的部分被丢弃了。如果不指定这个参数,E2BIG将被返回,而消息则留在队列中不被取出。当消息从队列内取出后,相应的消息就从队列中删除了。

msgbuf:结构体,定义如下:

structmsgbuf

{

longmtype;//信息种类

charmtest[x];//信息内容,长度由msgsz指定

}

msgtyp:信息类型。取值如下:

msgtyp=0,不分类型,直接返回消息队列中的第一项

msgtyp>0,返回第一项msgtyp与msgbuf结构体中的mtype相同的信息

msgtyp<0,返回第一项mtype小于等于msgtyp绝对值的信息

msgflg:取值如下:

IPC_NOWAIT,不阻塞

IPC_NOERROR,若信息长度超过参数msgsz,则截断信息而不报错。

返回值:

成功时返回所获取信息的长度,失败返回-1,错误信息存于error

Numberofbytescopiedintomessagebuffer-1onerror:errno=E2BIG(Messagelengthisgreaterthanmsgsz,noMSG_NOERROR)EACCES(Noreadpermission)EFAULT(Addresspointedtobymsgpisinvalid)EIDRM(Queuewasremovedduringretrieval)EINTR(Interruptedbyarrivingsignal)EINVAL(msgqidinvalid,ormsgszlessthan0)ENOMSG(IPC_NOWAITasserted,andnomessageexistsinthequeuetosatisfytherequest)

例子:

server.c

C代码

    <span><strong><em><spanstyle="font-size:small;">#include<stdio.h>#include<string.h>#include<stdlib.h>#include<errno.h>#include<unistd.h>#include<sys/types.h>#include<sys/ipc.h>#include<sys/stat.h>#include<sys/msg.h>#defineMSG_FILE"server.c"#defineBUFFER255#definePERMS_IRUSR|S_IWUSRstructmsgtype{longmtype;charbuffer[BUFFER+1];};intmain(){structmsgtypemsg;key_tkey;intmsgid;if((key=ftok(MSG_FILE,’a’))==-1){fprintf(stderr,"CreatKeyError:%s\a\n",strerror(errno));exit(1);}if((msgid=msgget(key,PERM|IPC_CREAT|IPC_EXCL))==-1){fprintf(stderr,"CreatMessageError:%s\a\n",strerror(errno));exit(1);}while(1){msgrcv(msgid,&msg,sizeof(structmsgtype),1,0);fprintf(stderr,"ServerReceive:%s\n",msg.buffer);msg.mtype=2;msgsnd(msgid,&msg,sizeof(structmsgtype),0);}exit(0);}</span></em></strong></span>
#include <stdio.h>#include <string.h>#include <stdlib.h>#include <errno.h>#include <unistd.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/stat.h>#include <sys/msg.h>#define MSG_FILE "server.c"#define BUFFER 255#define PERM S_IRUSR|S_IWUSRstruct msgtype {long mtype;char buffer[BUFFER+1];};int main(){struct msgtype msg;key_t key;int msgid;if((key=ftok(MSG_FILE,'a'))==-1){fprintf(stderr,"Creat Key Error:%s\a\n",strerror(errno));exit(1);}if((msgid=msgget(key,PERM|IPC_CREAT|IPC_EXCL))==-1){fprintf(stderr,"Creat Message Error:%s\a\n",strerror(errno));exit(1);}while(1){msgrcv(msgid,&msg,sizeof(struct msgtype),1,0);fprintf(stderr,"Server Receive:%s\n",msg.buffer);msg.mtype=2;msgsnd(msgid,&msg,sizeof(struct msgtype),0);}exit(0);}

client.c

C代码

    <span><strong><em><spanstyle="font-size:small;">#include<stdio.h>#include<string.h>#include<stdlib.h>#include<errno.h>#include<sys/types.h>#include<sys/ipc.h>#include<sys/msg.h>#include<sys/stat.h>#defineMSG_FILE"server.c"#defineBUFFER255#definePERMS_IRUSR|S_IWUSRstructmsgtype{longmtype;charbuffer[BUFFER+1];};intmain(intargc,char**argv){structmsgtypemsg;key_tkey;intmsgid;if(argc!=2){fprintf(stderr,"Usage:%sstring\n\a",argv[0]);exit(1);}if((key=ftok(MSG_FILE,’a’))==-1){fprintf(stderr,"CreatKeyError:%s\a\n",strerror(errno));exit(1);}if((msgid=msgget(key,PERM))==-1){fprintf(stderr,"CreatMessageError:%s\a\n",strerror(errno));exit(1);}msg.mtype=1;strncpy(msg.buffer,argv[1],BUFFER);msgsnd(msgid,&msg,sizeof(structmsgtype),0);memset(&msg,’\0′,sizeof(structmsgtype));msgrcv(msgid,&msg,sizeof(structmsgtype),2,0);fprintf(stderr,"Clientreceive:%s\n",msg.buffer);exit(0);}</span></em></strong></span>
#include <stdio.h>#include <string.h>#include <stdlib.h>#include <errno.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>#include <sys/stat.h>#define MSG_FILE "server.c"#define BUFFER 255#define PERM S_IRUSR|S_IWUSRstruct msgtype {long mtype;char buffer[BUFFER+1];};int main(int argc,char **argv){struct msgtype msg;key_t key;int msgid;if(argc!=2){fprintf(stderr,"Usage:%s string\n\a",argv[0]);exit(1);}if((key=ftok(MSG_FILE,'a'))==-1){fprintf(stderr,"Creat Key Error:%s\a\n",strerror(errno));exit(1);}if((msgid=msgget(key,PERM))==-1){fprintf(stderr,"Creat Message Error:%s\a\n",strerror(errno));exit(1);}msg.mtype=1;strncpy(msg.buffer,argv[1],BUFFER);msgsnd(msgid,&msg,sizeof(struct msgtype),0);memset(&msg,'\0',sizeof(struct msgtype));msgrcv(msgid,&msg,sizeof(struct msgtype),2,0);fprintf(stderr,"Client receive:%s\n",msg.buffer);exit(0);}

http://lobert.iteye.com/blog/1743256

前有阻碍,奋力把它冲开,运用炙热的激情,

linux进程间通信之消息队列 – David

相关文章:

你感兴趣的文章:

标签云: