Quantcast
Channel: Active questions tagged kernel - Stack Overflow
Viewing all articles
Browse latest Browse all 6372

What are UIO_USERISPACE, UIO_USERSPACE and UIO_SYSSPACE in os161?

$
0
0

I'm trying to complete an assignment for an operating systems course, Here.

I had a question from the assignment:

What is the difference between UIO_USERISPACE and UIO_USERSPACE? When should one use UIO_SYSSPACE instead?

When I searched the source code for them, here, I found this:

/* Source/destination. */enum uio_seg {        UIO_USERISPACE,         /* User process code. */        UIO_USERSPACE,          /* User process data. */        UIO_SYSSPACE,           /* Kernel. */};struct uio {    struct iovec     *uio_iov;  /* Data blocks */    unsigned          uio_iovcnt;   /* Number of iovecs */    off_t             uio_offset;   /* Desired offset into object */    size_t            uio_resid;    /* Remaining amt of data to xfer */    enum uio_seg      uio_segflg;   /* What kind of pointer we have */    enum uio_rw       uio_rw;   /* Whether op is a read or write */    struct addrspace *uio_space;    /* Address space for user pointer */};

I can see that it's used in the struct uio (which I'm gonna ask about it in a separate question) to indicate "what kind of pointer is used".

Also, I can see it mentioned in the description of the function uiomove, here:

 *   (5) if uio_seg is UIO_SYSSPACE, set uio_space to NULL; otherwise, *       initialize uio_space to the address space in which the buffer *       should be found.

The full description of the function uiomove, here:

/* * Copy data from a kernel buffer to a data region defined by a uio struct, * updating the uio struct's offset and resid fields. May alter the iovec * fields as well. * * Before calling this, you should *   (1) set up uio_iov to point to the buffer(s) you want to transfer *       to, and set uio_iovcnt to the number of such buffers; *   (2) initialize uio_offset as desired; *   (3) initialize uio_resid to the total amount of data that can be *       transferred through this uio; *   (4) set up uio_seg and uio_rw correctly; *   (5) if uio_seg is UIO_SYSSPACE, set uio_space to NULL; otherwise, *       initialize uio_space to the address space in which the buffer *       should be found. * * After calling, *   (1) the contents of uio_iov and uio_iovcnt may be altered and *       should not be interpreted; *   (2) uio_offset will have been incremented by the amount transferred; *   (3) uio_resid will have been decremented by the amount transferred; *   (4) uio_segflg, uio_rw, and uio_space will be unchanged. * * uiomove() may be called repeatedly on the same uio to transfer * additional data until the available buffer space the uio refers to * is exhausted. * * Note that the actual value of uio_offset is not interpreted. It is * provided (and updated by uiomove) to allow for easier file seek * pointer management. * * When uiomove is called, the address space presently in context must * be the same as the one recorded in uio_space. This is an important * sanity check if I/O has been queued. */

Definition of the function uiomove, here:

intuiomove(void *ptr, size_t n, struct uio *uio){    struct iovec *iov;    size_t size;    int result;    if (uio->uio_rw != UIO_READ && uio->uio_rw != UIO_WRITE) {        panic("uiomove: Invalid uio_rw %d\n", (int) uio->uio_rw);    }    if (uio->uio_segflg==UIO_SYSSPACE) {        KASSERT(uio->uio_space == NULL);    }    else {        KASSERT(uio->uio_space == proc_getas());    }    while (n > 0 && uio->uio_resid > 0) {        /* get the first iovec */        iov = uio->uio_iov;        size = iov->iov_len;        if (size > n) {            size = n;        }        if (size == 0) {            /* move to the next iovec and try again */            uio->uio_iov++;            uio->uio_iovcnt--;            if (uio->uio_iovcnt == 0) {                /*                 * This should only happen if you set                 * uio_resid incorrectly (to more than                 * the total length of buffers the uio                 * points to).                 */                panic("uiomove: ran out of buffers\n");            }            continue;        }        switch (uio->uio_segflg) {            case UIO_SYSSPACE:                if (uio->uio_rw == UIO_READ) {                    memmove(iov->iov_kbase, ptr, size);                }                else {                    memmove(ptr, iov->iov_kbase, size);                }                iov->iov_kbase = ((char *)iov->iov_kbase+size);                break;            case UIO_USERSPACE:            case UIO_USERISPACE:                if (uio->uio_rw == UIO_READ) {                    result = copyout(ptr, iov->iov_ubase,size);                }                else {                    result = copyin(iov->iov_ubase, ptr, size);                }                if (result) {                    return result;                }                iov->iov_ubase += size;                break;            default:                panic("uiomove: Invalid uio_segflg %d\n",                  (int)uio->uio_segflg);        }        iov->iov_len -= size;        uio->uio_resid -= size;        uio->uio_offset += size;        ptr = ((char *)ptr + size);        n -= size;    }    return 0;}

I don't seem to make sence of its use. Can anyone give me some intuition about them? For example, when and where they would be used? what is the purpose of them? And also, the answer to the original question, what is the difference between UIO_USERISPACE and UIO_USERSPACE? When should one use UIO_SYSSPACE instead?


Viewing all articles
Browse latest Browse all 6372

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>