【Free Style】CGO: Go与C互操作技术(四):疑难问题一

举报
赵志强 发表于 2017/11/17 16:02:59 2017/11/17
【摘要】 如何在Go中使用cputicks函数,如何使用Go的runtime中的cputicks函数?在C中,可以利用C嵌汇编的方式,通过rdtsc寄存器获取CPU的ticks。在Go中一种方式是可以通过Plan 9汇编定义一个Go的函数:-Groovy 代码1TEXT ·cputicks(SB),NOSPLIT,$0-02 RDTSC3 SHLQ $32, DX4

如何在Go中使用cputicks函数,如何使用Go的runtime中的cputicks函数?

在C中,可以利用C嵌汇编的方式,通过rdtsc寄存器获取CPU的ticks。在Go中一种方式是可以通过Plan 9汇编定义一个Go的函数:

-

Groovy 代码


1TEXT ·cputicks(SB),NOSPLIT,$0-0
2        RDTSC
3        SHLQ    $32, DX
4        ADDQ    DX, AX
5        MOVQ    AX, ret+0(FP)
6        RET

另一种方式,则是直接调用Go的私有函数runtime.cputicks。具体代码如下所示:

-

Groovy 代码


01package main
02
03import "unsafe"
04
05//go:linkname cputicks runtime.cputicks
06func cputicks() int64
07
08func main() {
09    println(cputicks())
10}

在这个例子中,使用了//go:linkname 这个编译制导语句,它会在链接时,把package main下面的cputicks与runtime.cputicks绑定在一起。这样在调用cputicks时,其实是调用的runtime.cputicks。另外,如果是只有这一个Go文件时,请在当前目录下创建一个空的asm.s文件。这是为了欺骗编译器。在编译期,当Go的编译器发现func cputicks() int64这个函数声明时,会寻找该函数的函数体。如果当前只有一个Go文件,则编译器就可以判定这个函数是没有函数体的。这样到不了链接期,编译过程就被打断了。如果在旁边再有一个空的asm.s文件,则在编译这个Go文件时,Go的编译器无法判断是否真的不存在这个函数声明的函数体。也就在不会在编译期出错了。当进入链接期,由于linkname的作用,该函数可以编译通过。


另外,不仅是cputicks,对于任何的不可见的函数都可以这么做。不过不建议滥用,请控制这种用法的使用范围



Go程序的链接并不使用链接脚本,如何给Go程序增加自定义段?



Go使用自带的链接器go tool link。这个链接器不使用链接脚本,所以在Go中无法想C那样定义自定义段。但并不是说在Go中没法增加自定义段。可以借助CGO实现这个目的。下面是Go文件

-

Groovy 代码


1package main
2
3// void sub() {}
4import "C"
5
6func main() {}


只需要在这里面能引起C的编译即可。编译命令是关键:

-

Bash 代码


1go build -o main -ldflags "-extldflags '-Xlinker -T linux64.lds'"

这里借助gcc的把链接脚本里面的信息拿进来。最后效果:

-

Bash 代码


查看代码

10000700100000001 <__CustomSeg>:
2    700100000001:       00 00                   add    %al,(%rax)
3        ...


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。