Windows 在Golang';s系统调用包?

Windows 在Golang';s系统调用包?,windows,go,Windows,Go,我试图理解Golangs系统调用包的一些底层细节。特别是,我对特定于Windows的系统调用感兴趣(参见下面的示例) 我可以找到基于UNIX系统的syscall.syscall()的定义: 但是,对于基于Windows的系统,例如asm\u Windows\u amd64.s,我找不到任何这样的定义 特别是,asm_unix_amd64.s具有以下生成指令,因此其·Syscall(SB)、NOSPLIT、$0-56定义不能同时用于Windows系统调用: 1// +build netb

我试图理解Golangs系统调用包的一些底层细节。特别是,我对特定于Windows的系统调用感兴趣(参见下面的示例)

我可以找到基于UNIX系统的
syscall.syscall()
的定义:

但是,对于基于Windows的系统,例如
asm\u Windows\u amd64.s
,我找不到任何这样的定义

特别是,
asm_unix_amd64.s
具有以下生成指令,因此其
·Syscall(SB)、NOSPLIT、$0-56
定义不能同时用于Windows系统调用:

 1// +build netbsd freebsd openbsd dragonfly
哪里是为基于Windows的系统定义的
syscall.syscall()

示例:


我没有或没有使用Windows,但一些使用源代码的grep发现:

  • syscall.syscall
    syscall.Syscall6
    等在中定义。例如,从第179行开始(目前):

    }

    go:linkname
    是使此函数命名为
    syscall.syscall
    的魔法,即使它在此处命名为
    runtime.syscall\u syscall

  • 它们使用前面加载的DLL来确定如何真正进行系统调用。(这就是
    c.fn
    要调用DLL,Go运行时必须锁定线程(参见前两个调用)并使用
    cgocall
    调用DLL。此外,使用通过
    getc().m.syscall
    获得的结构传递参数需要特殊的技巧

  • 启动加载似乎通过发生。请注意,
    \u GetProcAddress
    (和其他函数)由Windows加载程序填充,它允许引导


因为Windows每隔一小时左右(好吧,也许每个月左右)对系统调用重新编号,所以没有一个头脑正常的人会直接使用它们。调用总是通过一些DLL进行,这些DLL使用未发布的Microsoft机密将名称映射到系统调用号。Go似乎做了同样的事情,并且在构建时生成代码,使用@torek调用DLL-您能找到在上面的示例中调用的
syscall.syscall()
的定义吗:
r,,:=syscall.syscall(uintpttr(proc),0,0,0)
?另外,这里我使用的不是系统调用号,而是函数的DLL地址:
windows.GetProcAddress(h,“GetVersion”)
。。。我想。窗户是个谜;我建议自己不要用,也不要用。AHA:不,它在
运行时/syscall\u窗口中。go
。Linkname pragma导出具有给定名称的函数谢谢。你是说它的名字叫
runtime.syscall\u syscall
?Unix系统调用是在
系统调用
包中定义的,而Windows系统调用是在
运行时
中定义的,这是一个奇怪的决定-我不知道要看那里。这些功能是如何联系在一起的?它像静态链接还是动态链接?哎呀,对了,它应该是
runtime.syscall\u syscall
,但要不是linkname技巧。你也知道链接是怎么发生的吗?
//go:linkname
实际上并不是指“二进制链接”,是吗?它只是在运行时创建一个别名,对吗?至于链接,我没有研究Go编译器和链接器是如何工作的,但它们是Go构建系统的私有部分。
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")
//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