C语言 消息队列中的参数无效和标识符删除错误



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

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);
}

用户.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("nnhello 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提供了错误的权限,或者您忘记添加任何权限(使它们全部为零(,并且该消息队列仍然存在,具有这些权限。我自己也做过几次。这将在 msgget 中给出"权限被拒绝"错误,随后在 msgsnd 和 msgrcv 中给出"无效参数"。尝试另一个密钥。

请记住,消息队列是一个永久性的东西,类似于文件。创建它后,它会一直保留在您的计算机上,直到您将其删除(或重新启动计算机(,即使在程序退出后也是如此。

还有一件事:请记住,标准输出是行缓冲的,这意味着它实际上不会打印任何内容,直到它有一个换行符进行打印,我的建议是用printf("Whatevern")替换所有printf("nWhatever"),否则您可能看不到输出当您期望看到它时。

因此,在忍受了一天多(研究答案(之后,我的教授指出,我甚至在设置消息队列之前就将消息发送到用户进程。我所要做的就是增加睡眠(1(;从OSS发送消息后。

最新更新