Re: sock_receive_internal() and its (ab)use of uio
Re: sock_receive_internal() and its (ab)use of uio
- Subject: Re: sock_receive_internal() and its (ab)use of uio
- From: Sam Vaughan <email@hidden>
- Date: Tue, 26 Jul 2005 09:51:00 +1000
Hi Josh,
Thanks for the speedy reply. I'm only interested in sending/
receiving to/from kernel memory here so that's not a concern right now.
Don't you agree however that in moving from soreceive() to
sock_receive(), the interface has dropped in usefulness? The idea of
allocating yet another uio, walking the iovecs in my own one and
adding new iovecs with the appropriate addresses and lengths to the
new one makes me shudder. That'd be three uios allocated, prepared
and freed just to do one I/O operation - one in our platform-common
code, one in the 10.4 wrapper around sock_receive(), and another in
sock_receive_internal().
One more entry point that takes a uio and passes it straight to
soreceive would be a real bonus, for elegance, performance AND
sanity ;o)
Sam
On 26/07/2005, at 4:03 AM, Josh Graessley wrote:
Hi Sam,
The socket KPI was written to simplify the use of sockets in the
kernel. The new socket KPI is based more on the user space APIs for
interacting with sockets. sock_send is very much like sendmsg,
sock_receive is like recvmsg.
You may create a new iovec array to point to the buffers you're
interested in copying in to.
One other thing to be aware of is that the pointers in the iovec
array must point to data that resides in the kernel's address
space. If you need to receive in to a buffer in another process you
will need to copy the data yourself. To avoid copying the data
twice, you can use the sock_receivembuf variant which will receive
the mbuf chain without performing a copy.
-josh
On Jul 25, 2005, at 12:58 AM, Sam Vaughan wrote:
I'm trying to clean up the areas in our code where I'm using
symbols from mach_kernel instead of the 10.4 KPI. One of these is
the use of soreceive() and sosend().
I avoided using the KPI on these two initially because the new
interface that uses struct msghdr looked confusing. Now that I've
delved into it a bit more it looks pretty much unworkable. Let me
use sock_receive() here as an example.
When linking directly to the kernel, I can simply pass a uio
pointer to soreceive() as follows:
soreceive(so, NULL, uiop, NULL, NULL, flagsp);
I can do this safe in the knowledge that it will use uio_move() to
transfer the data it reads into my uio, using and updating my
uio_offset and uio_resid fields as appropriate.
My first attempt at a KPI replacement looked like this:
size_t bytes = uio->uio_resid;
struct msghdr msg = {0};
msg.msg_iov = uiop->uio_iov;
msg.msg_iovlen = uiop->uio_iovcnt;
error = sock_receive(so, &msg, 0, &bytes);
if (!error)
{
uiop->uio_offset += bytes;
uiop->uio_resid -= bytes;
ASSERT(uiop->uio_resid >= 0);
}
But it's clearly deficient because the uio_offset isn't being
passed into sock_receive(). It's also not clear that it will use
my uio_resid value. Sure enough when you run it up, this code
asserts pretty quickly, having read more than I wanted it to.
The problem as I see it is that the new socket KPI doesn't allow
you to specify an offset and a resid along with your iovecs. It's
therefore not possible to read into a range of memory somewhere in
the middle of the buffers represented by your iovecs.
If you use sock_receivembuf(), the data argument to
sock_receive_internal() won't be NULL and the value in recvdlen
will get used as the uio's resid. This solves one of the
problems. Unfortunately the call to uio_createwithbuffer() will
still specify 0 for the initial offset of the uio, so this is no
good if you want to read into somewhere in the middle of your
buffers.
The only solution I can see at the moment is to create yet another
uio structure before calling sock_receive(). This uio would be
given iovecs with data addresses and lengths that represent the
region of the original buffers to be received into. This is
clearly not an optimal solution, given the extra overhead and
unnecessary code to write and debug.
It seems odd to me that the shiny new uio KPI wasn't used in the
sock_receive() and sock_send() interfaces, since this is exactly
the functionality that uios are designed (and were previously
used) for. I've raised a radar bug requesting sock_receive_uio()
and sock_send_uio() to be added, (#4191646) but I'd be interested
to hear other people's opinions on this.
Sam
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-kernel mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
40apple.com
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