如何解决os161中的UIO_USERISPACE,UIO_USERSPACE和UIO_SYSSPACE是什么?
我正在尝试完成操作系统课程Here的作业。
我对作业有疑问:
UIO_USERISPACE和UIO_USERSPACE有什么区别?什么时候应该使用UIO_SYSSPACE代替?
当我在源代码中搜索here时,我发现了这一点:
/* 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 */
};
我可以看到它在结构uio
中使用(我将在另一个问题中对此进行询问)以指示“使用了哪种指针”。
此外,我可以在函数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.
函数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,* 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.
*/
函数uiomove
,here的定义:
int
uiomove(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,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;
}
我似乎不赞成使用它。谁能给我一些关于他们的直觉?例如,何时何地使用它们?他们的目的是什么?而且,对于原始问题的答案,UIO_USERISPACE
和UIO_USERSPACE
有什么区别?什么时候应该使用UIO_SYSSPACE
代替?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。