发送带有IPC队列的消息时标识符已删除(EIDRM)错误

时间:2009-08-16 19:17:23

标签: c ipc message-queue

我正在使用IPC队列来进行进程同步。

从IPC队列发送接收消息时,我总是得到EIDRM错误,但我可以看到队列中有ipcs。

我已经进行了2个小时的搜索,但我看不到错误。

以下代码是一个精简版本,它给出了同样的错误。

#define CLAVE 53543961
#define TAM_BUFFER 1024
#define PERMISOS 0777
#define DEBUG

int Cola_Mensages;
int msgqid;


typedef struct  {
    long mtype;
    char mtext[TAM_BUFFER];
}msgbuf;


int main (int argc, char *argv[]){
    msgbuf msg_ipc;
    int num_cli,i, i_aux;

    if(argc == 2){
    num_cli = atoi(argv[1]);
    }else{ 
    num_cli = 1;
    }


    //Creating the queue
    if(msgqid = msgget(CLAVE,PERMISOS|IPC_CREAT)<0){
        fprintf(stderr,"Problema al crear la cola de mensages IPC\n");
        exit(0);
    }

    if(msgqid < 0){
        fprintf(stderr,"Problema al crear la cola de mensages IPC\n");
        exit(0);
    }


    for(i = 0;i<num_cli;i++){
       //here i get the error
       i_aux=msgrcv(msgqid,&msg_ipc,TAM_BUFFER,1,0);
       if(i_aux == -1)
           fprintf(stderr,"Error enviando msg ipc %s \n",strerror(errno));
       }

    msg_ipc.mtype = 2;
    strcpy(msg_ipc.mtext,"COMIENZO");
    printf("Enviando msg\n");

       for(i = 0;i<num_cli;i++){
           printf("Enviado msg %d\n",i);
       //here i also get the same error
           if (msgsnd(msgqid,(char *) &msg_ipc,strlen(msg_ipc.mtext),0)!=0)
           {
              fprintf(stderr,"Ocurrio el error %s en msgsnd\n",strerror(errno));
              exit(4);
           }
       }   


    if (msgctl(msgqid,IPC_RMID,(struct msqid_ds *) NULL)<0)
    {
       fprintf(stderr,"Error al borrar la cola de mensajes de clave %d\n",CLAVE);
       exit(4);
    }

    return 0;

}

5 个答案:

答案 0 :(得分:4)

问题在于precedence and order of evaluation in C的处理不当,无论何时根据低于0的值评估msgget返回值:

if(msgqid = msgget(CLAVE,PERMISOS|IPC_CREAT)<0){
    fprintf(stderr,"Problema al crear la cola de mensages IPC\n");
    exit(0);
}

赋值运算符的优先级=低于比较值&lt;,这意味着您将msgget() < 0的结果分配给msgqid而不是检查(msgqid = msgget()) < 0

然后您应该用括号括起作业:

if((msgqid = msgget(CLAVE, PERMISOS | IPC_CREAT)) < 0){
    fprintf(stderr,"Problema al crear la cola de mensages IPC\n");
    exit(0);
}

答案 1 :(得分:1)

问题解决了。

我总是得到0作为队列的id,因为我在if条件中调用了msgget。我拿出了msgget并使用变量工作正常。

答案 2 :(得分:0)

只是一些想法,

您应该检查msgget()是否为-1,以检查它是否失败。

EIDRM代表“已删除标识符”,因此它与您在ipcs中看到的一致。

首先,您可能希望确保创建队列(请参阅ipcs),然后才能继续发送/接收消息。

答案 3 :(得分:0)

当您终止此进程时,消息队列是否会不存在?也就是说,每次测试时,您是否正在使用新队列?如果权限实际上是您认为的那样,我很好奇。

另外,如何发布一条可编辑的错误代码。我想看看你包含的文件。

答案 4 :(得分:0)

确定。关于这个问题的一个更新。

我第一次运行程序时,它运行得很好。如果我使用ipcs,我可以看到该程序创建了一个msqid为0的队列。程序删除队列没有问题。

第一次运行后,它停止工作并开始给出EIDRM错误,ipcs表示已创建队列,但它没有像第一次运行那样的msqid 0,它是一个随机数。即使我更改了ipckey,它也会发生这种情况,它只会创建另一个与不同的msquid相同的队列,并且会以同样的方式失败。