为什么CMSComm串口控件会造成内存泄漏

默认分类 未结 1 906
___耐撕Nice___
___耐撕Nice___ 2023-03-18 05:16
相关标签:
1条回答
  • 2023-03-18 05:49

    基于VC的串行通信技术应用实例(中国计算机报 李湘江 2001年10月25日 17:33)在工业控制中,串口是常用的计算机与外部串行设备之间的数据传输通道,由于串行通信方便易行,所以应用广泛。 本文将介绍在Windows平台下串行通信的工作机制和用Visual C++设计串行通信程序的编程方法及通信方式。 VC中实现串行通信的编程技术 以下我们将介绍VC中几种实现串行通信的编程技术: 利用VC++的标准通信函数 利用VC++的标准通信函数_inp和_outp可实现串口通信。下面是一个串口初始化的程序: void init_com(PORT){char i;outp(PORT+3,0x80);outp(PORT,0x0C);outp(PORT+1,0);outp(PORT+3 ,0x3a);outp(PORT+3 ,0x03);i=inp(PORT+5) && 0xfe;outp(PORT+5,i);} 使用串行通信控件MSComm 串行通信控件MSCOmm32.OCX提供了使用RS-232来进行数据通信的所有协议,VC为该控件提供了标准的事件处理函数、过程,并通过属性和方法提供了串行通信的设置。它使用户能够方便地访问Windows串行通信驱动程序的大多数特性,包括输入、输出缓冲区的大小及决定何时使用流控制命令挂起数据传输等。 在ClassWizard中为新创建的通信控件定义成员对象(CMSComm m_Serial),通过该对象便可以对串口属性进行设置,MSComm控件共有27个属性。以下是通过设置控件属性对串口进行初始化的实例: BOOL CSampleDlg:: PortOpen(){ BOOL m_Opened;......m_Serial.SetCommPort(2); // 指定串口号m_Serial.SetSettings("4800,N,8,1");// 通信参数设置m_Serial.SetInBufferSize(1024);// 指定接收缓冲区大小m_Serial.SetInBufferCount(0);// 清空接收缓冲区m_Serial.InputMode(1);// 设置数据获取方式m_Serial.SetInputLen(0);// 设置读取方式m_Opened=m_Serail.SetPortOpen(1);// 打开指定的串口return m_Opened;} 打开所需串口后,我们需要考虑串口通信的时机。在接收或发送数据过程中,可能需要监视并响应一些事件和错误,所以事件驱动是处理串行端*互作用的一种非常有效的方法。使用OnComm事件和CommEvent属性捕捉并检查通信事件和错误的值。发生通信事件或错误时将触发OnComm事件,CommEvent属性的值将被改变,应用程序通过检查CommEvent属性值并作出相应的反应。 使用API函数 控件虽然简单易用,但由于必须拿到对话框中使用,在一些需要在线程中实现通信的应用场合下,控件的使用显得捉襟见肘。API是附带在Windows内部的一个极其重要的组成部分。Windows的32位API主要是一系列很复杂的函数和消息集合。它可以看作是Windows系统为在其下运行的各种开发系统提供的开放式通用功能增强接口。 通信程序在CreateFile处指定串口设备及相关的操作属性,再返回一个句柄,该句柄将被用于后续的通信操作,并贯穿整个通信过程。串口打开后,其属性被设置为默认值,根据具体需要,通过调用GetCommState(hComm,&&dcb)读取当前串口设备控制块DCB设置,修改后通过SetCommState(hComm,&&dcb)将其写入。运用ReadFile()与WriteFile()这两个API函数实现串口读写操作,若为异步通信方式,两函数中最后一个参数为指向OVERLAPPED结构的非空指针,在读写函数返回值为FALSE的情况下,调用GetLastError()函数,返回值为ERROR_IO_PENDING,表明I/O操作悬挂,即操作转入后台继续执行。此时,可以用WaitForSingleObject()来等待结束信号并设置最长等待时间,举例如下: BOOL bReadStatus;bReadStatus = ReadFile( m_hIDComDev, buffer,dwBytesRead, &&dwBytesRead, &&m_OverlappedRead );if(!bReadStatus){if(GetLastError()==ERROR_IO_PENDING){WaitForSingleObject(m_OverlappedRead.hEvent,1000);return ((int)dwBytesRead);}return(0);}return ((int)dwBytesRead); 多线程下实现串行通信 Windows内部的抢先调度程序在活动的线程之间分配CPU时间,Windows区分两种不同类型的线程,一种是用户界面线程(User Interface Thread),它包含消息循环或消息泵,用于处理接收到的消息;另一种是工作线程(Work Thread),它没有消息循环,用于执行后台任务、监视串口事件的线程即为工作线程。 多线程程序的编写在端口的配置,连接部分与单线程的相同,在端口配置完毕后,最重要的是根据实际情况,建立多线程之间的同步对象,如信号灯、临界区和事件等。 一切就绪后即可启动工作线程,程序如下: CWinThrea CommThread = AfxBeginThread(CommWatchThread, // 线程函数名(LPVOID) m_pTTYInfo, // 传递的参数THREAD_PRIORITY_ABOVE_NORMAL,// 设置线程优先级(UINT) 0, // 最大堆栈大小(DWORD) CREATE_SUSPENDED , // 创建标志(LPSECURITY_ATTRIBUTES) NULL);if(WaitCommEvent(pTTYInfo->idComDev,&&dwEvtMask,NULL)){if((dwEvtMask && pTTYInfo->dwEvtMask )== pTTYInfo->dwEvtMask){WaitForSingleObject(pTTYInfo->hPostEvent,0xFFFFFFFF);ResetEvent(pTTYInfo->hPostEvent);// 置同步事件对象为非信号态::PostMessage(CSampleView,ID_COM1_DATA,0,0); // 发送通知消息}}BEGIN_MESSAGE_MAP(CSampleView, CView)//{{AFX_MSG_MAP(CSampleView)ON_MESSAGE(ID_COM1_DATA, OnProcessCom1Data)ON_MESSAGE(ID_COM2_DATA, OnProcessCom2Data).....//}}AFX_MSG_MAPEND_MESSAGE_MAP() 多线程的实现可以使得各端口独立,准确地实现串行通信,使串行通信具有更广泛的灵活性与严格性,且充分利用CPU时间。但在具体的实时监控系统中如何协调多个线程、线程之间以何种方式实现同步,这是多线程串行通信程序实现的难点。 串行通信的操作方式

    基于VC串行通信技术应用实例 (计算机报 李湘江 200110月25 17:33)工业控制串口用计算机与外部串行设备间数据传输通道由于串行通信便易行所应用广泛 本文介绍Windows平台串行通信工作机制用Visual C++设计串行通信程序编程及通信式 VC实现串行通信编程技术 我介绍VC几种实现串行通信编程技术: 利用VC++标准通信函数 利用VC++标准通信函数_inp_outp实现串口通信面串口初始化程序: void init_com(PORT) {char i; outp(PORT+3,0x80); outp(PORT,0x0C); outp(PORT+1,0); outp(PORT+3 ,0x3a); outp(PORT+3 ,0x03); i=inp(PORT+5) && 0xfe; outp(PORT+5,i);} 使用串行通信控件MSComm 串行通信控件MSCOmm32.OCX提供使用RS-232进行数据通信所协议VC该控件提供标准事件处理函数、程并通属性提供串行通信设置使用户能够便访问Windows串行通信驱程序数特性包括输入、输缓冲区及决定何使用流控制命令挂起数据传输等 ClassWizard新创建通信控件定义员象(CMSComm m_Serial)通该象便串口属性进行设置MSComm控件共27属性通设置控件属性串口进行初始化实例: BOOL CSampleDlg:: PortOpen() { BOOL m_Opened; ...... m_Serial.SetCommPort(2); // 指定串口号 m_Serial.SetSettings("4800,N,8,1"); // 通信参数设置 m_Serial.SetInBufferSize(1024); // 指定接收缓冲区 m_Serial.SetInBufferCount(0); // 清空接收缓冲区 m_Serial.InputMode(1); // 设置数据获取式 m_Serial.SetInputLen(0); // 设置读取式 m_Opened=m_Serail.SetPortOpen(1); // 打指定串口 return m_Opened;} 打所需串口我需要考虑串口通信机接收或发送数据程能需要监视并响应些事件错误所事件驱处理串行端*互作用种非效使用OnComm事件CommEvent属性捕捉并检查通信事件错误值发通信事件或错误触发OnComm事件CommEvent属性值改变应用程序通检查CommEvent属性值并作相应反应 使用API函数 控件虽简单易用由于必须拿框使用些需要线程实现通信应用场合控件使用显捉襟见肘API附带Windows内部极其重要组部Windows32位API主要系列复杂函数消息集合看作Windows系统其运行各种发系统提供放式通用功能增强接口 通信程序CreateFile处指定串口设备及相关操作属性再返句柄该句柄用于续通信操作并贯穿整通信程串口打其属性设置默认值根据具体需要通调用GetCommState(hComm,&&dcb)读取前串口设备控制块DCB设置修改通SetCommState(hComm,&&dcb)其写入运用ReadFile()与WriteFile()两API函数实现串口读写操作若异步通信式两函数参数指向OVERLAPPED结构非空指针读写函数返值FALSE情况调用GetLastError()函数返值ERROR_IO_PENDING表明I/O操作悬挂即操作转入台继续执行用WaitForSingleObject()等待结束信号并设置等待间举例: BOOL bReadStatus; bReadStatus = ReadFile( m_hIDComDev, buffer, dwBytesRead, &&dwBytesRead, &&m_OverlappedRead ); if(!bReadStatus){ if(GetLastError()==ERROR_IO_PENDING){ WaitForSingleObject(m_OverlappedRead.hEvent,1000); return ((int)dwBytesRead);} return(0);} return ((int)dwBytesRead); 线程实现串行通信 Windows内部抢先调度程序线程间配CPU间Windows区两种同类型线程种用户界面线程(User Interface Thread),包含消息循环或消息泵用于处理接收消息;另种工作线程(Work Thread)没消息循环用于执行台任务、监视串口事件线程即工作线程 线程程序编写端口配置连接部与单线程相同端口配置完毕重要根据实际情况建立线程间同步象信号灯、临界区事件等 切绪即启工作线程程序: CWinThrea CommThread = AfxBegin Thread(CommWatchThread, // 线程函数名 (LPVOID) m_pTTYInfo, // 传递参数 THREAD_PRIORITY_ABOVE_NORMAL, // 设置线程优先级 (UINT) 0, // 堆栈 (DWORD) CREATE_SUSPENDED , // 创建标志 (LPSECURITY_ATTRIBUTES) NULL); if(WaitCommEvent(pTTYInfo->idComDev,&&dwEvtMask,NULL)) { if((dwEvtMask && pTTYInfo->dwEvtMask )== pTTYInfo->dwEvtMask) { WaitForSingleObject(pTTYInfo->hPostEvent,0xFFFFFFFF); ResetEvent(pTTYInfo->hPostEvent); // 置同步事件象非信号态 ::PostMessage(CSampleView,ID_COM1_DATA,0,0); // 发送通知消息}} BEGIN_MESSAGE_MAP(CSampleView, CView) //{{AFX_MSG_MAP(CSampleView) ON_MESSAGE(ID_COM1_DATA, OnProcessCom1Data) ON_MESSAGE(ID_COM2_DATA, OnProcessCom2Data) ..... //}}AFX_MSG_MAP END_MESSAGE_MAP() 线程实现使各端口独立准确实现串行通信使串行通信具更广泛灵性与严格性且充利用CPU间具体实监控系统何协调线程、线程间何种式实现同步线程串行通信程序实现难点 串行通信操作

    0 讨论(0)
提交回复