我们有一个 vxWorks 设计,它需要一个任务来处理来自两个消息队列 Q1 和 Q2 的消息。
我们想在两个队列上等待,无论哪个收到消息,都从队列中处理消息。
我们希望避免轮询队列或使用可能导致其他队列填满的超时值。
有没有办法做到这一点?
如果你使用命名管道(pipeDevCreate(), write(), read())而不是消息队列,你可以使用select()来阻塞,直到任一管道中有消息。
每当 select() 触发时,您都会处理高优先级管道中的所有消息。然后处理来自低优先级管道的单个消息。然后再次调用选择(循环)。
示例代码片段:
// Initialization: Create high and low priority named pipes
pipeDrv(); //initialize pipe driver
int fdHi = pipeDevCreate("/pipe/high",numMsgs,msgSize);
int fdLo = pipeDevCreate("/pipe/low",numMsgs,msgSize);
...
// Message sending thread: Add messages to pipe
write(fdHi, buf, sizeof(buf));
...
// Message processing Thread: select loop
fd_set rdFdSet;
while(1)
{
FD_ZERO(&rdFdSet);
FD_SET(fdHi, &rdFdSet);
FD_SET(fdLo, &rdFdSet;
if (select(FD_SETSIZE, &rdFdSet, NULL, NULL, NULL) != ERROR)
{
if (FD_ISSET(fdHi, &rdFdSet))
{
// process all high-priority messages
while(read(fdHi,buf,size) > 0)
{
//process high-priority
}
}
if (FD_ISSET(fdLo, &rdFdSet))
{
// process a single low priority message
if (read(fdLo,buf,size) > 0)
{
// process low priority
}
}
}
}
在vxWorks中,不能直接在多个队列上等待。但是,您可以使用操作系统事件(来自 eventLib)来实现此结果。 这是一个简单的代码片段:
MSG_Q_ID lowQ, hiQ;
void Init() {
// Task Initialization Code. This should be called from the task that will
// be receiving the messages
...
hiQ = msgQCreate(...);
lowQ = msgQCreate(...);
msgQEvStart(hiQ, VX_EV01); // Event 1 sent when hiQ receives message
msgQEvStart(loQ, VX_EV02); // Event 2 sent when loQ receives message
...
}
void RxMessages() {
...
UINT32 ev; // Event received
// Blocks until we receive Event 1 or 2
eventReceive(VX_EV01 | VX_EV02, EVENT_WAIT_ANY, WAIT_FOREVER, &ev);
if(ev & VX_EV01) {
msgQReceive(hiQ, ...);
}
if(ev & VX_EV02) {
msgQReceive(loQ, ...);
}
}
请注意,您需要修改该代码以确保排空所有队列,以防收到多条消息。
使用 semEvStart() 函数也可以将相同的机制应用于二进制信号量。