编写设备驱动程序

用户地址

当用户线程发出 write(2) 系统调用时,该线程会传递用户空间中某个缓冲区的地址:

    char buffer[] = "python";
    count = write(fd, buffer, strlen(buffer) + 1);

系统通过分配 iovec(9S) 结构,并将 iov_base 字段设置为传递给 write(2) 的地址(在本例中为 buffer),来生成 uio(9S) 结构以描述此传输。uio(9S) 结构将被传递到驱动程序 write(9E) 例程。有关 uio(9S) 结构的详细信息,请参见向量化的 I/O

iovec(9S) 中的地址位于用户空间而非内核空间。因此,既不能保证该地址当前处于内存中,也不能保证该地址是有效地址。无论哪一种情况,从设备驱动程序或从内核访问用户地址都会导致系统崩溃。因此,设备驱动程序永远不应该直接访问用户地址,而是应使用 Solaris DDI/DKI 中的数据传输例程,向内核中传送数据或从内核中读取数据。这些例程能够处理页面错误。DDI/DKI 例程可以读取适当的用户页面,以便继续进行透明复制。这些例程也可以在发生无效访问时返回错误。

使用 copyout(9F) 可将数据从内核空间复制到用户空间。copyin(9F) 可将数据从用户空间复制到内核空间。ddi_copyout(9F)ddi_copyin(9F) 的运行方式与它们类似,但要在 ioctl(9E) 例程中使用。可以对每个 iovec(9S) 结构描述的缓冲区使用 copyin(9F)copyout(9F),或者 uiomove(9F) 可以对驱动程序或设备内存的连续区域执行完整的数据传入或传出操作。