从.NET9看Golang

点击上方蓝字 江湖评谈设为关注/星标

0b286cc508e4ee4762fd64d0978f0d20.png

前言

NET9在Linux入口是Glibc,偶然看到Go的main入口不是Glibc,这难道是GO的性能和体积都具有优势的地方,本篇看下Glibc。

Go操作

#apt install golang-go 安装
#go verison 查看版本号
#which gdb查看调试器
#go run godemo.go 运行
#go build 生成可执行文件

例子:

# filename gofirstproj.go 可执行文件名 gofirstproj
package main
import "fmt"
func main() {
    fmt.Printf("Welcome to golang World\n")
}

GDB

#readelf gofirstproj 查看下go可执行文件头
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x45bfa0
  Start of program headers:          64 (bytes into file)
  Start of section headers:          456 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         7
  Size of section headers:           64 (bytes)
  Number of section headers:         23
  Section header string table index: 3
#gdb gofirstproj
(gdb)b main.main 两个main注意了
(gdb)r
(gdb)n 下一步
(gdb)bt
#0  runtime.sigtramp () at /usr/lib/go-1.18/src/runtime/sys_linux_amd64.s:353
#1  0x000000000045c5e0 in ?? ()
#2  0x0000000000000007 in ?? ()
#3  0x0000000000000000 in ?? ()

看到GO的这个main入口是在文件sys_linux_amd64.s里,具体代码如下(实际GO main调用是在353行PUSH_REGS_HOST_TO_ABI0):

337 TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
338         MOVQ    fn+0(FP),    AX
339         MOVL    sig+8(FP),   DI
340         MOVQ    info+16(FP), SI
341         MOVQ    ctx+24(FP),  DX
342         PUSHQ   BP
343         MOVQ    SP, BP
344         ANDQ    $~15, SP     // alignment for x86_64 ABI
345         CALL    AX
346         MOVQ    BP, SP
347         POPQ    BP
348         RET
349 
350 // Called using C ABI.
351 TEXT runtime·sigtramp(SB),NOSPLIT,$0
352         // Transition from C ABI to Go ABI.
353         PUSH_REGS_HOST_TO_ABI0()
354 
355         // Call into the Go signal handler
356         NOP     SP              // disable vet stack checking
357         ADJSP   $24
358         MOVQ    DI, 0(SP)       // sig
359         MOVQ    SI, 8(SP)       // info
360         MOVQ    DX, 16(SP)      // ctx
361         CALL    ·sigtrampgo(SB)
362         ADJSP   $-24

可以看到main确实不是glibc里面被调用的,而是go1.18版本自己用汇编代码实现的main调用。把CGO_ENABLED关闭和开启分别试下:

#go env 查看go环境变量,CGO_ENABLED默认为1
#CGO_ENABLED=0 go build -o no_cgo gofirstproj.go 
#CGO_ENABLED=1 go build -o yes_cgo gofirstproj.go
#ldd no_cgo yes_cgo 
no_cgo:
  not a dynamic executable
yes_cgo:
  not a dynamic executable

看到无论CGO_ENABLED开启或者是关闭都没有动态依赖,难道go1.18都是静态链接了?

.NET9

用lldb看下.NET9的corerun-Main的Linux下面是被谁调用的

#lldb corerun ConsoleApp1.dll
(lldb) b main
(lldb)r  
(lldb)bt
* thread #1, name = 'corerun', stop reason = breakpoint 1.1
  * frame #0: 0x000055555556c420 corerun`main(argc=<unavailable>, argv=<unavailable>) at corerun.cpp:616
    frame #1: 0x00007ffff7829d90 libc.so.6`__libc_start_call_main(main=(corerun`main at corerun.cpp:616), argc=2, argv=0x00007fffffffdef8) at libc_start_call_main.h:58:16
    frame #2: 0x00007ffff7829e40 libc.so.6`__libc_start_main_impl(main=(corerun`main at corerun.cpp:616), argc=2, argv=0x00007fffffffdef8, init=0x00007ffff7ffd040, fini=<unavailable>, rtld_fini=<unavailable>, stack_end=0x00007fffffffdee8) at libc-start.c:392:3
    frame #3: 0x000055555556bf45 corerun`_start + 37

很清晰的看到了libc-start.c,它即 是 GNU C 库(Glibc)的一部分。

结尾

Go能直接避开Glibc用自己的汇编代码调用Main入口,确实属于非常独立的可执行文件,可以避免很多的依赖纠缠,各种发行版的特性阻碍。.NET目前似乎尚未实现此功能,.NET9 PreView2里面的AOT自举来看,以后不排除也会这样搞。至于性能和体积方面的优势,需要更多深入了解GO才能下结论。

b9b97167f5715e58ef09087d82038c95.jpeg

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值