c - mmap 缓冲区到文件句柄

标签 c go posix cgo

我需要“伪造”一个文件描述符(支持fstat),我就是这样做的。

func ScanBytes(b []byte) error {
  size := C.size_t(len(b))
  path := C.CString("/bytes")
  fd := C.shm_open(path, C.O_RDWR|C.O_CREAT, C.mode_t(0600))
  defer C.shm_unlink(path)
  defer C.close(fd)

  res := C.ftruncate(fd, C.__off_t(size))
  if res != 0 {
    return fmt.Errorf("could not allocate shared memory region (%d)", res)
  }

  var addr = unsafe.Pointer(&b[0])
  C.mmap(addr, size, C.PROT_READ|C.PROT_WRITE, C.MAP_SHARED|C.MAP_FIXED, fd, 0)
  defer C.munmap(addr, size)

  // _, err := syscall.Write(int(fd), b)

  return doSomethingWith(fd)
}

您会看到文件句柄的写入被注释掉。

如果我不将缓冲区写入分配的区域,它就是空的。 我希望 mmapMAP_FIXED 结合使用所提供的缓冲区的地址,从而将内容映射到该区域。

我猜想 write 调用会复制,从而使内存使用量加倍。我真的必须吗?

最佳答案

听起来您想要的是能够通过文件描述符访问现有的内存区域而无需复制。

这个问题听起来很像 this previous stackoverflow question about mmap .

这个答案没有什么可补充的。由于您无法控制 b 的分配,因此在没有副本的情况下不可能执行此操作。接受需要副本,您的 shm 解决方案很好。不需要 mmap。

从 mmap 的手册页中,MAP_FIXED 的定义:

Do not permit the system to select a different address than the one specified. If the specified address cannot be used, mmap() will fail. If MAP_FIXED is specified, addr must be a multiple of the pagesize. If a MAP_FIXED request is successful, the mapping established by mmap() replaces any previous mappings for the process' pages in the range from addr to addr + len. Use of this option is discouraged.

unsafe.Pointer(&b[0]) 很可能不是页面大小的倍数,特别是当底层数组很小时。在这种情况下 mmap 将失败。与往常一样,检查返回值

如果 mmap 成功,该映射将替换任何以前的映射,这意味着您的数据现在已经消失。读取 slice 会给你零字节。

关于c - mmap 缓冲区到文件句柄,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20126447/

相关文章:

c - 有没有办法确定是否有任何线程正在等待给定的条件变量?

C 和 POSIX Pthreads

go - 在没有第三方路由库的情况下路由 PUT 请求

go - 如何定义返回函数的函数?

linux - 通过域套接字传输的单个数据包大小的实际限制是多少?

c - 为什么我的程序可以在 Xcode 上运行,但不能在 codeblocks 上运行

go - 如何将 IntelliJ Go 调试器附加到本地进程

C - 使用 mmap 通过共享内存读取整数

c - 删除树节点时出现访问冲突错误

c - 用于读取输入的动态缓冲区大小