消息中的无效参数和标识符已删除错误 queues

Invalid argument and Identifier removed error in message queues

我是新消息 queues。 基本上我在这里要做的是,我分叉并创建一个用户进程。在 fork() 之后,我向用户进程发送一条消息并等待从用户消息返回的消息。在实际程序中,我使用 while(1) 像这样循环 100 个用户进程。为了确保我一次只从一个特定的用户进程发送消息和接收消息,我使用用户进程 PID 作为消息接收中的第 4 个参数,并且在发送消息时将消息类型设为 =getpid()。我收到无效参数错误。我试图将权限位更改为 0666,但是当我这样做时,程序进入无限循环。当权限为 0777 时,我得到以下结果。这是我所做的最小工作代码。请原谅 headers.

的长列表

oss.c

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

//global variables
int shmid;
int msgid;
key_t shmkey;

int currentprocessPID;
int key= 11223344;
void startprocess();

struct mesg_buffer {
    long mesg_type;
    int mesg_text[4];
} message;
/*mesg.text[0]-Stores PID
mesg.text[1]-stores CPU time used by process seconds
mesg.text[2]= stores CPU time used by process nanoseconds
*/

int main(int argc, char **argv)
{
    if((msgid = msgget(key, 0777 | IPC_CREAT))==-1)
        perror("error in msg get");
    printf("going to fork");
                    pid_t pID = fork();
                    if (pID < 0)
                    {
                        perror("Failed to fork:");
                        exit(EXIT_FAILURE);
                    }

                    else if (pID == 0)
                    {
                        static char *args[]={"./user",NULL};
                        int status;
                        if(( status= (execv(args[0], args)))==-1)
                        {
                            perror("oss:failed to execv");
                            exit(EXIT_FAILURE);
                        }
                        else
                            printf("\n message sent to user sucessfully");
                    }

                    currentprocessPID=pID;

                    message.mesg_type = currentprocessPID;
                    if( msgsnd(msgid, &message, sizeof(message), 0)==-1)
                        perror("error in sending message to user process");
                    else
                    {
                        printf("\nmessage sent to process %d",currentprocessPID);

                    }


                if(msgrcv(msgid, &message, sizeof(message), currentprocessPID, 0)==-1)
                    perror("error in recieving message from user process");
                else
                {
                    int corpse,status;
                        while ((corpse = waitpid(message.mesg_text[0], &status, 0)) != message.mesg_text[0] && corpse != -1)
                        {
                            char pmsg[64];
                            snprintf(pmsg, sizeof(pmsg), "logParse: PID %d exited with status 0x%.4X", corpse, status);
                            perror(pmsg);
                        }

                    printf("\n%d process is done with its work",message.mesg_text[0]);
                }

    return 0;
    exit(0);
}

user.c

//copy same headers as above

int shmid;
int key= 11223344;
struct mesg_buffer {
    long mesg_type;
    int mesg_text[4];
} message;
void main()
{
        int pid=getpid();
        printf("\n\nhello from %d",getpid());
        int times=0,timen=0,zero=0,randomnum,timelimit,n=0,sum,i,locals=0,localn=0;

        int msgid = msgget(key, 0666 | IPC_CREAT);
        if(msgid==-1)
            {
            perror("User:error in message get");
            exit(0);
            }
                if(msgrcv(msgid, &message, sizeof(message), pid, 0)==-1)
                {
                    perror("User: Error in receieving message from OSS");
                    exit(0);
                }
                else
                {
                    printf("\nIn User: Data received ");

                        message.mesg_type = pid;
                        message.mesg_text[0]=pid;
                        message.mesg_text[1] = locals;
                        message.mesg_text[2]=localn;
                        message.mesg_text[3]=1;

                        if( msgsnd(msgid, &message, sizeof(message), 0)==-1)
                            perror("error in sending message back to OSS");
                        exit(0);

                }
    exit(0);

}

这是我得到的输出:

error in msg get: Permission denied
error in sending message to user process: Invalid argument
error in recieving message from user process: Invalid argument
going to fork

在大约 500 行的实际程序中,我使用了权限位 0666。在该程序中,当用户进程尝试从 oss 接收消息时,出现标识符已删除错误。

您可能 运行 该程序的早期版本,您在其中使用 IPC_CREAT 赋予了错误的权限,或者您根本忘记添加任何权限(将它们全部设置为零),并且 that 消息队列仍然存在,具有这些权限。我自己做过几次。这将在 msgget 中产生 "Permission denied" 错误,随后在 msgsnd 和 msgrcv 中产生 "Invalid argument" 错误。试试另一个键。

记住消息队列是永久的东西,类似于文件。一旦您创建了它,它就会保留在您的计算机上,直到您将其删除(或重新启动计算机),即使您的程序已经退出。

还有一件事:记住标准输出是行缓冲的,这意味着它实际上不会打印任何东西,直到它得到一个换行符来打印,我的建议是用 [=11 替换你所有的 printf("\nWhatever") =], 否则你可能看不到预期的输出。

所以在痛苦了一天多之后(研究答案)我的教授指出我在消息队列设置之前就将消息发送给用户进程。我所要做的就是添加 sleep(1);从oss发送消息后。