Re: cross-bounday memory communication b/w user app and the Kernel.How?
Re: cross-bounday memory communication b/w user app and the Kernel.How?
- Subject: Re: cross-bounday memory communication b/w user app and the Kernel.How?
- From: Terry Lambert <email@hidden>
- Date: Fri, 2 Jun 2006 12:37:12 -0700
On Jun 2, 2006, at 11:39 AM, rohit dhamija wrote:
Hi Michael,
I shall try to explain my doubt again:
I understand Michael's frustration.
I'm having a hard time understanding whether you are trying to modify
the contents of the packet in user space or kernel space, or where and
when you are trying to do this.
You are using an IOMemoryDescriptor, which you should be taking to
mean "this is a fancy name for a pointer to memory, which probaly
lives in user space", given the way you are using it.
The distinction between "user space" and "kernel space" is that they
are different address spaces. Unlike most 32 bit OS's intended to
operate on small machines, MacOS X does not map the user process
address space into the kernel address space, so a direct copy is not
possible for a user space buffer when you are operating in kernel
space (or vice versa - which is not possible even on OS's that map
process in, since they don't map the kernel out into user land). The
benefit of doing this is that instead of having only 2G or 3G for your
programs, you get the full 4G. It also means that instead of only
having 2G or 1G for the kernel's use, you have the full 4G - that
effectively means that the kernel can do a lot more housekeeping in
its own memory, and can theerefore run on machines with large amounts
of physical memory (8G, 16G, etc.) without running out of address space.
At this point, you really need to define which address space you are
allocating in, which you are reading in, and which you are writing
in. Then you need to define your protection domain crossings (i.e.
when you move from user space to kernel space, and back again).
I'll answer the rest of your question by making some assumptions, and
I'll call them out.
I need to send various command packets to the device and get the
corresponding response packet. My command consists of
[a]. command identifier i.e. command_id
[b] command payload: This command payload differs from command to
command. The maximum size of command payload is:
"unsigned char Commandpayload[257];"
My output response packet again varies from command to command. The
maximum size of response packet can be
"unsigned char ResponseData[256];"
So, one way is to make the shared structure (the structure to
communicate with user kernel space) can be:
typedef struct _mypacket{
int command_id;
union {
unsigned char Commandpayload[257];
unsigned char ResponseData[256]
} MY_PACKET, *PMY_PACKET;
But this type of structure will consume the maximum memory. So In
order to avoid it, can we have pointers instead of static memory
allocation ?
ASSUMPTIONS:
If I'm understanding, you have a user space process that creates an
IOMemoryDescriptor to a variable length command buffer. You also
pass it an IOMemoryDescriptor for the response buffer.
You want to dynamically allocate the command buffer and the response
buffer, instead of statically allocating them.
This is possible for the command buffer, since it's written in user
space and read in kernel space.
The allocation of the response buffer, which is apparently written in
kernel space and read in user space, has to take place in your process
address space.
-
What this effectively means is that there is *NO WAY* for you to
dynamically allocate it. You will be required to allocate the maximum
response buffer size, for the possible responses to each command, up
front.
The reason for this is that you cannot have the kernel allocate the
memory in your process address space for you.
If you don't *know* up front how much data you're going to get back,
but it's bounded at 256 bytes, then you will be better off going with
your union.
If you *know* for certain up front that the data you're going to get
back will *never* be more than X bytes for command C, then you can
allocate your buffers using overallocation and C99 variable length
structure tail arrays:
struct command_packet {
int id;
unsigned char payload[];
};
And then:
cmd = (struct command_packet *)malloc(sizeof(struct command_packet) +
payload_size);
If you can't use C99 semantics (gcc 4.x or above, or you are setting
options to disable them), then instead of "[]" , you can use the gcc
extension "[0]":
struct command_packet {
int id;
unsigned char payload[0];
};
If you can't use the C99 OR the gcc extension because of compilation
options, then you can coerce it:
struct command_packet {
int id;
unsigned char payload[1];
};
cmd = (struct command_packet *)malloc(offsetof(struct command_packet,
payload) + payload_size);
...there's no enforcement of out of range access for the character
array "payload", so if your allocation is large enough, then:
strcpy(cmd->payload, "command fred");
(or whatever) will work fine.
The command packet the structure will be
struct command_packet{
int command_id
unsigned char* cmd_payload;
int size_of_command;
}
Similary for response_packet. Is this possible ?
I have to echo other people in this thread; you really need to get
some information/background or at least a quick primer on programming
device drivers in protected mode OSs which separate kernel and user
(process) virtual address spaces.
The above sentence should give you some useful keywords for some
google searches. 8-).
-- Terry
Rohit
On 6/2/06, Michael Smith <email@hidden> wrote:
On Jun 2, 2006, at 12:28 AM, rohit dhamija wrote:
> Thanks for your suggestion, but i need to tell you two things :
>
> 1. I am sure that you did not get my question right.
That's entirely possible.
> Regarding my query,
>> You don't. The descriptor refers to the buffer that already
exists
>> in the user-space process' address space. You don't need to copy
>> anything.
>
> I know that the descriptor refers to the buffer only. But say for
> example I wish to set this data to all zero's.
I'm not sure why you would want to do this. If you want a buffer
full of zeroes, you would create an IOBufferMemoryDescriptor, since
that will have private memory associated with it, already mapped into
your address space.
In your example, you want to send the command buffer that the user
has supplied, so you need a descriptor that refers to it.
> So in this case: (a)
> will I give address of the structure OR (b) address of
> IOMemoryDescriptor,, as the first parameter to memset ?
Neither. The IOMemoryDescriptor is a class instance, and the
structure pointer in your example just points to a couple of
pointers. You can't use the pointers inside the structure, because
they are not valid in your address space.
Why do you want to change the contents of the command buffer? In the
typical interface model, the caller is not going to expect you to do
anything to it. Mapping it so that you can write into it will be
expensive, too.
> Similarly what if I want to copy the data AGAIN in my driver side ?
> Do I need to send the address of structure to the memcpy ? Or do i
> need to pass
> address of IOMemoryDescriptor as the first parameter to memcpy.
You don't want to copy the data at all, unless you are going to
modify it before you send it out.
> I hope I am able to clarify my query. Please comment.
Not really. I don't yet understand why you are obsessed with copying
this data...
= Mike
--
Rohit Dhamija(M) 9818446545
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-kernel mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-kernel mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden