今天寫了一個小程序,使用了消息隊列的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;
}