c - 如何从 golang 正确地 IOCTL

标签 c linux go raspberry-pi ioctl

我正在尝试移植 raspberrypi's userspace 的位从 C 到 golang 的代码,我遇到了一个涉及 ioctl() 的程序。

我在执行 C 代码时遇到了问题

#define MAJOR_NUM 100
#define IOCTL_MBOX_PROPERTY _IOWR(MAJOR_NUM, 0, char *)
static int mbox_property(int file_desc, void *buf){

   int ret_val = ioctl(file_desc, IOCTL_MBOX_PROPERTY, buf);
   return ret_val;
}

我的 go 等价物是

func mBoxProperty(f *os.File, buf [256]int64) {
        err := Ioctl(f.Fd(), IOWR(100, 0, 8), uintptr(unsafe.Pointer(&buf[0])))

        if err != nil {
                log.Fatalln("mBoxProperty() : ", err)
        }

}

func Ioctl(fd, op, arg uintptr) error {
        _, _, ep := syscall.Syscall(syscall.SYS_IOCTL, fd, op, arg)
        if ep != 0 {
                return syscall.Errno(ep)
        }
        return nil
}

func IOWR(t, nr, size uintptr) uintptr {
        return IOC(IocRead|IocWrite, t, nr, size)
}
func IOC(dir, t, nr, size uintptr) uintptr {
        return (dir << IocDirshift) | (t << IocTypeshift) | (nr << IocNrshift) | (size << IocSizeshift)
}

但每当我运行它时,我都会收到 invalid argument 错误,我认为这可能是由于我如何调用 IOCTL() 但我不确定,如何我可以解决这个问题吗?

最佳答案

"golang.org/x/sys/unix" 中有ioctl(2) 个包装器. unix.IoctlSetInt机械上可能会满足您的需求。

看起来您正在将对小内存缓冲区的控制权交给内核。你需要小心这样做:Go 垃圾收集器释放它认为没有被使用的内存对象,即使某些东西正在使用,它也可以移动它。内核不会知道这一点并将继续使用旧指针。 unsafe.Pointer文档在这个主题上有很多话要说,即使是关于不那么奇特的系统调用。我不知道有什么可以将 Go 对象“锁定”在内存中以防止它被移动或释放(例如,runtime 包中没有任何内容跳出)。

您可以考虑使用 cgo 编写一个非常小的扩展malloc() 编辑了一个适当的缓冲区并将其交给 ioctl。 malloc 的内存不是垃圾收集的,因此它不会移动或从您的下方释放;一些低级工具可能认为这看起来像是内存泄漏(保留指针的旧值以便以后能够释放它并避免这种情况并不是一个坏主意)。

关于c - 如何从 golang 正确地 IOCTL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54388088/

相关文章:

C:socket连接超时

c - wdk 8.1 kmdf驱动蓝屏

c - 指针队列提取在C中进入无限循环

c++ - 库正在调用可执行文件内的函数,而不是库内的函数

linux - 在不升级的情况下恢复包状态以保持 Docker 容器较小

oracle - 无法使用Oracle db在Golang中构建应用

c - 使用 .h 文件中声明的 C 类型

linux - 强制查找查找所有子目录

xml - 从 XML 模板生成 XML 文档

go - 如何在Go中获取特定扩展名的文件数?