errno to Go 错误

我正在尝试从 Go 代码中发出 KVM 图标。目前我有如下内容:


func (vm *Vm) RegisterIrqFd(efd *EventFd, gsi uint32) error {

    irqfd := (*C.struct_kvm_irqfd)(C.calloc(1, C.sizeof_struct_kvm_irqfd))

    defer C.free(unsafe.Pointer(irqfd))

    irqfd.fd = C.uint(efd.Fd())

    irqfd.gsi = C.uint(gsi)

    if _, err := sysutils.Ioctl(vm.Fd(), C.KVM_IRQFD, uintptr(unsafe.Pointer(irqfd))); err != nil {

        return fmt.Errorf("RegisterIrqFd failed: %v", err)

    }

    return nil

}

Ioctl 函数的实现方式如下:


func Ioctl(fd uintptr, cmd C.uint, arg uintptr) (uintptr, error) {

    ret, _, errno := syscall.Syscall(

        syscall.SYS_IOCTL,

        fd,

        uintptr(cmd),

        uintptr(arg),

    )

    if int64(ret) == -1 {

        return ret, ErrnoToErr(errno)

    }

    return ret, nil

}

而埃尔诺托尔函数的实现方式如下:


func ErrnoToErr(errno syscall.Errno) error {

    return fmt.Errorf("%v", errno.Error())

}

  1. 在内部 获得支持的处理器,ioctl的参数,是使用 分配的。如果这是C代码,则可以在堆栈上分配代码。有什么办法可以绕过使用caloc和免费使用分配吗?有什么替代方案会更习惯吗?cpuidC.calloccpuid

  2. 有没有办法让埃雷诺托埃尔返回一个与埃雷诺对应的 go 错误类型?目前它使用内部系统调用/syscall_unix.go;因此,它只是取消引用字符串列表并返回字符串。最好有一个类型,这样我就可以测试单元测试中的特定错误。(e Errno) Error()


森林海
浏览 126回答 2
2回答

当年话下

只需回复更新后的示例,我们就可以这样做:func (vm *Vm) RegisterIrqFd(efd *EventFd, gsi uint32) error {    irqfd := C.struct_kvm_irqfd{}    irqfd.fd = C.uint(efd.Fd())    irqfd.gsi = C.uint(gsi)    if _, err := sysutils.Ioctl(vm.Fd(), C.KVM_IRQFD, uintptr(unsafe.Pointer(&irqfd))); err != nil {        return fmt.Errorf("RegisterIrqFd failed: %v", err)    }    return nil}我认为这是安全的,但无论如何,我们可能会发现,因为我们把它的地址带到这里,在这种情况下,没有太多的节省。即便如此,只要这不违反Go指针规则(我不认为它确实如此),阅读起来会好得多。irqfd escapes to heap

扬帆大鱼

阅读文档系统调用。埃尔诺因此转换可以像这样执行func ErrnoToErr(errno syscall.Errno) error {    if errno != 0 {        return errno    }    return nil}对于平等,它只声明可以使用 errors.Is 根据 os 包中的错误值测试 Errno 值。比较错误的问题已经在这里考虑如何比较Go错误
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go