7.6. mmap()

mmap(void * start, size_t length, int prot, int flags, int sg_fd, off_t offset)。 此系统调用返回一个指针,指向与 sg 文件描述符 'sg_fd' 关联的保留缓冲区起始位置。 'start' 参数是给内核的提示,会被此驱动程序忽略;最好将其设置为 0。 'length' 参数应小于或等于与 'sg_fd' 关联的保留缓冲区的大小。 如果它超过了保留缓冲区大小(在 'length' 向上舍入为页大小的倍数之后),则返回 MAP_FAILED,并且 ENOMEM 会被置于 errno 中。 'prot' 参数应为 PROT_READ 或 (PROT_READ | PROT_WRITE)。 'flags' 参数应包含 MAP_SHARED。 从某种意义上说,用户应用程序正在与 sg 驱动程序“共享”数据。 MAP_PRIVATE 标志与编译器优化标志(如 '-O2')不能很好地协同工作。 'offset' 参数必须设置为 0(或 NULL)。

可以在同一个 sg_fd 上多次调用 mmap() 系统调用。 如果在 sg_fd 上调用了 close(),则不需要 munmap() 系统调用。 当进程被 fork()(或执行等效的更细粒度的 clone() 系统调用)时,mmap 映射的 IO 行为良好。 在 fork() 的情况下,两个进程将与 sg 驱动程序一起共享同一块内存映射区域,用于 sg_fd,并且最后一个关闭 sg_fd(或退出)的进程将导致共享内存被释放。

假定如果默认的 32 KB 保留缓冲区大小不足,则在任何 mmap() 调用之前,都会调用 ioctl(SG_SET_RESERVED_SIZE)。 如果所需的 size 不是内核页大小(由 getpagesize() 系统调用返回)的倍数,则传递给 ioctl(SG_SET_RESERVED_SIZE) 的 size 应向上舍入到下一个页大小的倍数。

通过在调用 write() 或 ioctl(SG_IO) 之前,将 SG_FLAG_MMAP_IO 常量设置(或按位或运算)到 sg_io_hdr 结构的 flag 成员中,来请求 Mmap 映射的 IO。 执行 mmap 映射 IO 的逻辑 _假定_ 应用程序已进行了适当的 mmap() 调用。 换句话说,它不会进行检查。 [1]

注释

[1]

sg 驱动程序确实会记录 mmap() 系统调用已在文件描述符上至少被调用过一次。 这并不足够,因为给定的 'length' 可能对于当前的 IO 来说太短。 此外,驱动程序不知道 munmap() 调用,因此很容易被欺骗。