打印

Win CE中流驱动支持临界区的问题!

[复制链接]
2042|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
zzddk|  楼主 | 2008-1-28 14:20 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
写了一个简单的流驱动,大体是这样的:
在DLL文件中,定义一个全局变量:
unsigned char chBuffer[BUFSIZE];

在XXX_Init中对其进行初始化为全0;
DWORD COM_Init(DWORD dwContext)

EnterCriticalSection(&(pDrv->InitCS));    
memset (chBuffer, 0, BUFSIZE * sizeof(unsigned char));
LeaveCriticalSection(&(pDrv->InitCS));

在XXX_Write()中对其写入数据,例如一个固定的字符串;
DWORD COM_Write(HANDLE hOpenContext, LPCVOID pSourceBytes, DWORD NumberOfBytes)

    EnterCriticalSection(&(pDrv->WriteCS));
    dwRet = min(BUFSIZE, NumberOfBytes);
    memcpy(chBuffer, (PBYTE)pSourceBytes, dwRet);
    LeaveCriticalSection(&(pDrv->WriteCS));

在XXX_Read中把写入的数据读出;

DWORD COM_Read(HANDLE hOpenContext, LPVOID pBuffer, DWORD Count)

    EnterCriticalSection(&(pDrv->ReadCS));
    // Copy the smaller of buffer size or string size.
    DWORD dwcbBuffer = strlen((char *)chBuffer);
    dwRet = min(dwcbBuffer, Count);
    memcpy((unsigned char *)pBuffer, chBuffer, dwRet);
    LeaveCriticalSection(&(pDrv->ReadCS));

大体就是这个样子,我在初始化,读,写里面加了临界区保护数据,DLL文件可以编译通过,但是生成NK文件,对流驱动进行操作时确同问题,调试口给出的信息是:
                                                                     Data Abort: Thread=8fe8b6d8 Proc=8e626160 'device.exe'
AKY=00000005 PC=03f92490(coredll.dll+0x00022490) RA=06039a38(device.exe+0x00029a
38) BVA=06039a39 FSR=00000003
RaiseException: Thread=8fe8b6d8 Proc=8e626160 'device.exe'
AKY=00000005 PC=03f8dff8(coredll.dll+0x0001dff8) RA=8c22a6d4(NK.EXE+0x0002a6d4)
BVA=00000001 FSR=00000001

但是我把监界区保护去掉,程序驱动可以正常加载和调用,只要一出现临界区保护:EnterCriticalSection();
LeaveCriticalSection();
就会出现上面的错误,会是那里的原因呢?

相关帖子

沙发
zzddk|  楼主 | 2008-1-28 14:21 | 只看该作者

驱动源码给出:

// VirtualCom.cpp : Defines the entry point for the DLL application.
//

#include "stdafx.h"
#include "VirtualCom.h"


HANDLE g_hInstance;

#define BUFSIZE 2048
unsigned char chBuffer[BUFSIZE];

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
        case DLL_PROCESS_ATTACH:
            g_hInstance = hModule;
            RETAILMSG(1,(TEXT("VirtualCom: DLL_PROCESS_ATTACH\n")));
            DisableThreadLibraryCalls ((HMODULE)g_hInstance);            
            break;
        //case DLL_THREAD_ATTACH:
        //    RETAILMSG(1,(TEXT("VirtualCom: DLL_THREAD_ATTACH\n")));
        //    break;
        //case DLL_THREAD_DETACH:
        //    RETAILMSG(1,(TEXT("VirtualCom: DLL_THREAD_DETACH\n")));
        //    break;
        case DLL_PROCESS_DETACH:
            RETAILMSG(1,(TEXT("VirtualCom: DLL_PROCESS_DETACH\n")));
            break;
    }
    return TRUE;
}


// This is an example of an exported variable
VirtualCom_API int nVirtualCom=0;

// This is an example of an exported function.
VirtualCom_API int fnVirtualCom(void)
{
    return 42;
}

// This is the constructor of a class that has been exported.
// see VirtualCom.h for the class definition
CVirtualCom::CVirtualCom()

    return; 
}

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
DWORD COM_Init(DWORD dwContext)
{
    PDRVCONTEXT pDrv;
    DWORD dwRet = 0;
    RETAILMSG(1,(TEXT("VirtualCom: COM_Init\n")));
    
    //Allocate a driver instance struct
    pDrv = (PDRVCONTEXT)LocalAlloc(LPTR,sizeof(PDRVCONTEXT));
    //allocate driver instance struct failed 
    if(pDrv == NULL)
    {
        RETAILMSG(1,(TEXT("COM_Init:Allocate driver instance struct failed!\n")));
        return 0;
    }
    //initialize driver instance struct
    memset((PBYTE)pDrv,0,sizeof(PDRVCONTEXT));
    pDrv->dwSize = sizeof(PDRVCONTEXT);

    //initialize critical section variable
    InitializeCriticalSection(&(pDrv->InitCS));
    InitializeCriticalSection(&(pDrv->CloseCS));
    InitializeCriticalSection(&(pDrv->ReadCS));
    InitializeCriticalSection(&(pDrv->WriteCS));
    
    // Initialize buffer to zero.
    EnterCriticalSection(&(pDrv->InitCS));
    RETAILMSG(1,(TEXT("COM_Init:EnterCriticalSection(&(pDrv->InitCS))\n")));
    memset (chBuffer, 0, BUFSIZE * sizeof(unsigned char));
    LeaveCriticalSection(&(pDrv->InitCS));
    RETAILMSG(1,(TEXT("COM_Init:LeaveCriticalSection(&(pDrv->InitCS))\n")));
    // Set return value to non-zero.
    dwRet = 1;
    return dwRet;


//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
BOOL COM_Deinit(DWORD hDeviceContext)
{
    PDRVCONTEXT pDrv = (PDRVCONTEXT) hDeviceContext;
    BOOL bRet = TRUE;
    RETAILMSG(1,(TEXT("VirtualCom: COM_Deinit\n")));
    
    if(pDrv&&(pDrv->dwSize == sizeof(PDRVCONTEXT)))
    {
        LocalFree((PBYTE)pDrv);
        RETAILMSG(1,(TEXT("COM_Deinit:LocalFree((PBYTE)pDrv)\n")));
    }

    //Delete Critical Section
    //DeleteCriticalSection(&(pDrv->InitCS));
    DeleteCriticalSection(&(pDrv->CloseCS));
    DeleteCriticalSection(&(pDrv->ReadCS));
    DeleteCriticalSection(&(pDrv->WriteCS));
    return bRet;


//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
DWORD COM_Open(HANDLE hDeviceContext, DWORD AccessCode, DWORD ShareMode)
{
    PDRVCONTEXT pDrv = (PDRVCONTEXT)hDeviceContext;
    DWORD dwRet = 0;
    RETAILMSG(1,(TEXT("VirtualCom: COM_Open\n")));
    //Verify that the context handle is valid
    //if(pDrv && (pDrv->dwSize != sizeof(PDRVCONTEXT)))
    //{
    //    RETAILMSG(1,(TEXT("COM_Open:context handle is invalid\n")));
    //    return 0;
    //}
    //count the number of opens
    RETAILMSG(1,(TEXT("COM_Open:Enter InterlockedIncrement\r\n")));
    //InterlockedIncrement((long *)&pDrv->nNumOpens);
    RETAILMSG(1,(TEXT("COM_Open:pDrv->nNumOpens++\n")));

    dwRet = 1; // Have to make non-zero for this call to succeed.
    return dwRet;


//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
BOOL COM_Close(DWORD hOpenContext)
{
    PDRVCONTEXT pDrv = (PDRVCONTEXT)hOpenContext;
    BOOL bRet = TRUE;
    RETAILMSG(1,(TEXT("VirtualCom: COM_Close\n")));
    //Verify that the context handle is valid 
    if(pDrv && (pDrv->dwSize != sizeof(PDRVCONTEXT)))
    {
        return FALSE;
    }
    //Close stream driver and increase counter.
    //if(pDrv->nNumOpens)
    //    pDrv->nNumOpens--;
    //Clear data buffer
    EnterCriticalSection(&(pDrv->CloseCS));
    memset(chBuffer,0,sizeof(unsigned char)*BUFSIZE);
    LeaveCriticalSection(&(pDrv->CloseCS));

    return bRet;


//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
DWORD COM_Read(HANDLE hOpenContext, LPVOID pBuffer, DWORD Count)
{
    PDRVCONTEXT pDrv = (PDRVCONTEXT)hOpenContext;
    DWORD dwRet = 0;
    RETAILMSG(1,(TEXT("VirtualCom: COM_Read\n")));
    //Verify that the context handle is valid
    //if(pDrv && (pDrv->dwSize != sizeof(PDRVCONTEXT)))
    //{
    //    RETAILMSG(1,(TEXT("COM_Read:context handle is invalid\n")));
    //    return 0;
    //}
    RETAILMSG(1,(TEXT("VirtualCom: EnterCriticalSection(&(pDrv->ReadCS))\n")));
    EnterCriticalSection(&(pDrv->ReadCS));
    RETAILMSG(1,(TEXT("VirtualCom: Enter aleady CriticalSection(&(pDrv->ReadCS))\n")));
    // Copy the smaller of buffer size or string size.
    //DWORD cbBuffer = wcslen(chBuffer);
    DWORD dwcbBuffer = strlen((char *)chBuffer);
    dwRet = min(dwcbBuffer, Count);
    memcpy((unsigned char *)pBuffer, chBuffer, dwRet);
    LeaveCriticalSection(&(pDrv->ReadCS));
    RETAILMSG(1,(TEXT("VirtualCom: LeaveCriticalSection(&(pDrv->ReadCS))\n")));
    // Return number of bytes read.
    return dwRet;


//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
DWORD COM_Write(HANDLE hOpenContext, LPCVOID pSourceBytes, DWORD NumberOfBytes)
{
    PDRVCONTEXT pDrv = (PDRVCONTEXT)hOpenContext;
    DWORD dwRet = 0;
    RETAILMSG(1,(TEXT("VirtualCom: COM_Write\n")));
    
    //Verify that the context handle is valid
    //if(pDrv && (pDrv->dwSize != sizeof(PDRVCONTEXT)))
    //{
    //    RETAILMSG(1,(TEXT("COM_Write:context handle is invalid\n")));
    //    return 0;
    //}
    RETAILMSG(1,(TEXT("COM_Write:EnterCriticalSection(&(pDrv->WriteCS))\n")));
    EnterCriticalSection(&(pDrv->WriteCS));
    RETAILMSG(1,(TEXT("VirtualCom: Enter aleady CriticalSection(&(pDrv->WriteCS))\n")));
    // Copy the smaller of buffer size or number of bytes they send us.
    dwRet = min(BUFSIZE, NumberOfBytes);
    memcpy(chBuffer, (PBYTE)pSourceBytes, dwRet);
    LeaveCriticalSection(&(pDrv->WriteCS));
    RETAILMSG(1,(TEXT("COM_Write:LeaveCriticalSection(&(pDrv->WriteCS))\n")));
    // Return number of bytes written.
    return dwRet;
}

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
BOOL COM_IOControl(DWORD hOpenContext, 
    DWORD dwCode, 
    PBYTE pBufIn, 
    DWORD dwLenIn, 
    PBYTE pBufOut, 
    DWORD dwLenOut, 
    PDWORD pdwActualOut)
{
    BOOL bRet = TRUE;
    RETAILMSG(1,(TEXT("VirtualCom: COM_IOControl\n")));
    return bRet;
}



//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void COM_PowerDown(DWORD hDeviceContext)
{
    RETAILMSG(1,(TEXT("VirtualCom: COM_PowerDown\n")));


//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void COM_PowerUp(DWORD hDeviceContext)
{
    RETAILMSG(1,(TEXT("VirtualCom: COM_PowerUp\n")));


//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
DWORD COM_Seek(DWORD hOpenContext, long Amount, DWORD Type)
{
    DWORD dwRet = 0;
    RETAILMSG(1,(TEXT("VirtualCom: COM_Seek\n")));
    return dwRet;

使用特权

评论回复
板凳
zzddk|  楼主 | 2008-1-28 14:22 | 只看该作者

PDRVCONTEXT是我定义的一个结构体.

typedef struct {
    DWORD dwSize;
    INT nNumOpens;
    CRITICAL_SECTION InitCS;
    CRITICAL_SECTION ReadCS;
    CRITICAL_SECTION WriteCS;
    CRITICAL_SECTION CloseCS;
} DRVCONTEXT, *PDRVCONTEXT;

使用特权

评论回复
地板
high| | 2008-1-28 14:24 | 只看该作者

哥们,你可以做这些事情.

1.你可以根据map文件定位错误,不过好像你已经定位好了.
2.你应该有pb,你找到这个宏看看究竟干了啥.

使用特权

评论回复
5
农民讲习所| | 2008-1-30 22:35 | 只看该作者

pDrv = (PDRVCONTEXT)LocalAlloc(LPTR,sizeof( DRVCONTEXT )); ?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

5

主题

20

帖子

0

粉丝