等待多个信号量或多个消息队列

时间:2018-12-11 01:35:44

标签: c unix cpu-architecture blocking epoll

  

在大多数UNIX实现中,进程可以在多个事件上阻塞。也就是说,该进程可以等待多个信号或多个消息队列,而不是等待单个信号或从单个消息队列接收消息。这种功能提供什么优势?您将如何实施?

现在,在所有人开始问这是否是我的学校作业之前,不是。这是我要参加的课程的推荐考试问题。

我的想法-像这样:

typedef struct QueueElement {
    int Sender;
    int Receiver;
    char Message[MAX_MSG_SIZE];
    int MessageSize;
} QueueElement;

QueueElement MessageQueue[NUM_OF_PROCESSES];



/* Send Message to receiving process queue number */
int SendMsg(int SenderId, int ReceiverId, char* Msg, int Size)
{
    /* Create Queue Element to Enqueue */
    QueueElement El = {
        .Sender = SenderId,
        .Receiver = ...
        .
        .
    };

    /* Enqueue element in queue specified by Receiver's Id */
    Enqueue(&(MessageQueue[ReceiverId]), El);
}



/* Get messages for process defined by ReceiverId, from any queue */
int RecvMsg(int* SenderId, int ReceiverId, char* Msg, int* size)
{
    int i;
    for (i=NUM_OF_PROCESSES; i>=0; i--)
    {
        /* If a message is available for receiving process, Dequeue element from queue */
        if (MessageQueue[i].Receiver = ReceiverId)
        {
            QueueElement El = Dequeue(&(MessageQueue[i]));
            *SenderId = El.Sender;
            strcpy(Msg, El.Message);
            .
            .
            .

            return TRUE;
        }
    }

    return FALSE;
}

现在,考虑4个并行运行的进程。他们将消息连续发送到消息队列1、2、3、4。现在,假设所有消息都已发送到进程2。这意味着进程2必须检查所有4个队列(1、2、3、4)中的消息。但是,如果不断添加新消息,则只会处理队列4中的消息。一个人如何摆脱饥饿的其他消息队列?

是否有更好的方法来处理?现代建筑如何处理这一问题?此解决方案的问题在于,如果邮件继续进入高优先级队列(NUM_OF_PROCESSES),则低优先级队列中的邮件将永远不会得到处理。

3 个答案:

答案 0 :(得分:2)

  

有没有更好的方法来解决这个问题?

是的。主要问题是您的代码根本没有等待,因此持续浪费CPU时间轮询。

更好的方法是将其放入内核,例如:

  • 当任务调用RecvMsg()时,内核可以自动执行if no messages in queue { tell scheduler this task should block until a message is received }(无竞争条件)

  • 任何调用SendMsg()的内核都可以自动执行if receiving task is blocked waiting for a message { tell scheduler the receiving task should be unblocked }(无竞争条件)

下一个问题是它仅等待消息。如果要等待(异步)打开文件,等待信号,等待时间过去或等待获取互斥锁,该怎么办?对于此问题,有两种可能的解决方案:

  • 在不同类型的事物上具有不同参数的可怕混乱(例如epoll_pwait())(对于某些事物仍然无法使用,例如等待互斥体)。

    < / li>
  • 在消息之上实现所有功能,因此您只需要等待消息即可。

第二种解决方案;您最终最终会用actor模型取代传统的过程编程。

答案 1 :(得分:1)

我认为您的代码无法按照提问者的意图来回答问题。扩展问题的范围:

通常,您可以调用类似read()的文件来读取文件描述符,并且它将阻塞直到有一些数据输入为止。但是,如果您有多个文件描述符,并且希望对所有文件描述符都进行阻塞,该怎么办?直到数据输入其中的任何一个?您无法使用仅包含单个文件描述符的简单read()来做到这一点。

  • 您需要哪种API?显示一个或一组可以让某人同时从多个来源读取的功能。

提示: select()正是这样做的。 google的好关键字包括“选择”,“多路复用”和“非阻塞I / O”。

答案 2 :(得分:0)

当使用不同优先级的消息队列时,阅读器将继续为高优先级队列服务,当耗尽时,它将移至较低优先级队列。如果不使用优先级,则可以使用线程并行服务队列,但不能保证消息在不同队列中出现的顺序。