洗尘斋

三悬明镜垂鸿韵,九撩清泉洗尘心

常用链接

统计

最新评论

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;
}
//rcv
int
 main(int argc,char **argv)
{
    
int mid;
    
if((mid=msgget(4446,IPC_CREAT|0666))==-1)
        perr_exit(
"msgget:");
    s_msg mymsg;
    
while(1)
    {
        
if(msgrcv(mid,&mymsg,256,0,MSG_NOERROR)==-1)   //就是这里出错的,记住你了
                perr_exit(
"msgrcv");
        
if(mymsg.type!=4446)
            cout
<<mymsg.type<<" :"<<mymsg.mtext<<endl;
        
else {
            cout
<<"4446 quit\n";
            
break;    
        }
        memset(
&mymsg,0,sizeof(mymsg));
    }
    
return 0;
}

posted on 2007-09-19 17:52 芥之舟 阅读(12374) 评论(4)  编辑 收藏 引用 所属分类: unix

评论

# re: msgsnd与msgrcv函数出现invalid参数的问题 2008-07-18 23:45 jonny

我也碰到同样的问题了,多亏了楼主,谢啦。  回复  更多评论   

# re: msgsnd与msgrcv函数出现invalid参数的问题 2008-10-07 10:03 xwy48563526

这个linux程序设计书上已经写的很清楚了  回复  更多评论   

# re: msgsnd与msgrcv函数出现invalid参数的问题 2009-03-14 21:05 邓燕均

今天我也是 发现这个问题 ,琢磨了近一个小时 ,最后我是乱改了下,把sizeof(msg) 用一个特定的 数字替换,结果可以接收和发送。  回复  更多评论   

# re: msgsnd与msgrcv函数出现invalid参数的问题 2009-03-14 21:06 邓燕军

今天我也是 发现这个问题 ,琢磨了近一个小时 ,最后我是乱改了下,把sizeof(msg) 用一个特定的 数字替换,结果可以接收和发送。

/*客服端*/
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

struct msgbuf1
{
long msgto;
long msgfrom;
char buffer[100];
} ;

int main()
{
int rtrn, msqid ;
int pid;
struct msgbuf1 msg;


if ((msqid = msgget(0x888, IPC_CREAT|0600)) == -1)
{
perror("msgget");
exit(1);
}
switch(fork())
{
case -1:
perror("fork");
exit(1);
case 0:
execl("server3", "server3", NULL);
perror("execl");
exit(2);
}
pid =getpid();
while(1)
{
msg.msgto=1;
msg.msgfrom = pid;
write(fileno(stdout), "cmd>",5);
memset(msg.buffer, 0, sizeof(msg.buffer));
rtrn= read(fileno(stdin), msg.buffer, BUFSIZ);

if(rtrn == 0)
{
break;
}
else
{
msg.buffer[rtrn] = 0;
printf("client send: %s\n", msg.buffer);
rtrn=msgsnd(msqid, &msg, sizeof(msg), 0);
if (rtrn<0)
{
perror("msgsnd");
exit(2);
}
}
if((rtrn == msgrcv(msqid,&msg, sizeof(msg), pid, 0)) !=-1)
write(fileno(stdout), msg.buffer, strlen(msg.buffer));
}

msgctl(msqid, IPC_RMID, NULL);
return 0;
}


/*******************************/
/*服务器端*/
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>

struct msgbuf1
{
long msgto;
long msgfrom;
char buffer[BUFSIZ];
} ;
void process_msg(char *b,int len);

int main()
{
int rtrn;
int mid;
struct msgbuf1 msg;

if ((mid = msgget(0x888, IPC_CREAT|0600)) == -1)
{
perror("msgget");
exit(1);
}

while(1)
{
rtrn=msgrcv(mid, &msg, sizeof(msg), 1 , 0);
if(rtrn < -1)
{
perror("msgrcv");
exit(-1);
}
else if(rtrn ==0)
break;
else
{
process_msg(msg.buffer,strlen(msg.buffer));
printf("server received %s\n", msg.buffer);
msg.msgto = msg.msgfrom;
msg.msgfrom = 1;
if(msgsnd(mid,(struct msgbuf*)&msg, sizeof(msg), 0) ==-1)
{
perror("Server: msgsnd");
exit(3);
}
}
}
msgctl(mid, IPC_RMID,(struct msqid_ds*)0);

return 0;
}


void process_msg(char *b,int len)
{
int i = 0;
for(i = 0; i<len; i++)
if(isalpha(*(b+1)))
*(b+i) = toupper(*(b+i));

}
















  回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理