Как и где определяется syscall.Syscall () для системных вызовов Windows -specifi c в пакете Golang syscall? - PullRequest
0 голосов
/ 03 февраля 2020

Я пытаюсь понять некоторые подробности низкоуровневого пакета Golangs syscall. В частности, меня интересуют системные вызовы Windows -specifi c (см. Пример ниже).

Я могу найти определение syscall.Syscall() для систем UNIX:

Однако я не могу найти какие-либо такое определение для Windows систем, таких как asm_windows_amd64.s.

В частности, asm_unix_amd64.s имеет следующую директиву сборки, поэтому его определение ·Syscall(SB),NOSPLIT,$0-56 не может быть тем, которое также вызывается для Windows системные вызовы:

 1// +build netbsd freebsd openbsd dragonfly

Где определено syscall.Syscall() для систем Windows?

Пример: https://godoc.org/golang.org/x/sys/windows#example -LoadLibrary

h, err := windows.LoadLibrary("kernel32.dll")
if err != nil {
    abort("LoadLibrary", err)
}
defer windows.FreeLibrary(h)
proc, err := windows.GetProcAddress(h, "GetVersion")
if err != nil {
    abort("GetProcAddress", err)
}
r, _, _ := syscall.Syscall(uintptr(proc), 0, 0, 0, 0)
major := byte(r)
minor := uint8(r >> 8)
build := uint16(r >> 16)
print("windows version ", major, ".", minor, " (Build ", build, ")\n")

1 Ответ

0 голосов
/ 03 февраля 2020

У меня нет или не используется Windows, но некоторая работа grep с источником находит это:

  • syscall.Syscall, syscall.Syscall6 и т. Д. Определены в runtime/syscall_windows.go. Например, начиная со строки 179 (в настоящее время):

    //go:linkname syscall_Syscall syscall.Syscall
    //go:nosplit
    func syscall_Syscall(fn, nargs, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
        lockOSThread()
        defer unlockOSThread()
        c := &getg().m.syscall
        c.fn = fn
        c.n = nargs
        c.args = uintptr(noescape(unsafe.Pointer(&a1)))
        cgocall(asmstdcallAddr, unsafe.Pointer(c))
        return c.r1, c.r2, c.err
    

    }

    go:linkname - это маги c, который дает этой функции имя syscall.Syscall, даже если она с именем runtime.syscall_Syscall здесь.

  • Они используют загруженные ранее библиотеки DLL, чтобы выяснить, как действительно выполнять системные вызовы. (Вот о чем c.fn.) Чтобы вызвать DLL, среда выполнения Go должна заблокировать поток (см. Первые два вызова) и использовать cgocall для вызова DLL. Кроме того, для передачи параметров требуется специальная хитрость с использованием структуры, полученной с помощью getc().m.syscall.

  • Загрузка при запуске, по-видимому, происходит через runtime/os_windows.go. Обратите внимание, что _GetProcAddress (и другие функции) заполняются загрузчиком Windows, который позволяет загрузиться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...