5570|16

74

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

求教关于marshaling的概念问题!!! [复制链接]

正在学习写驱动(WinCE6),遇到驱动和应用程序之间存取数据的问题,求高手解答一些问题,让我开化一下:

1.我看到两个概念,一个是指针参数,一个是嵌入指针,请问有什么不同?

2.关于内核态线程对用户空间内存访问的两种方式:同步和异步,恕我愚钝网上的文章没看明白,求个通俗的解释……

3.我现在写一个流驱动,在应用程序中分配缓存然后将指针通过DeviceIOControl传给驱动,如果在驱动中的XXX_IOControl函数中往这个地址写数据,算是同步还是异步?

4.同上,在应用程序中分配缓存然后将指针通过DeviceIOControl传给驱动,但XXX_IOControl函数将此指针交给某个写数据线程,在那个线程中向这个地址写数据,那这是同步还是异步?

5.根据我的理解,函数CeOpenCallerBuffer检查一个传入的地址unmapped并让驱动获得一个驱动能用的相对应的地址mapped,在驱动里访问mapped就等于在应用程序里访问unmapped,理解的对吗? ; 而函数CeAllocAsynchronousBuffer我不太理解,这个函数分配的内存是怎么等同于应用程序里分配的缓存的?调用CeAllocAsynchronousBuffer时的参数2是一个“Pointer to the buffer that has already been marshaled for synchronous access by the current process”,这个地址和应用程序里的地址是什么关系?是不是在调CeAllocAsynchronousBuffer前要先用CeOpenCallerBuffer?

望对这个问题已经通达的人们不吝赐教!!跪谢!!

最新回复

明白了,我已经改成在一个线程里面调用了。 timer消息的话,好像是消息队列里面如果有多个timer消息,系统就会把它们合并成一个。 谢谢指导。  详情 回复 发表于 2010-6-2 09:15
点赞 关注

回复
举报

78

帖子

0

TA的资源

一粒金砂(初级)

沙发
 
顶。
这些个问题,Paul Cao应该能给你非常好的解释的。
 
 

回复

79

帖子

0

TA的资源

一粒金砂(初级)

板凳
 
呼唤Paul Cao~~~~~~~~~~~~~~~~~~~~
 
 
 

回复

85

帖子

0

TA的资源

一粒金砂(初级)

4
 
补充一个问题,我做了如下实验:

1.在应用程序中使用malloc分配一块内存,指针(姑且叫pApp)和内存大小(有size这么大)通过DeviceIOControl传给驱动。
2.在XXX_IOControl函数中使用CeOpenCallerBuffer函数得到一个对应的指针(叫它pDriver吧)然后传给了一个写数据线程。
3.在写数据线程中等待中断,终端来了就往pDriver写size这么多数据,死循环,不断在写。
4.在应用程序中使设备工作起来以后,读取pApp地址的size大小的数据,看看当前写进来的数据是多少。

程序运行的结果是,由驱动的输出得知写数据线程的确不断在写,但是一读发现从pAdd取出来的数据还都是0。
请问为什么??
 
 
 

回复

87

帖子

0

TA的资源

一粒金砂(初级)

5
 
1. 应用程序如此调用
BYTE *pData = (BYTE*)malloc(100);
DeviceIOControl(hDriver, IOCTL, pData, ...);
pData是指针参数, 这个指针传到驱动中,系统会自动映射,不需要调用CeOpenCallerBuffer
假设是这样的
Struct MyStruct
{
   BYTE *pData;
   int iLen;
}
应用程序调用时
MyStruct *pStruct = new MyStruct();
pStruct->iLen = 100;
pStruct->pData = new BYTE[100];
DeviceIOControl(hDriver, IOCTL, pStruct , ...);
pStruct 是指针参数, pData是嵌入指针, 传入驱动后,操作系统不会为你转换pData的地址,需要手动调用CeOpenCallerBuffer

2. 同步访问,比如刚才那样调用,你在XXX_IOControl里,对传入的指针指向的内容赋值
XXX_IOControl调用返回时,赋值已经完成
异步访问,在XXX_IOControl中创建一个线程(或者是把地址传给一个已经创建的线程),线程中访问指针指向的内容,XXX_IOControl返回时,可能访问还在继续,这个时候如果你在应用程序里再访问该地址,就可能发生冲突


 
 
 

回复

62

帖子

0

TA的资源

一粒金砂(初级)

6
 
引用 4 楼 reallyu 的回复:

1. 应用程序如此调用
BYTE *pData = (BYTE*)malloc(100);
DeviceIOControl(hDriver, IOCTL, pData, ...);
pData是指针参数, 这个指针传到驱动中,系统会自动映射,不需要调用CeOpenCallerBuffer
假设是这样的
Struct MyStruct
{
   BYTE *pData;
   in……


按照您说的不使用CeOpenCallerBuffer,结果在写数据线程里面往这个地址重复写了2次后,在第三次写这个地址时(此时应用程序还没有访问这片内存)就出现了错误exception data abort (4),PC指向memcpy函数,我在写线程用的memcpy。
但是在出错使驱动停掉后,在应用程序中读数据,发现数据有了,说明前两次数据写成功了。

我糊涂了…………用了CeOpenCallerBuffer的话可以一直写,但是读不到,不用的话第三遍写会错误,但是前两次写对了,也读到了……………………

含泪求原因……………………
 
 
 

回复

76

帖子

0

TA的资源

一粒金砂(初级)

7
 
你这个是异步操作吧,应该还需要CeAllocAsynchronousBuffer。我不是很确定,你可以试试看。
 
 
 

回复

80

帖子

0

TA的资源

一粒金砂(初级)

8
 
异步线程中需要调用 CeAllocAsynchronousBuffer() 来使线程获取访问这个地址的权利
 
 
 

回复

72

帖子

0

TA的资源

一粒金砂(初级)

9
 
放学回家了……明天试试
 
 
 

回复

63

帖子

0

TA的资源

一粒金砂(初级)

10
 
帮不上忙,友情帮顶,呵呵
 
 
 

回复

74

帖子

0

TA的资源

一粒金砂(初级)

11
 
看来确如四楼所说,指针参数不需要CeOpenCallerBuffer,目前程序从结果上看正确,播放还算不错,但是遇到以下问题:

取数据的部分,驱动是这样写的:

  1. EXTERN_C
  2. BOOL
  3. CAM_IOControl(
  4.     DWORD   dwContext,
  5.     DWORD   Ioctl,
  6.     UCHAR * pInBufUnmapped,
  7.     DWORD   InBufLen,
  8.     UCHAR * pOutBufUnmapped,
  9.     DWORD   OutBufLen,
  10.     DWORD * pdwBytesTransferred
  11.    )
  12. {
  13.     UCHAR * pInBuf = NULL;
  14.     UCHAR * pOutBuf = NULL;
  15.         CamDC * cdc;
  16.         PVOID tmp;

  17.         cdc = (CamDC *)dwContext;
  18.         pInBuf = pInBufUnmapped;
  19.     pOutBuf = pOutBufUnmapped;

  20.         switch(Ioctl)
  21.         {
  22.         case IOCTL_CAM_OCCTL_OPEN:
  23.                 //开启摄像头////////////////////////////////////////////////////////////////
  24.                 //这里省略了……
  25.                 ////////////////////////////////////////////////////////////////////////////
  26.                 break;
  27.         case IOCTL_CAM_OCCTL_CLOSE:
  28.                 //关闭摄像头,省略……
  29.                 break;
  30.         case IOCTL_CAM_OCCTL_GET:
  31.                 tmp = GetImage();
  32.                 if(tmp != NULL)
  33.                 {
  34.                         memcpy(pInBuf, tmp, InBufLen);
  35.                 }
  36.                 break;
  37.         default:
  38.                 break;
  39.         }
  40.         return TRUE;
  41. }
  42. //GetImage函数如下:
  43. void * GetImage()
  44. {
  45.         DWORD    dwCause;
  46.         int CurrentFrame;

  47.     dwCause = WaitForSingleObject(PreviewEvent, INFINITE);

  48.     if (dwCause == WAIT_OBJECT_0)
  49.     {
  50.         CurrentFrame = CameraGetCurrentFrameNum(PREVIEW_CAPTURE_BUFFER);//取当前获得的图像在哪个缓存中
  51.                
  52.         s6410CAM->CIGCTRL |= (1<<18);
  53.         InterruptDone(g_CamSysIntr_P);
  54.     }
  55.         else
  56.         {
  57.                 RETAILMSG(1, (TEXT("[CALL]: dwCause != WAIT_OBJECT_0 \n")));
  58.                 return NULL;
  59.         }

  60.     return (void *)m_CameraHWPreviewBuffers[CurrentFrame].VirtAddr;//返回相应的缓存的地址
  61. }
复制代码

然后在应用程序中的TIMER消息里面不断地:
r = DeviceIoControl(hOpen, IOCTL_CAM_OCCTL_GET,ImageData, WIDTH*HEIGHT*2,//输出为rgb565
                        NULL,0,NULL,NULL);
取到的图像正确,显示也算流畅,但是串口在不断出现如下错误:

Exception 'Data Abort' (4): Thread-Id=07e20022(pth=8580a000), Proc-Id=00400002(pprc=82599308) 'NK.EXE', VM-active=07e10022(pprc=8387d6d0) '2-DirectCam-Timer.exe'
PC=c007151c(k.coredll.dll+0x0005151c) RA=c0b628c4(smdk6410_camera.dll+0x000028c4) SP=d4f4fba4, BVA=00106000

Exception 'Raised Exception' (-1): Thread-Id=07e20022(pth=8580a000), Proc-Id=00400002(pprc=82599308) 'NK.EXE', VM-active=07e10022(pprc=8387d6d0) '2-DirectCam-Timer.exe'
PC=c003b810(k.coredll.dll+0x0001b810) RA=801174c8(kernel.dll+0x000064c8) SP=d4f4f434, BVA=ffffffff

经过查k.coredll.map发现:
k.coredll.dll+0x0005151c是memmove
k.coredll.dll+0x0001b810是xxx_CeFreeAsynchronousBuffer
这两个函数我都没有调用。

求解~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~???
 
 
 

回复

79

帖子

0

TA的资源

一粒金砂(初级)

12
 
这个程序,真是写的很诡异...
出现诡异的现象是很正常的
容我有空了再来和你解释
当然你也可以思考下,对于这种需要多线程处理的程序怎么样更为合理
一般作法是,驱动中 createevent , 应用中 openevent ,并且 waitforsingleobject 等待这个event
然后驱动中的IST中接收完一帧图像 setevent, 应用调用 deviceiocontrol 读取图像并显示
别的方法也成,但是要注意同步,注意条理
 
 
 

回复

76

帖子

0

TA的资源

一粒金砂(初级)

13
 
引用 11 楼 reallyu 的回复:

这个程序,真是写的很诡异...
出现诡异的现象是很正常的
容我有空了再来和你解释
当然你也可以思考下,对于这种需要多线程处理的程序怎么样更为合理
一般作法是,驱动中 createevent , 应用中 openevent ,并且 waitforsingleobject 等待这个event
然后驱动中的IST中接收完一帧图像 setevent, 应用调用 deviceiocontrol ……


期待您有空……
在应用程序中没把读数并刷新显示单写一个线程就是图省事。应当是写成一个线程并放在while(1)里面的。
您说的这个模式我找的一个例子里面也是那么写的,但是我不太理解的是:
首先,驱动如何知道一帧图像来了呢,要等中断,也就是要waitforsingleobject一个跟中断关联的event。然后驱动等到中断以后,set一个通知收图的event。
那么,有什么必要用一个event来串联中断和应用程序?为什么不能等到中断就传出数据呢?,反正应用程序中调用deviceiocontrol,如果没有中断来,就会阻塞在那。
 
 
 

回复

67

帖子

0

TA的资源

一粒金砂(初级)

14
 
理论上理解了大部分,不过实践不足,做个标记,呵呵。
 
 
 

回复

80

帖子

0

TA的资源

一粒金砂(初级)

15
 
我晕…………测试程序里面deviceiocontrol的参数敲错了…………WIDTH*HEIGHT*2写成了WIDTH*HEIGHT*3…………
改了就不输出异常了…………也变流畅了,效果跟使用DShow的相同。

等Reallyu兄再给点建议就结贴~~
 
 
 

回复

73

帖子

0

TA的资源

一粒金砂(初级)

16
 
我说诡异的意思,是我也拿不准这种做法到底会导致什么后果
你在timer中调用DeviceIOControl
假设第一次调用时,中断还有没发生,调用被阻塞了,timer无法返回
当上一个timer还没有执行完,下一个timer的时间又到了
这个时候分两种情况,如果timer不可重入
新来的timer就无法执行,可能被丢弃,或者等待上一个timer执行完以后再执行
如果timer可重入,即使上一个timer还没有执行完,新的timer依然会被执行
所以依靠timer来控制这段程序,会有可能造成不同步的现象.
 
 
 

回复

66

帖子

0

TA的资源

一粒金砂(初级)

17
 
引用 15 楼 reallyu 的回复:

我说诡异的意思,是我也拿不准这种做法到底会导致什么后果
你在timer中调用DeviceIOControl
假设第一次调用时,中断还有没发生,调用被阻塞了,timer无法返回
当上一个timer还没有执行完,下一个timer的时间又到了
这个时候分两种情况,如果timer不可重入
新来的timer就无法执行,可能被丢弃,或者等待上一个timer执行完以后再执行
如果timer可重入,……


明白了,我已经改成在一个线程里面调用了。
timer消息的话,好像是消息队列里面如果有多个timer消息,系统就会把它们合并成一个。

谢谢指导。
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/7 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表