100分求助写U盘慢怎么办?
环境:i.mx25 ddr256 wince6.0
通过CAN总线接收数据(每秒10000字节),想把数据写到文件中(大概24000字节/s),直接接收CAN的数据没有丢数据的情况。数据接收是一个单独的线程,如果直接在接收数据后面进行写U盘操作,那么就会发生数据丢失现象.
单独开了一个写的线程,结果丢失的数据更多。想改进机制,较少丢失数据显现,我该怎么做。
求高手指点。
//CAN读线程函数
DWORD EM9170_CAN::ReadThreadFunc( LPVOID lparam )
{
EM9170_CAN *pCAN = (EM9170_CAN*)lparam;
DWORDdwEvtMask=0;
DWORDdwLen;
BOOLbResult;
while( 1 )
{
if( pCAN->m_nKillRxThread==1 )
{
SetEvent( pCAN->m_hReadCloseEvent );
break;
}
//Sleep(500);
if( WaitCANEvent( pCAN->m_hCAN, &dwEvtMask, 2000 ) )
{
if( dwEvtMask & 0x01 ) // 接收到数据包
{
//data available, so get it!
dwLen = 1;
while(dwLen > 0)
{
bResult = ReadFile( pCAN->m_hCAN, (char*)&pCAN->rxmsg, sizeof(CAN_PACKET), &dwLen, 0 );
// 对接收的数据进行处理,这里为简单的数据回发
if( dwLen > 0 )
{
pCAN->PackagePro( (char*)&pCAN->rxmsg, dwLen );
pCAN->m_Count ++;
}
}
// 处理完毕
}
if( dwEvtMask & 0x02 ) // 错误事件
{
// AfxMessageBox(_T("rece error"));
//当前情况下can1和can2必须连接can设备并且已经打开了才不会报错,如果之后报错分开了,推荐当错误产生时调用函数stopchip然后再startchip
}
}
else
{
Sleep(1);
}
}
return 0;
}
// CAN接收数据处理函数
int EM9170_CAN::PackagePro( char* Buf, int len )
{
// 对接收的数据进行处理,这里为简单的数据回发
PCAN_PACKET pmsg;
CString str;
double df_time;
CString str_data;
int i;
pmsg = (PCAN_PACKET)Buf;
DWORD Ms_timer;
Ms_timer = GetTickCount();
if(0 == First_Recv_Flag)
{
df_time = 0.0010;
First_Time = Ms_timer;
First_Recv_Flag = 1;
m_count_Recv = 0;
m_Str = _T("");
str = _T(" 0.000000 Start of measurement\r");
m_FRecordFile.Seek(0,CFile::end);
m_FRecordFile.WriteString( str );
}
else
{
df_time = (double)((double)(Ms_timer - First_Time) / 1000.000);
}
Recv_Buf[m_til].time = df_time;
Recv_Buf[m_til].ID = pmsg->dwID;
Recv_Buf[m_til].len = pmsg->dwDatLen;
memcpy(Recv_Buf[m_til].Rev_buf, pmsg->ucDat, pmsg->dwDatLen);
m_til ++;
m_til %= BUF_DEEP;
if(m_til == m_head)
{
if(0 == m_til) /*丢一包*/
{
m_til = BUF_DEEP - 1;
}
else
{
m_til -= 1;
}
AfxMessageBox(_T("rece buf full"));
Sleep(100);
}
else
{
}
return 0;
}
DWORD EM9170_CAN::WriteThreadFunc(LPVOID lparam)
{
EM9170_CAN *Write = (EM9170_CAN*)lparam;
CString str;
CString str_data;
int i;
while(1)
{
if(Write->m_head != Write->m_til)
{
str.Format(_T("%11.6f 1 %-16XRX d %d "),Write->Recv_Buf[Write->m_head].time,Write->Recv_Buf[Write->m_head].ID, Write->Recv_Buf[Write->m_head].len);
for(i = 0; i < Write->Recv_Buf[Write->m_head].len; i++)
{
str_data.Format(_T("%-2x "),Write->Recv_Buf[Write->m_head].Rev_buf[i]);
str += str_data;
}
str +=_T("\r");
Write->m_FRecordFile.Seek(0,CFile::end);
Write->m_FRecordFile.WriteString( str );
Write->m_head++;
Write->m_head %= BUF_DEEP;
Write->My_Max_Count ++;
if(Write->My_Max_Count > FILE_SIZE)
{
CString str_end = _T("End TriggerBlock\r");
Write->m_FRecordFile.Seek(0,CFile::end);
Write->m_FRecordFile.WriteString( str_end );
Write->m_FRecordFile.Close();
Write->m_File_Num ++;
Write->First_Recv_Flag = 0;
Write->My_Max_Count = 0;
CString File_Name = _T("");
CString PointFile;
File_Name.Format(_T("%d"), Write->m_File_Num);
if(1 == Write->m_Can_Num)
{
PointFile = _T("\\USBDisk\\CAN1RecordData") + File_Name + _T(".txt");
}
else
{
PointFile = _T("\\USBDisk\\CAN2RecordData") + File_Name + _T(".txt");
}
Write->m_FRecordFile.Open(PointFile,CFile::modeCreate| CFile::modeWrite);
CString str_head = _T("date Sun Oct 16 06:09:42 pm 2011\r\nbase hex timestamps absolute \r\ninternal events logged \r\nBegin Triggerblock Sun Oct 16 06:09:42 pm 2011\r");
Write->m_FRecordFile.Seek(0,CFile::end);
Write->m_FRecordFile.WriteString( str_head );
}
}
else
{
Sleep(1);
}
}
return 0;
}
[解决办法]
建议LZ开个大缓冲,间隔几秒写一次文件。
但这样频繁的写,会有问题的。U盘是 flash,会写坏的。
[解决办法]
用专门的CAN总线接收数据线程,接收到数据之后,调用回调函数,给主线程发送自定义消息,在主线程自定义消息处理函数中,先将CAN总线数据装入大缓存,待缓存满了之后写入一次FLASH。也可以考虑使用两级缓存。在CAN总线接收数据线程和回调函数中完成的工作要尽量少,保存数据的工作要挪到主线程的消息处理函数中。
[解决办法]