串口通信的读线程访问内存冲突

u011187092 2013-07-31 05:45:52
// com_thread.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "windows.h"
#include "iostream"
using namespace std;
//全局变量
HANDLE hMutex = NULL; //创建互斥信号量
HANDLE hComm = NULL; //定义串口句柄
OVERLAPPED m_overlapped;//Overlapped结构,重叠I/O
COMSTAT comstat; //串口传输数据的方式
DWORD m_dwCommEvents; //串口事件
bool sel = true;
HANDLE m_hReadThread = NULL;
HANDLE m_hWriteThread = NULL;
bool openport(TCHAR *portname)
{
hComm = CreateFile( portname, //串口号
GENERIC_READ| GENERIC_WRITE, //允许读写
0, //允许独占
0, //安全属性默认
OPEN_EXISTING, //只打开不创建
FILE_FLAG_OVERLAPPED, //异步I/O
NULL); //通讯设备不使用模板
if (hComm == INVALID_HANDLE_VALUE)
{
CloseHandle(hComm);
return FALSE;
}
else
return TRUE;
}

bool setDCB(int rate_arg)
{
DCB dcb;
int rate = rate_arg;
memset(&dcb,0,sizeof(dcb));
if (!GetCommState(hComm,&dcb))
{
return FALSE;
}

//set DCB
dcb.DCBlength = sizeof(dcb); //dcb长度
dcb.BaudRate = rate; //波特率
dcb.ByteSize = 8; //数据位采用八位
dcb.Parity = NOPARITY; //不采用奇偶校验
dcb.fParity = 0; //
dcb.StopBits = ONESTOPBIT; //采用一位停止位
dcb.fOutxCtsFlow = 0;
dcb.fOutxDsrFlow = 0;
dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcb.fDsrSensitivity = 0;
dcb.fRtsControl = RTS_CONTROL_DISABLE;
dcb.fOutX = 0;
dcb.fInX = 0;

/*--------------------------------------------------------------------*/
/* ----------------- misc parameters ----- */
dcb.fErrorChar = 0;
dcb.fBinary = 1;
dcb.fNull = 0;
dcb.fAbortOnError = 0;
dcb.wReserved = 0;
dcb.XonLim = 2;
dcb.XoffLim = 4;
dcb.XonChar = 0x13;
dcb.XoffChar = 0x19;
dcb.EvtChar = 0;

if(!SetCommState(hComm,&dcb))
{
return FALSE;
}
else
return TRUE;
}
//设置超时时间
bool setTimeOuts(DWORD ReadInterval,DWORD ReadTotalMultiplier,
DWORD ReadTotalConstant,DWORD WriteTotalMutiplier,
DWORD WriteTotalConstant)
{
COMMTIMEOUTS timeouts;
timeouts.ReadIntervalTimeout = ReadInterval;
timeouts.ReadTotalTimeoutConstant = ReadTotalConstant;
timeouts.ReadTotalTimeoutMultiplier = ReadTotalMultiplier;
timeouts.WriteTotalTimeoutConstant = WriteTotalConstant;
timeouts.WriteTotalTimeoutMultiplier = WriteTotalMutiplier;
if (!SetCommTimeouts(hComm,&timeouts))
{
return FALSE;
}
else
return TRUE;

}
//写进程
DWORD WINAPI MyThread2(LPVOID lParam)
{
char *m_szWriteBuffer = new char[1];
BOOL bWrite = TRUE;
BOOL bResult = TRUE;
DWORD dwError= 0;
DWORD ByteSend = 0;
HANDLE m_hWriteEvent = NULL;
ResetEvent(m_hWriteEvent);//将指定的事件对象设置为无信号状态
while(true)
{
WaitForSingleObject(hMutex,INFINITE);
Sleep(1000);
cout<<"写串口->";
bResult = ClearCommError(hComm,&dwError,&comstat);//清空错误数据
if (bWrite)
{
printf("Write:");
scanf("%s",m_szWriteBuffer);
bResult = WriteFile(hComm,m_szWriteBuffer,
strlen(m_szWriteBuffer)+1,&ByteSend,&m_overlapped);
if (!bResult)
{
dwError = GetLastError();
switch (dwError)
{
case ERROR_IO_PENDING:
{
bWrite = FALSE;
break;
}
default:
printf("WriteFile()");
}//end switch()
}//end if(!bResult)
if (!bWrite)//写入失败
{
bWrite = TRUE;
bResult = GetOverlappedResult(hComm,
&m_overlapped,// Overlapped structure
&ByteSend,// Stores number of bytes sent
TRUE);// Wait flag
//deal with the error codes
if (!bResult)
{
printf("GetOVerLappedResult() is writefile()");
}
}//end if(!bWrite)
}//end if(bWrite)
ReleaseMutex(hMutex);
}//while(true)
delete m_szWriteBuffer;
return 0;
}

//读进程
DWORD WINAPI MyThread1(LPVOID lParam)
{
BOOL bRead = TRUE;
BOOL bResult = TRUE;
DWORD deError = 0;
DWORD BytesRead = 0;
char RecvBuff = '0';
while(true)
{
WaitForSingleObject(hMutex,INFINITE);
Sleep(2000);
cout<<"读串口->Read :";
//printf();
while(true)
{
bResult = ClearCommError(hComm,&deError,&comstat);//清空错误数据
if (comstat.cbInQue == 0)//如果输入缓冲区为空
break;
if (bRead)
{
bResult = ReadFile(hComm, //串口句柄
&RecvBuff, //数据接收缓冲区
1, //每次读取一个字节
&BytesRead, //实际读取的数据数量
&m_overlapped); //异步I/O
printf("%c",RecvBuff);
if (!bResult)
{
switch(deError = GetLastError())
{
case ERROR_IO_PENDING: //重叠I/O操作进行中
bRead = FALSE;
break;
default:
break;
}
}
else
bRead = TRUE;
}
if (!bRead)
{
bRead = TRUE;
bResult = GetOverlappedResult(hComm,&m_overlapped,&BytesRead,TRUE);
}
}
printf("\n");
ReleaseMutex(hMutex);
}
return 0;
}
int main()
{
bool open;
open = openport(_T("com1"));
if (open)
{
cout<<"openport success"<<endl;
}
if (setDCB(9600))
{
cout<<"setDCB success"<<endl;
}
if (setTimeOuts(0,0,0,0,0))
{
cout<<"set timeouts success"<<endl;
}

//清空这个串口的说有操作
PurgeComm(hComm,
PURGE_RXABORT | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR);
//创建互斥信号量
hMutex = CreateMutex(NULL,FALSE,_T("read or write"));
//创建写串口线程   
m_hWriteThread = CreateThread(NULL,0,MyThread2,0,0,NULL);
//创建读串口线程
m_hReadThread = CreateThread(NULL,0,MyThread1,0,0,NULL);
while (true)
{ }
CloseHandle(m_hReadThread);
CloseHandle(m_hWriteThread);
CloseHandle(hMutex);
CloseHandle(hComm);
return 0;
}
...全文
97 点赞 收藏 7
写回复
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
向立天 2013-08-01
代码没仔细看 不过看你是异步操作的 改成同步试试
回复
u011187092 2013-08-01
引用 4 楼 xianglitian 的回复:
[quote=引用 2 楼 u011187092 的回复:] com_thread.exe 中的 0x63ae30d7 处最可能的异常: 0xC0000005: 读取位置 0x6868687c 时发生访问冲突 当我输入的数据超过几百个时,就读取冲突,为什么呢?数据短了就没事,长了就出问题
是不是因为长的数据还没操作完就接到了下一次操作请求所以导致冲突[/quote] 如果WaitForSingleObject(hMutex,INFINITE);失败是等待操作的话,就应该不会有冲突啊,读线程正在读的话,根本没有ReleaseMutex(hMutex);如何产生冲突呢?又或者是这个冲突到底是和谁冲突?是和写线程吗?
回复
向立天 2013-08-01
引用 2 楼 u011187092 的回复:
com_thread.exe 中的 0x63ae30d7 处最可能的异常: 0xC0000005: 读取位置 0x6868687c 时发生访问冲突 当我输入的数据超过几百个时,就读取冲突,为什么呢?数据短了就没事,长了就出问题
是不是因为长的数据还没操作完就接到了下一次操作请求所以导致冲突
回复
u011187092 2013-08-01
引用 1 楼 hdg3707 的回复:
串口不能同时读写的,如果一定要设置读写两个线程,就采用互斥或临界区来保证只能有一个操作而且保存串口一不定要操作完才能执行另一个线程
我写的是互斥信号量,但是还是有冲突,故迷惑之。。
回复
u011187092 2013-08-01
com_thread.exe 中的 0x63ae30d7 处最可能的异常: 0xC0000005: 读取位置 0x6868687c 时发生访问冲突 当我输入的数据超过几百个时,就读取冲突,为什么呢?数据短了就没事,长了就出问题
回复
hdg3707 2013-08-01
串口不能同时读写的,如果一定要设置读写两个线程,就采用互斥或临界区来保证只能有一个操作而且保存串口一不定要操作完才能执行另一个线程
回复
u011187092 2013-08-01
找到问题了,是写进程的数组越界了,不过我也没有好办法去控制这个数组的大小,数组大小未知?
回复
发动态
发帖子
进程/线程/DLL
创建于2007-09-28

1.5w+

社区成员

VC/MFC 进程/线程/DLL
申请成为版主
社区公告
暂无公告