简体   繁体   English

在 Golang 的 syscall 包中,syscall.Syscall() 是如何以及在何处为特定于 Windows 的系统调用定义的?

[英]How and where is syscall.Syscall() defined for Windows-specific system calls in Golang's syscall package?

I'm trying to understand some of the low-level details of Golangs syscall package.我试图了解 Golangs 系统调用包的一些低级细节。 In particular, I'm interested in Windows-specific system calls (see the example below).特别是,我对特定于 Windows 的系统调用感兴趣(请参见下面的示例)。

I can find the definition of syscall.Syscall() for UNIX-based systems:我可以找到基于 UNIX 的系统的syscall.Syscall()的定义:

However, I cannot find any such definition for Windows-based systems, like an asm_windows_amd64.s .但是,我找不到基于 Windows 的系统的任何此类定义,例如asm_windows_amd64.s

In particular, asm_unix_amd64.s has the following build directive, so its ·Syscall(SB),NOSPLIT,$0-56 definition cannot be the one also called for Windows system calls:特别是, asm_unix_amd64.s有以下构建指令,所以它的·Syscall(SB),NOSPLIT,$0-56定义不能是 Windows 系统调用也调用的:

 1// +build netbsd freebsd openbsd dragonfly

Where is syscall.Syscall() defined for Windows-based systems? syscall.Syscall()在哪里为基于 Windows 的系统定义?

Example: https://godoc.org/golang.org/x/sys/windows#example-LoadLibrary示例: 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")

I don't have or use Windows, but some grep work with the source finds this:我没有或使用 Windows,但一些 grep 与源的工作发现这一点:

  • syscall.Syscall , syscall.Syscall6 , and so on are defined in runtime/syscall_windows.go . syscall.Syscallsyscall.Syscall6等在runtime/syscall_windows.go中定义。 For instance, starting at line 179 (currently):例如,从第 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 cn = nargs c.args = uintptr(noescape(unsafe.Pointer(&a1))) cgocall(asmstdcallAddr, unsafe.Pointer(c)) return c.r1, c.r2, c.err

    } }

    The go:linkname is the magic that makes this function be named syscall.Syscall , even though it's named runtime.syscall_Syscall here. go:linkname是使这个函数被命名为syscall.Syscall的魔法,即使它在这里被命名为runtime.syscall_Syscall

  • These use DLLs loaded earlier to figure out how to really make the system calls.这些使用之前加载的 DLL 来确定如何真正进行系统调用。 (This is what c.fn is about.) To call into the DLLs, the Go runtime must lock the thread (see the first two calls) and use cgocall to invoke the DLL. (这就是c.fn作用。)为了调用 DLL,Go 运行时必须锁定线程(参见前两个调用)并使用cgocall来调用 DLL。 Furthermore, special trickery is required to pass the parameters using the structure obtained by getc().m.syscall .此外,使用getc().m.syscall获得的结构传递参数需要特殊的getc().m.syscall

  • Startup loading appears to happen via runtime/os_windows.go .启动加载似乎是通过runtime/os_windows.go发生的。 Note that _GetProcAddress (and other functions) are filled-in by the Windows loader, which allows bootstrapping.请注意, _GetProcAddress (和其他函数)由 Windows 加载程序填充,它允许引导。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM