msgrcv 中的错误:无效参数

发布于 2024-08-07 16:30:18 字数 447 浏览 1 评论 0原文

我正在unix系统上用C编写代码。我创建了一个消息队列服务器。每次我收到新消息时,我都会分叉,并且子进程会处理新客户端。服务器等待新的客户端。这是代码。

for (;;)
 {
      struct my_msgbuf buf;

      if (msgrcv (msqid, &(buf.mtype), sizeof (buf), 1, 0) == -1)
      perror ("msgrcv");


    if((pid = fork())<0)
    perror("fork");


    if(pid==0)
    {
     //child code
    }
}

现在代码适用于第一次迭代,但在第二次迭代时 msgrcv 给出以下错误 - msgrcv:无效参数而不是等待新消息。

I am writing a code in C on a unix system. I have created a message queue server. Each time I receive a new message I fork and the child process handles the new client. The server waits for new client. Here's the code.

for (;;)
 {
      struct my_msgbuf buf;

      if (msgrcv (msqid, &(buf.mtype), sizeof (buf), 1, 0) == -1)
      perror ("msgrcv");


    if((pid = fork())<0)
    perror("fork");


    if(pid==0)
    {
     //child code
    }
}

Now the code works for the first iteration but on the second iteration msgrcv gives the following error -
msgrcv: Invalid Arguments instead of waiting for new messages.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

软糯酥胸 2024-08-14 16:30:18

msgrcv 确实采用 msgsz 参数,但它不是 struct my_msgbuf 的大小,而是 中的字节数mtext[] 结构体的字段。

我认为您实际上不应该直接使用 struct msgbuf 。用适当的空间来定义自己的内容是正常的。按照您的方式,您的 buf 声明仅分配 1 个字节,然后代码告诉内核您有 sizeof buf 字节,但您没有。因此,该代码据说会调用未定义行为或 UB。

这可能会也可能不会解释 EINVAL,但人们应该始终修复已知的错误并重新测试,因为 UB 会污染进一步的分析......

msgrcv does take a msgsz parameter, but it's not the size of a struct my_msgbuf, rather, it's the number of bytes in the mtext[] field of the structure.

You aren't really supposed to use struct msgbuf directly, I think. It would be normal to define your own with appropriate space. The way you have it, your buf declaration allocates only 1 byte, and then the code tells the kernel that you have sizeof buf bytes, which you don't. As a result, the code is said to invoke Undefined Behavior or UB.

This may or may not explain the EINVAL but one should always fix the known bugs and retest because UB taints further analysis...

蝶…霜飞 2024-08-14 16:30:18

上面的代码有几个问题。首先,

msgrcv (msqid, &(buf.mtype), sizeof (buf), 1, 0)

第二个参数 &(buf.mtype) 不正确,因为进程期望接收完整的 buf 而不仅仅是 buf.mtype。如果 struct my_msgbuf 看起来像

struct my_msgbuf {
       long mtype;       /* message type, must be > 0 */
       char mtext[1];    /* message data */

};

那么 msgrcv() 应该看起来像

msgrcv (msqid, &buf, sizeof(buf), 1, 0);

现在代码在第一次迭代中有效,但在第二次迭代中有效
msgrcv 给出以下错误 - msgrcv:无效参数
等待新消息?

这是因为 msgrcv()fork() 之前执行,如果父进程不执行 msgsnd() 怎么办?

要解决此问题,您应该将 msgrcv() 语句保留在子进程内。还在 child & 内部运行 for 循环父进程不在子/父块之外。例如

struct my_msgbuf buf;

if((pid = fork())<0)
{
    /* @TODO set the buf.mtype here  */
    perror("fork");
    for(;;) /* use loop inside parent process to write into MQ continuously */
    {
        /* @TODO scan the data into  buf.mtext */
        /* @TODO msgsnd statement */
    }
}
else
{
    for(;;) /* use loop inside child process to read from MQ continuously */
    {
        if (msgrcv (msqid, &buf, sizeof (buf), 1, 0) == -1)
            perror ("msgrcv");
        printf("received data : %s\n", buf.mtext);
    }
}

There are few issues with the above code. Firstly here

msgrcv (msqid, &(buf.mtype), sizeof (buf), 1, 0)

second argument &(buf.mtype) is incorrect as process is expected to receive complete buf not only buf.mtype. If struct my_msgbuf looks like

struct my_msgbuf {
       long mtype;       /* message type, must be > 0 */
       char mtext[1];    /* message data */

};

then msgrcv() should look like

msgrcv (msqid, &buf, sizeof(buf), 1, 0);

Now the code works for the first iteration but on the second iteration
msgrcv gives the following error - msgrcv: Invalid Arguments instead
of waiting for new messages ?

That's because msgrcv() executes before fork(), what if parent process doesn't executes msgsnd() ?

To resolve this you should keep msgrcv() statement inside child process. Also run the for loop inside child & parent process not outside child/parent block. For e.g

struct my_msgbuf buf;

if((pid = fork())<0)
{
    /* @TODO set the buf.mtype here  */
    perror("fork");
    for(;;) /* use loop inside parent process to write into MQ continuously */
    {
        /* @TODO scan the data into  buf.mtext */
        /* @TODO msgsnd statement */
    }
}
else
{
    for(;;) /* use loop inside child process to read from MQ continuously */
    {
        if (msgrcv (msqid, &buf, sizeof (buf), 1, 0) == -1)
            perror ("msgrcv");
        printf("received data : %s\n", buf.mtext);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文