uiomove vs. copy{in,out,instr,str}

Matthew Dillon dillon at apollo.backplane.com
Thu Mar 30 22:07:11 PST 2006

:I am doing some research on device driver implementation in
:DragonFlyBSD.  I am unclear on when to use uiomove and when to use
:copy{in,out,str,instr}.  I noticed the character device example; 
:/usr/share/examples/kld/cdev/module/cdev.c uses copy... yet hasn't
:been updated to use the new cdevsw interface.  I have mostly gotten
:the example to work using uiomove but have failed to get the example
:working with copy...  From uio(9) is would seem is the way to go.

    Its kinda a messy.  UIO's can do a lot more then copyin/copyout, but
    at its core a UIO generated from a user request such as read() or
    write() basically just does copyout or copyin (depending on the
    direction of the I/O).

    copyout and copyin allow the kernel to access a user process's VM space.
    But there is a big caveat... and the same with UIO's too, and that is
    that the kernel can only run the operations in question while in the
    process context of the original userland requester.  A UIO, copyin, or
    copyout cannot be run in a separate kernel thread, because the kenrel
    then has no idea which user VM space to use.

    UIO's do have a thread field, but as far as I can tell all BSDs require
    that the thread pointer in the UIO be the 'current thread' if the UIO
    is specifying a transfer to or from user space.  There are functions
    that allow copying to and from an arbitrary user VM context, but they
    are pretty hokey and not really something I would depend on.

    copyinstr is a weird version of copyin that allows the kernel to copy
    \0-terminated strings from string pointers supplied by userland.

    The copyin, copyout, and copyinstr implementations basically just use
    a segment override embedded in an otherwise normal bcopy-like operation
    in order to force the cpu to access the memory from the point of view
    of the user process.  If an unrecoverable fault occurs, the kernel 
    intercepts it and causes the copy*() call to return an error (instead
    of panicing the kernel), indicating that the user process gave the kernel
    a bogus pointer to copy from or to.

					Matthew Dillon 
					<dillon at xxxxxxxxxxxxx>

More information about the Kernel mailing list