sharing memory between application and driver KMDF

I am using DeviceIoControl to pass a buffer to my driver.

retval = DeviceIoControl(DriverHandle,
(DWORD)IOCTL_APOLLO_RECORD_BUFFER ,
NULL, // Ptr to InBuffer
0, // Length of InBuffer
data, // Ptr to OutBuffer
len, // Length of OutBuffer
&index, // BytesReturned
overlapped); // Ptr to Overlapped structure

#define IOCTL_APOLLO_RECORD_BUFFER CTL_CODE(FILE_DEVICE_WDFDIO,
2060, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)

I put the request in a queue to be used later to get the buffer out.

This buffer in turn is is filled up with data from my DSP. When the buffer
is full my driver sends a buffer full message to my application and
completes the request.

At that time my application wites the data to disk. And sends the buffer
back to the driver through the same method. Everything works fine.

I would like to try and make the whole process more efficent by not
completing the request and just holding on to the buffer in the driver.
When the application gets the buffer full message I want it to write the
data to disk and set the buffer content length to zero from the application.

This buffer_content_length variable is part of the structure that I pass
down with the buffer to the driver.

I have set buffer_content_length variable to zero in the application, but
the driver never sees the variable as zero.

I know the buffer is just supposed to be an ouput buffer from the way I
passed it, but since I set METHOD_OUT_DIRECT I assume that the application
and the driver should be looking at the same memory. Why does the driver
never see the buffer_content_lenght set to zero? Is it some memory paging
thing going on?

I am really asking for a more detailed explanation of how memory mapping
works in relation to direct IO and how the buffers are passed. I have the
Microsoft WDM book and on page 368 is seems to imply that the the driver and
application should be looking at the same memory, but that does not seem to
be exactly the case.

If it just does not work this way. What would be the best way to have
shared 2 way (read and write) memory between my application and driver?

Thanks,
Greg

Such memory sharing is a bad idea, since the synchronization issues on
shared variable will surely arise.

I would just complete the IRP and submit the next one.


Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com

“Greg Coleson” wrote in message news:xxxxx@ntdev…
> I am using DeviceIoControl to pass a buffer to my driver.
>
> retval = DeviceIoControl(DriverHandle,
> (DWORD)IOCTL_APOLLO_RECORD_BUFFER ,
> NULL, // Ptr to InBuffer
> 0, // Length of InBuffer
> data, // Ptr to OutBuffer
> len, // Length of OutBuffer
> &index, // BytesReturned
> overlapped); // Ptr to Overlapped structure
>
> #define IOCTL_APOLLO_RECORD_BUFFER CTL_CODE(FILE_DEVICE_WDFDIO,
> 2060, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
>
> I put the request in a queue to be used later to get the buffer out.
>
> This buffer in turn is is filled up with data from my DSP. When the buffer
> is full my driver sends a buffer full message to my application and
> completes the request.
>
> At that time my application wites the data to disk. And sends the buffer
> back to the driver through the same method. Everything works fine.
>
> I would like to try and make the whole process more efficent by not
> completing the request and just holding on to the buffer in the driver.
> When the application gets the buffer full message I want it to write the
> data to disk and set the buffer content length to zero from the application.
>
> This buffer_content_length variable is part of the structure that I pass
> down with the buffer to the driver.
>
> I have set buffer_content_length variable to zero in the application, but
> the driver never sees the variable as zero.
>
> I know the buffer is just supposed to be an ouput buffer from the way I
> passed it, but since I set METHOD_OUT_DIRECT I assume that the application
> and the driver should be looking at the same memory. Why does the driver
> never see the buffer_content_lenght set to zero? Is it some memory paging
> thing going on?
>
> I am really asking for a more detailed explanation of how memory mapping
> works in relation to direct IO and how the buffers are passed. I have the
> Microsoft WDM book and on page 368 is seems to imply that the the driver and
> application should be looking at the same memory, but that does not seem to
> be exactly the case.
>
> If it just does not work this way. What would be the best way to have
> shared 2 way (read and write) memory between my application and driver?
>
> Thanks,
> Greg
>
>
>

Did you map the MDL into kernel space so you could access it independent of the original process? If you’re using a UM VA in the wrong process context, no teling what you are going to see.

> When the buffer is full my driver sends a buffer full message to my
application and completes the request.

Is this a 2 step process where you are notifying the app of completion
and *then* completing the request? Why not just complete the request?
That will indicate to the application that the transfer has finished.

I would like to try and make the whole process more efficient
Have you measured the current method to see that it is inefficient?
More succinctly, is this a guess that this will make things faster or do
you have evidence to say that this part of your design is really the
bottleneck? Your current design is simple, elegant and requires no
synchronization between you and the application. By creating a shared
memory block, you now have to synchronize access to the buffer with the
application and add what could be a lot of fragile code (not to mention
a potential security problem or two).

d

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Greg Coleson
Sent: Wednesday, April 04, 2007 9:13 AM
To: Windows System Software Devs Interest List
Subject: [ntdev] sharing memory between application and driver KMDF

I am using DeviceIoControl to pass a buffer to my driver.

retval = DeviceIoControl(DriverHandle,
(DWORD)IOCTL_APOLLO_RECORD_BUFFER ,
NULL, // Ptr to InBuffer
0, // Length of InBuffer
data, // Ptr to OutBuffer
len, // Length of OutBuffer
&index, // BytesReturned
overlapped); // Ptr to Overlapped
structure

#define IOCTL_APOLLO_RECORD_BUFFER
CTL_CODE(FILE_DEVICE_WDFDIO,
2060, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)

I put the request in a queue to be used later to get the buffer out.

This buffer in turn is is filled up with data from my DSP. When the
buffer
is full my driver sends a buffer full message to my application and
completes the request.

At that time my application wites the data to disk. And sends the
buffer
back to the driver through the same method. Everything works fine.

I would like to try and make the whole process more efficent by not
completing the request and just holding on to the buffer in the driver.
When the application gets the buffer full message I want it to write the

data to disk and set the buffer content length to zero from the
application.

This buffer_content_length variable is part of the structure that I pass

down with the buffer to the driver.

I have set buffer_content_length variable to zero in the application,
but
the driver never sees the variable as zero.

I know the buffer is just supposed to be an ouput buffer from the way I
passed it, but since I set METHOD_OUT_DIRECT I assume that the
application
and the driver should be looking at the same memory. Why does the
driver
never see the buffer_content_lenght set to zero? Is it some memory
paging
thing going on?

I am really asking for a more detailed explanation of how memory mapping

works in relation to direct IO and how the buffers are passed. I have
the
Microsoft WDM book and on page 368 is seems to imply that the the driver
and
application should be looking at the same memory, but that does not seem
to
be exactly the case.

If it just does not work this way. What would be the best way to have
shared 2 way (read and write) memory between my application and driver?

Thanks,
Greg


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

Isn’t WdfRequestRetrieveOutputBuffer supposed to do that for me?

Just to be clear, I am not having problems accessing the buffer from my
application or the driver. It just seems like if it is really direct IO
then when I write something to the buffer from my application after I send
the buffer to the driver, the driver should be able to see those changes?

It does not. I get all the data back into my application correctly from the
buffer after the driver writes into it. I just don’t seem to be able to
write data from the app and have the driver see the changes after I send the
buffer. The buffer is behaving exactly like it is buffered IO, not direct
IO.

This is more just me wanting to know how the buffers really work behind the
scenes.

“Bob Kjelgaard” wrote in message
news:xxxxx@ntdev…
Did you map the MDL into kernel space so you could access it independent of
the original process? If you’re using a UM VA in the wrong process context,
no teling what you are going to see.

Yes, I would expect WdfRequestRetrieveOutputBuffer to handle that (you didn’t say how you were getting the address- I was just thinking of ways you might get what you are seeing).

Next thought after that is that the buffer’s UM VA may be copy-on-write, so the driver can write to the page, but if the app writes to it, then that virtual page becomes a different physical page than the one originally mapped into the driver. I believe some PE binary segments normally get loaded that way, but I’m not expert enough to detail exactly which ones off the top of my head. DLLs, I think, but that’s way too back in the hazy recesses of the mind…

I have done the sort of thing you’re talking about (along with a zillion other practices guaranteed to draw flames), so I know it can be done. I’ve not done this with a KMDF driver, per se, but I can’t think of anything there that would cause this.

When I have I usually VirtualAlloc the UM page, so I don’t run afoul of this sort of thing, because I can control those attributes.

Don’t take my previous comments wrongly, though- the concerns and suggestions that were mentioned previously are valid. I just like to play with the foot-shaped rocket launcher- sometimes it even lets me think I’m an adult…

>Next thought after that is that the buffer’s UM VA may be copy-on-write, so
the

driver can write to the page, but if the app writes to it, then that virtual
page
becomes a different physical page than the one originally mapped into the
driver. I believe some PE binary segments normally get loaded that way, but
I’m
not expert enough to detail exactly which ones off the top of my head. DLLs,
I
think, but that’s way too back in the hazy recesses of the mind…

All PE sections with “copy-on-write” flag set by the linker. Generally, this
flag is set to .data sections.

.text and .rdata is read-only.


Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com

Thanks for the info, Maxim-

So if Greg was, for instance, using a fixed-size output buffer declared as static within a function, or simply at the global level of some particular source file (both should wind up in .data by default), this is to be expected.

That’s pretty much what I thought- it’s something a decent programmer would generally do [especially in a quickie verification test, for instance], and a subtle enough side effect not to be obvious.

Of course, this is an armchair analysis based on very little actual data- I’m assuming, for instance, he didn’t modify any data on that page before sending the I/O, or the whole idea falls apart.

But it MIGHT be what’s happening.