【问题标题】:Posix message queue issue about sending message关于发送消息的 Posix 消息队列问题
【发布时间】:2020-12-08 19:59:49
【问题描述】:

我正在尝试使用 POSIX 消息队列将消息从子进程发送到父进程。在使用 fork() 创建子代之前,我创建了消息队列。我的代码应该从链接列表中获取单词并将它们发送给父级。但是,当我调用 mq_send 函数发送数据时,程序会卡在函数中,尝试从控制台获取输入并且永远不会停止。我已经在这个问题上工作了一天多,但我不知道该怎么做。我检查了代码的其他部分,它们都可以工作。只有 mq_send 函数会导致问题。有人可以告诉我这里有什么问题吗?也许我错过了一些东西。代码如下。

注意:我不能在此处包含所有代码。这里只有与问题相关的部分。另外,这是我在 stackoverflow 中的第一个问题,所以对于可能的格式错误,我深表歉意。

编辑:代码无法编译,因为我没有添加所有部分。我的问题仅基于发送消息的代码的最后一个 while 循环。这就是代码卡住的地方。

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <math.h>
#include <string.h>
#include <sys/types.h>
#include <mqueue.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <sys/ipc.h> 
#include <sys/msg.h> 
#include <unistd.h>

struct Node {
    char value[1024];
    int count;
    struct Node* next;
};

struct dataPackage {
    char word[1024];
    int count;
};


int main(int argcount, char** argvalues) {
    struct Node* headList[atoi(argvalues[1])];      // an array to hold linked lists   
    
    // creating fileCount number of linked lists and storing them
    for ( int i = 0; i < atoi(argvalues[1]); i++ ) {
        headList[i] = NULL;
    }

    // creating message queues
    mqd_t mqList[fileCount];
    char queueNames[5][1024];
    int n;
    // creating different names for different message queues

    strcpy(queueNames[0], "/queue1");
    strcpy(queueNames[1], "/queue2");
    strcpy(queueNames[2], "/queue3");
    strcpy(queueNames[3], "/queue4");
    strcpy(queueNames[4], "/queue5");

    // creating the message queues
    for (int i = 0; i < atoi(argvalues[1]); i++ ) {
        mqList[i] = mq_open(queueNames[i], O_RDWR | O_CREAT, 0666, NULL ); 
        printf("%i\n", mqList[i]); 
    }

    // creating child processes to process input files
    
    for (int i = 0; i < atoi(argvalues[1]); i++ ) {
        
        // creating a child process
        pid_t pid = fork();
        
        // child processes process seperate files
        if (pid == 0 ) {
            //printf("Before file process\n");
            // processing the file and creating the sorted linked lists
            processFile(fileNames[i], &headList[i]);
            
            // send linked list contents to parent process below
            struct dataPackage package;
            struct Node* tempHead = headList[i];
            
            while (tempHead != NULL) {
                // creating a package to send it to the parent process
                package.count = tempHead->count;
                strcpy(package.word, tempHead->value);
                
                // !!!!!this is the part where the program gets stuck!!!!!!!!
                n = mq_send(mqList[i], (char*) &package, sizeof(struct dataPackage), 0);
                tempHead = tempHead -> next;
            }
            // creating a message that will indicate the end of message queue
            package.count = -10;
            strcpy(package.word, "stop");
            n = mq_send(mqList[i], (char *) &package, sizeof(struct dataPackage), 0);
            exit(0);
        }   
        else {
            wait(NULL);
        }
    }

【问题讨论】:

  • char** argvalues struct Node* headList[argvalues[1]]; 大小为char* 的数组?你认为那条线有什么作用? i &lt; argvalues[1] intchar* 之间的比较?你没有从你的编译器那里得到一堵警告墙吗?一定要修复它们。 i &lt; atoi(argvalues[1]) 哦? I cannot include all the code here 为什么不呢?提供minimal reproducible example 可以更快地获得帮助。
  • 您的代码没有按照提供的那样编译,因此很难确定可能是什么实际问题。您需要提供minimal reproducible example
  • @KamilCuk 我在复制代码时很着急。它实际上是 i

标签: c posix message-queue ubuntu-18.04


【解决方案1】:

线

 struct Node* headList[argvalues[1]];

让我想知道你想要实现什么。 argvalues[1] 是指向字符的指针,而不是数字。你的编译器应该告诉你这一点。

如果要将第一个参数转换为数字,则应使用类似

int count;
if (sscanf(argvalues[1], "%d", &count) != 1) {
     /* does not look like a number */
     exit(1);
}
/* use count */

【讨论】:

  • 是的。我在复制代码时很着急。它实际上是 atoi(argvalues[1])。代码的目的是使用子进程读取和处理文件并将它们发送到父进程。我没有包含整个代码,因为并非所有部分都与我的问题相关。实际上只有代码中的最后一个循环与问题直接相关。
  • @suleyman6001 然后请编辑您的代码以使其编译。永远不要给我们修改过的代码。
【解决方案2】:

我没有看到 mq_receive 调用。系统施加了一个队列限制,一旦您的消息队列建立,您应该可以通过执行 cat /dev/mqueue/mymq 之类的操作来查看该限制。也就是说,我会检查您是否正确地使用了您的消息。我看到您的代码所做的事情是产生与 argvalues[1] 中的值一样多的子代,无论 argvalues[1] 中的值是多少,都有子代 mq_send,但父代只是等待子代死去而不消耗消息。

https://linux.die.net/man/7/mq_overview

【讨论】:

  • 子进程只处理给定的输入文件,使用消息队列生成并将其内容发送给父进程,并使用 exit(0) 终止它们。我没有包括接收部分,因为程序没有从 mq_send 函数向前移动。我认为问题就在那里。
  • 确切地说,“然后,默认情况下,mq_send() 会阻塞,直到有足够的空间可用于允许消息排队”,因此如果您不使用消息,您将卡在 mq_send 上。所以我会检查你的 mq_receive 逻辑。
  • 感谢您的回复。我现在将再次检查 mq_receive,但有一个问题。分配告诉我在子进程内发送消息,并且接收只能在所有子进程终止后发生。所以我将不得不不断地发送消息而不接收。你认为这可能吗?
  • 是的,有可能。即使关闭,消息也会保留在队列中。要清空消息队列,必须读出消息,或者销毁队列(取消链接)。实际上,您的问题可能是在没有正确 mq_receive 的情况下,您的程序之前运行的队列已满。例如您发送 3 次,但接收 2 次您的队列将在 # 运行后填满并阻止发送。此外,请检查 mq_overview 中提到的限制,如果您只有一条消息的空间并且需要发送三条消息,您也会被阻止。
【解决方案3】:

确保您尝试访问的队列中没有填满消息。

使用mq_getattr()mq_curmsgs 确定当前的消息数量。

【讨论】:

  • 您能给我们提供一个使用这种方法的例子吗?
猜你喜欢
  • 2020-11-27
  • 2019-03-17
  • 1970-01-01
  • 2020-04-18
  • 1970-01-01
  • 2013-03-21
  • 2019-07-10
  • 2011-07-10
  • 2016-11-26
相关资源
最近更新 更多