簡體   English   中英

消息隊列(msgget-msgsnd-msgrcv)Linux-EIDRM

[英]Message queue (msgget - msgsnd - msgrcv) Linux - EIDRM

這是我的問題:我正在嘗試在服務器和客戶端之間實現消息隊列。 為此,我有兩個文件, msq-server.cmsq-client.c

我使用函數msgctl(msqid, IPC_RMID, &buf)退出服務器(例如,當我們要求他讀取消息隊列3次msgctl(msqid, IPC_RMID, &buf) )。

與往常一樣, msqid由msgget函數設置,而buf由struct msqid_ds buf定義。

官方的msgctl文檔說,對於讀者(客戶端),errno設置為EIDRM(43),並且我想在發生錯誤時顯示自定義錯誤。 但是,當我嘗試從關閉的服務器讀取消息時,函數msgrcv(msqid, &message, 64, 0, IPC_NOWAIT)返回EINVAL錯誤。 我認為msqid有罪

對於功能msgget

  • 在服務器上:我使用IPC_CREAT | IPC_EXCL |0666 IPC_CREAT | IPC_EXCL |0666標志
  • 在客戶端上:我使用IPC_EXCL | 0666 IPC_EXCL | 0666標志

感謝您的幫助

當您通過ms​​gctl()刪除消息隊列時,在讀取消息隊列時,msgrcv()將返回EIDRM(43)。

當您嘗試從不再存在的消息隊列中讀取消息時(因為已將其刪除),msgrcv()將返回EINVAL(22)。

請參見下面的示例。

服務器啟動,並將一條消息放入隊列。 然后等待。

客戶端啟動並讀取第一條消息,然后阻止等待從未到達的第二條消息。

服務器在客戶端等待第二條消息時刪除隊列,並看到EIDRM返回碼。

然后,客戶端嘗試再次讀取,並且由於沒有可用的隊列,因此會看到EINVAL。

msg_server.c

#include <sys/msg.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct msgbuf {
   long mType;
   char mText[50];
};

int main() {
   char txtBuf[50];
   int qId;
   key_t key;
   struct msgbuf msg, buf;
   struct msqid_ds msgCtlBuf;

   if ( ( key = ftok( "/tmp", 'C' ) ) == -1 ) {
      perror( "server: ftok failed:" );
      exit( 1 );
   }

   printf( "server: System V IPC key = %u\n", key );

   if ( ( qId = msgget( key, IPC_CREAT | 0666 ) ) == -1 ) {
      perror( "server: Failed to create message queue:" );
      exit( 2 );
   }

   printf( "server: Message queue id = %u\n", qId );

   strcpy( msg.mText, "This is a message" );
   msg.mType = 1;

   if ( msgsnd( qId, &msg, sizeof msg.mText, 0 ) == -1 ) {
      perror( "server: msgsnd failed:" );
      exit( 3 );
   }

   printf( "server: Message sent successfully\n" );

   printf( "server: waiting..." );
   sleep( 15 );
   printf( "server: done waiting. removing message queue...\n" );

   if ( msgctl( qId, IPC_RMID, &msgCtlBuf ) == -1 ) {
      perror( "server: msgctl failed:" );
      exit( 4 );
   }

   printf( "server: Message queue removed OK\n" );
}

msg_client.c

#include <sys/msg.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

struct msgbuf {
   long mType;
   char mText[50];
};

int main() {
   char txtBuf[50];
   int qId;
   key_t key;
   struct msgbuf msg, buf;
   struct msqid_ds msgCtlBuf;

   if ( ( key = ftok( "/tmp", 'C' ) ) == -1 ) {
      perror( "client: ftok failed:" );
      exit( 1 );
   }

   printf( "client: System V IPC key = %u\n", key );

   if ( ( qId = msgget( key, IPC_CREAT | 0666 ) ) == -1 ) {
      perror( "client: Failed to create message queue:" );
      exit( 2 );
   }

   printf( "client: Message queue id = %u\n", qId );

   if ( msgrcv( qId, &buf, sizeof msg.mText, 1, 0 ) == -1 )
      perror( "client: msgrcv failed:" );
   else
      printf( "client: Message received = %s\n", buf.mText );

   //
   // attempt read again and block on queue waiting for server to IPC_RMID
   //
   if ( msgrcv( qId, &buf, sizeof msg.mText, 1, 0 ) == -1 )
      perror( "client: msgrcv failed:" );
   else
      printf( "client: Message received = %s\n", buf.mText );

   printf( "client: errno = %d\n", errno );

   //
   // attempt read again but message queue should now be gone
   //
   if ( msgrcv( qId, &buf, sizeof msg.mText, 1, 0 ) == -1 )
      perror( "client: msgrcv failed:" );
   else
      printf( "client: Message received = %s\n", buf.mText );

   printf( "client: errno = %d\n", errno );
}

./msg_server和

[1] 668

服務器:系統V IPC密鑰= 1124335618

服務器:消息隊列標識= 262144

服務器:消息發送成功

./msg_client

客戶端:系統V IPC密鑰= 1124335618

客戶端:消息隊列標識= 262144

客戶端:收到消息=這是一條消息

服務器:正在等待...服務器:已完成等待。 正在刪除郵件隊列...

服務器:消息隊列已刪除,確定

客戶端:msgrcv失敗::標識符已刪除

客戶:errno = 43

客戶端:msgrcv失敗::無效參數

客戶端:errno = 22

[1] +出口33 ./msg_server

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM