【msgsnd/msgrcv系统调用】
功能描述:
在消息队列上进行收发消息。为了发送消息,调用进程对消息队列必须有写权能。接收消息时必须有读权能。
用法:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
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);
参数:
msqid:消息队列的识别码。
msgp:指向消息缓冲区的指针,此位置用来暂时存储发送和接收的消息,是一个用户可定义的通用结构,形态如下
struct msgbuf {
long mtype; /* 消息类型,必须 > 0 */
char mtext[1]; /* 消息文本 */
};
msgsz:消息的大小。
msgtyp:从消息队列内读取的消息形态。如果值为零,则表示消息队列中的所有消息都会被读取。
msgflg:用来指明核心程序在队列没有数据的情况下所应采取的行动。如果msgflg和常数IPC_NOWAIT合用,则在msgsnd()执行时若是消息队列已满,则msgsnd()将不会阻塞,而会立即返回-1,如果执行的是msgrcv(),则在消息队列呈空时,不做等待马上返回-1,并设定错误码为ENOMSG。当msgflg为0时,msgsnd()及msgrcv()在队列呈满或呈空的情形时,采取阻塞等待的处理模式。
返回说明:
成功执行时,msgsnd()返回0,msgrcv()返回拷贝到mtext数组的实际字节数。失败两者都返回-1,errno被设为以下的某个值
[对于msgsnd]
EACCES:调用进程在消息队列上没有写权能,同时没有CAP_IPC_OWNER权能
EAGAIN:由于消息队列的msg_qbytes的限制和msgflg中指定IPC_NOWAIT标志,消息不能被发送
EFAULT:msgp指针指向的内存空间不可访问
EIDRM:消息队列已被删除
EINTR:等待消息队列空间可用时被信号中断
EINVAL:参数无效
ENOMEM:系统内存不足,无法将msgp指向的消息拷贝进来
[对于msgrcv]
E2BIG:消息文本长度大于msgsz,并且msgflg中没有指定MSG_NOERROR
EACCES:调用进程没有读权能,同时没具有CAP_IPC_OWNER权能
EAGAIN:消息队列为空,并且msgflg中没有指定IPC_NOWAIT
EFAULT:msgp指向的空间不可访问
EIDRM:当进程睡眠等待接收消息时,消息已被删除
EINTR:当进程睡眠等待接收消息时,被信号中断
EINVAL:参数无效
ENOMSG:msgflg中指定了IPC_NOWAIT,同时所请求类型的消息不存在
转自: http://blog.csdn.net/liangjm_1984/article/details/2768014
msgsnd与msgrcv函数出现invalid参数的问题
今天写了一个小程序,使用了消息队列的msgsnd msgrcv函数,由msgsnd函数循环处理由终端输入的消息,然后把它发送到消息队列,而另一个进程则循环读取消息,进行处理。
这时,问题出现了,每次调用msgrcv函数的时候,它总是第一次调用成功,而第二次返回错误,察看errno=22,打印出来是invalid argument,无效参数。
凭它的说明,可以看出可能是我调用函数的时候参数错误,但为什么第一次能调用成功呢?
检查了一下,没看出问题。然后google之,发现许多人和我出现了同样的问题,但没有人给出解答。
自己鼓捣了好久,还是没搞定。
然后man 2 msgsnd,一下午不知打了多少遍了,这一次从头到尾一个字一个字的读了下去。
终于发现问题了。
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); man文档里有一句话:The mtext field is an array (or other structure) whose size is specified by msgsz
一直没认真去看,想当然的以为msgsz就是msgp的大小了,原来人家不是,自己自作多情了。。。
这么一个小问题花了我半个下午,但现在发现总比以后出错要好多了~
写出来,给那些第一次使用的朋友们看~~
把修改后的代码贴出来:
struct s_msg{
long type;
char mtext[256];
};
//snd
int main()
{
int mid;
if((mid=msgget(4446,IPC_CREAT|0666))==-1)
perr_exit("msgget:");
char buf[BUFSIZE];
memset(buf,'\0',BUFSIZE);
s_msg mymsg;
while(fgets(buf,BUFSIZE,stdin)!=NULL){
if(strlen(buf)<=2)continue;
buf[strlen(buf)]='\0';
if(sscanf(buf,"%d%s",&mymsg.type,mymsg.mtext)!=2)
perr_exit("Invalid input:");
if(msgsnd(mid,&mymsg,256,IPC_NOWAIT)) //msgsiz 为sizeof(mtext[]),而非sizeof(s_msg)
perr_exit("msgsnd:");
memset(buf,'\0',BUFSIZE);
}
return 0;
}