The user I/O or uio structure is a data structure describing a memory buffer to be used in a data transfer. The uio structure is most commonly used in the read and write interfaces to device drivers supporting character or raw I/O. It is also useful in other instances in which an input or output buffer can exist in different kinds of address spaces, and in which the buffer is not contiguous in virtual memory.
The uio structure is defined in the /usr/include/sys/uio.h file.
The uio structure describes a buffer that is not contiguous in virtual memory. It also indicates the address space in which the buffer is defined. When used in the character device read and write interface, it also contains the device open-mode flags, along with the device read/write offset.
The kernel provides services that access data using a uio structure. The ureadc, uwritec, uiomove, and uphysio kernel services all perform data transfers into or out of a data buffer described by a uio structure. The ureadc kernel service writes a character into the buffer described by the uio structure. The uwritec kernel service reads a character from the buffer. These two services have names opposite from what you would expect, since they are named for the user action initiating the operation. A read on the part of the user thus results in a device driver writing to the buffer, while a write results in a driver reading from the buffer.
The uiomove kernel service copies data to or from a buffer described by a uio structure from or to a buffer in the system address space. The uphysio kernel service is used primarily by block device drivers providing raw I/O support. The uphysio kernel service converts the character read or write request into a block read or write request and sends it to the ddstrategy routine.
The buffer described by the uio structure can consist of multiple noncontiguous areas of virtual memory of different lengths. This is achieved by describing the data buffer with an array of elements, each of which consists of a virtual memory address and a byte length. Each element is defined as an iovec element. The uio structure also contains a field specifying the total number of bytes in the data buffer described by the structure.
Another field in the uio structure describes the address space of the data buffer, which can either be system space, user space, or cross-memory space. If the address space is defined as cross memory, an additional array of cross-memory descriptors is specified in the uio structure to match the array of iovec elements.
The uio structure also contains a byte offset (uio_offset) . This field is a 64 bit integer (offset_t) ; it allows the file system to send I/O requests to a device driver's read & write entry points which have logical offsets beyond 2 gigabytes. Device drivers must use care not to cause a loss of significance by assigning the offset to a 32 bit variable or using it in calculations that overflow a 32 bit variable.
The called routine (device driver) is permitted to modify fields in the uio and iovec structures as the data transfer progresses. The final uio_resid count is in fact used to determine how much data was transferred. Therefore this count must be decremented, with each operation, by the number of bytes actually copied.
The uio structure contains the following fields:
uio_iov | A pointer to an array of iovec structures describing the user buffer for the data transfer. |
uio_xmem | A pointer to an array of xmem structures containing the cross-memory descriptors for the iovec array. |
uio_iovcnt | The number of yet-to-be-processed iovec structures in the array pointed to by the uio_iov pointer. The count must be at least 1. If the count is greater than 1, then a scatter-gather of the data is to be performed into or out of the areas described by the iovec structures. |
uio_iovdcnt | The number of already processed iovec structures in the iovec array. |
uio_offset | The file offset established by a previous lseek, llseek subroutine call. Most character devices ignore this variable, but some, such as the /dev/mem pseudo-device, use and maintain it. |
uio_segflg | A flag indicating the type of buffer being described by the uio structure. This flag typically describes whether the data area is in user or kernel space or is in cross-memory. Refer to the /usr/include/sys/uio.h file for a description of the possible values of this flag and their meanings. |
uio_fmode | The value of the file mode that was specified on opening the file or modified by the fcntl subroutine. This flag describes the file control parameters. The /usr/include/sys/fcntl.h file contains specific values for this flag. |
uio_resid | The byte count for the data transfer. It must not exceed the sum of all the iov_len values in the array of iovec structures. Initially, this field contains the total byte count, and when the operation completes, the value must be decremented by the actual number of bytes transferred. |
The iovec structure contains the starting address and length of a contiguous data area to be used in a data transfer. The iovec structure is the element type in an array pointed to by the uio_iov field in the uio structure. This array can contain any number of iovec structures, each of which describes a single unit of contiguous storage. Taken together, these units represent the total area into which, or from which, data is to be transferred. The uio_iovcnt field gives the number of iovec structures in the array.
The iovec structure contains the following fields:
The ddread device driver entry point, ddwrite device driver entry point.
The uiomove kernel service, uphysio kernel service, ureadc kernel service, uwritec kernel service.
The fcntl subroutine, lseek subroutine.
Device Driver Kernel Extension Overview in AIX Kernel Extensions and Device Support Programming Concepts.
Programming In the Kernel Environment Overview in AIX Kernel Extensions and Device Support Programming Concepts.
Cross Memory Kernel Services in AIX Kernel Extensions and Device Support Programming Concepts.