【问题标题】:Message queue (msgget - msgsnd - msgrcv) Linux - EIDRM消息队列 (msgget - msgsnd - msgrcv) Linux - EIDRM
【发布时间】:2018-09-09 06:58:29
【问题描述】:

这是我的问题: 我正在尝试在服务器和客户端之间实现消息队列。 为此,我有两个文件,msq-server.cmsq-client.c

我使用函数msgctl(msqid, IPC_RMID, &buf) 退出服务器(例如,当我们要求他读取消息队列 3 次,每秒一次,例如)。

像往常一样,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_EXCL | 0666 标志

感谢您的帮助

【问题讨论】:

    标签: c ipc message-queue shared-memory


    【解决方案1】:

    当您在通过 msgctl() 删除队列时读取消息队列时,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

    服务器:System V IPC 密钥 = 1124335618

    服务器:消息队列 id = 262144

    服务器:消息发送成功

    ./msg_client

    客户端:System V IPC 密钥 = 1124335618

    客户端:消息队列 id = 262144

    客户端:收到消息 = 这是一条消息

    服务器:等待...服务器:等待完成。删除消息队列...

    服务器:消息队列删除正常

    客户端:msgrcv 失败:: 标识符已删除

    客户端:errno = 43

    客户端:msgrcv 失败:: 无效参数

    客户端:errno = 22

    [1]+ 退出 33 ./msg_server

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-08-25
      • 2011-07-15
      • 1970-01-01
      • 2011-07-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-17
      相关资源
      最近更新 更多