我正在运行vxWorks 6.3,遇到了一个问题。我有一系列像在RTP中一样运行的任务。我创建一个任务,做一些事情,然后销毁任务。然后创建两个非常紧密的任务,做一些事情并摧毁它们。这些任务必须做一些疯狂的事情,比如malloc和释放内存。不幸的是,如果我这样做的次数足够多,其中一个任务将被困在信号量的内存(malloc和free)例程中。在free或malloc中,它总是在任务一开始就"丢失"的第二个任务。失败后,我仍然可以创建任务,并且仍然可以对内存进行malloc。失败的任务永远在等待信号灯。。。其他任务必须使用的信号量。
有人知道一项任务是如何被困在内存例程中的吗?
0x08265e58 malloc +0x2c : 0x082416f4 ()
0x08267e50 memPartAlloc +0x28 : 0x08241734 ()
0x08267e0c memPartAlignedAlloc+0x70 : 0x08267c04 ()
0x08267c7c memPartFree +0xfc : 0x08240654 ()
0x082753c0 semTake +0x90 : 0x08242534 ()
0x082752ec semUMTake +0xd8 : 0x08242514 ()
---- system call boundary ----
-> tw 0x69d21b0
NAME ENTRY TID STATUS DELAY OBJ_TYPE OBJ_ID OBJ_NAME
---------- ---------- ---------- ---------- ----- ---------- ---------- --------
tHttp631-2 0x827dbfc 0x69d21b0 PEND 0 SEM_M 0x6859650 N/A
Semaphore Id : 0x6859650
Semaphore Type : MUTEX
Task Queuing : PRIORITY
Pended Tasks : 1
Owner : 0x69d1a08 Deleted!
Options : 0xd SEM_Q_PRIORITY
SEM_DELETE_SAFE
SEM_INVERSION_SAFE
VxWorks Events
--------------
Registered Task : NONE
Event(s) to Send : N/A
Options : N/A
Pended Tasks
------------
NAME TID PRI TIMEOUT
---------- -------- --- -------
tHttp631-25502 69d21b0 120 0
value = 0 = 0x0
->
建议您在初始化时为最坏的情况分配足够的内存,然后在整个程序期间重复使用这些内存。特别是如果您确实有实时需求,因为malloc/free是非确定性操作,我还建议重新使用任务,而不是在运行时重新创建新任务,然后使用信号量或msgQueue在适当的时间启动适当的任务。所以你的程序流程可能看起来像这样:
initTime()
{
t1mem = malloc(t1memSize);
t2mem = malloc(t2memSize);
t3mem = malloc(t3memSize);
t1q = msgQCreate(qlen, msglen, MSG_Q_FIFO);
t2q = msgQCreate(qlen, msglen, MSG_Q_FIFO);
t3q = msgQCreate(qlen, msglen, MSG_Q_FIFO);
rspq = msgQCreate(qlen, msglen, MSG_Q_FIFO);
taskSpawn("t1", t1pri, ..., t1Entry, t1mem, t1q, rspq, ...);
taskSpawn("t2", t2pri, ..., t2Entry, t2mem, t2q, rspq, ...);
taskSpawn("t3", t3pri, ..., t3Entry, t3mem, t3q, rspq, ...);
runTime(t1sem, t2sem, t3sem, rspq);
msgQDelete(t1q);
msgQDelete(t2q);
msgQDelete(t3q);
msgQDelete(rspq);
free(t1mem);
free(t2mem);
free(t3mem);
}
runTime(MSG_Q_ID t1q, MSG_Q_ID t2q, MSG_Q_ID t3q, MSG_Q_ID rspq)
{
while (programRun)
{
tasksDone = 0;
msgQSend(t1q, t1start, msglen, 100, MSG_PRI_NORMAL);
if (msgQReceive(rspq, buf, msglen, errorCaseTimeout) == OK)
{
// check to make sure the msg is t1done...
// report error if it isn't...
msgQSend(t2q, t2start, msglen, 100, MSG_PRI_NORMAL);
msgQSend(t3q, t3start, msglen, 100, MSG_PRI_NORMAL);
for (int x = 0; x < 2; x++)
{
if (msgQReceive(rspq, buf, msglen, errorCaseTimeout) == OK)
{
// check to make sure the msg is t2done/t3done...
// report error if it isn't...
tasksDone++;
}
}
}
if (tasksDone == 2)
{
// everything is good... keep on running...
}
else
{
// a task didnt finish within the errorCaseTimeout time...
// report error or something, maybe set programRun to false...
}
}
}
t1Entry(void* mem, MSG_Q_ID q, MSG_Q_ID rspq)
{
while (programRun)
{
if (msgQReceive(q, buf, msglen, 100) == OK)
{
doTask1(mem);
msgQSend(rspq, t1done, msglen, 100, MSG_PRI_NORMAL);
}
}
}
t2Entry(void* mem, MSG_Q_ID q, MSG_Q_ID rspq)
{
while (programRun)
{
if (msgQReceive(q, buf, msglen, 100) == OK)
{
doTask2(mem);
msgQSend(rspq, t2done, msglen, 100, MSG_PRI_NORMAL);
}
}
}
t3Entry(void* mem, MSG_Q_ID q, MSG_Q_ID rspq)
{
while (programRun)
{
if (msgQReceive(q, buf, msglen, 100) == OK)
{
doTask3(mem);
msgQSend(rspq, t3done, msglen, 100, MSG_PRI_NORMAL);
}
}
}
显然,上面的代码不是很DRY,也不是所有的错误情况都得到了完全处理,但这是一个开始,很有可能确定地工作。
几个问题:
- 是否在RTP中创建/删除了所有任务
- 你是如何"破坏任务"的
- 当任务阻塞时,新的malloc/任务是在同一个RTP中创建的还是在不同的RTP中
- 你正在删除整个RTP吗
听起来你正在使用一个任务从一个任务中删除来销毁其他任务。如果是这种情况,那么有可能在内存操作过程中删除了任务。
由于这是RTP中的malloc操作,因此创建的每个RTP都包含自己的堆(malloc)信号量。我认为这将是正在持有的信号量。
我建议联系Wind River支持部门。这可能是他们熟悉的问题。
这可能与我遇到的问题有关,尽管我看到了不同的症状。在这两种情况下,信号量的所有者都将被删除。在我的例子中,我正在挂起tWebTask,并将其跟踪到web套接字上丢失的信号量所有者。
这是我SO问题的链接。