Как правильно IOCTL из Голанга - PullRequest
0 голосов
/ 27 января 2019

Я пытаюсь перенести бит пользовательского пространства 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(), но я не уверен, как я могу это исправить?

1 Ответ

0 голосов
/ 27 января 2019

В "golang.org/x/sys/unix" есть ioctl (2) обертки.unix.IoctlSetInt может механически удовлетворить ваши потребности.

Выглядит также, как будто вы передаете ядру управление небольшим буфером памяти.Вы должны быть осторожны при этом: сборщик мусора Go освобождает объекты памяти, которые, по его мнению, не используются, и даже если что-то используется, оно может перемещать его.Ядро не будет знать об этом и будет продолжать использовать старый указатель.Документация unsafe.Pointer содержит достаточно информации по этой теме, даже в отношении менее экзотических системных вызовов.Я не знаю ничего, что могло бы «заблокировать» объект Go в памяти, чтобы предотвратить его перемещение или освобождение (например, в пакете runtime ничего не выпадает).

Вы могли бы рассмотретьнаписать очень маленькое расширение, используя cgo , которое malloc() отредактировало соответствующий буфер и передало его в ioctl.память malloc'd не является сборщиком мусора, поэтому она не будет перемещаться или освобождаться из-под вас;некоторые низкоуровневые инструменты могут подумать, что это похоже на утечку памяти (было бы неплохо сохранить старое значение указателя, чтобы иметь возможность позже его освободить и избежать этого).

...