![](/img/trans.png)
[英]Using ioctl(), read() and malloc() to receive a message from server not working properly
[英]How to IOCTL properly from golang
我试图将raspberrypi 的用户空间代码从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;
}
而我与此等效的是
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的内存不会被垃圾收集,因此不会移动或从您的身下释放; 一些低级的工具可能会认为这看起来像是内存泄漏(保留指针的旧值以便以后释放它并躲避它并不是一个坏主意)。
您可能还不了解uintpr(unsafe.Pointer(...))
在调用 syscall.Syscall
需要发生的细节。
以下是详细信息,来自https://golang.org/pkg/unsafe/#Pointer
(4)调用syscall.Syscall时将指针转换为uintptr。
软件包syscall中的Syscall函数将其uintptr参数直接传递给操作系统,然后,操作系统可以根据调用的详细信息将其中一些参数重新解释为指针。 也就是说,系统调用实现正在将某些参数从uintptr隐式转换回指针。
如果必须将指针参数转换为uintptr用作参数,则该转换必须出现在调用表达式本身中:
syscall.Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(p)), uintptr(n))
编译器通过安排所引用的分配对象(如果有的话)被保留并且直到调用完成才移动,即使从类型本身开始,也处理在汇编中实现的函数的调用的参数列表中转换为uintptr的Pointer。似乎在调用过程中不再需要该对象。
为了使编译器能够识别这种模式,转换必须出现在参数列表中:
// INVALID: uintptr cannot be stored in variable // before implicit conversion back to Pointer during system call. u := uintptr(unsafe.Pointer(p)) syscall.Syscall(SYS_READ, uintptr(fd), u, uintptr(n))
这种unsafe
使用方法可以使您“锁定” Dave Maze在上面寻找的Go对象。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.