Golang runtime 淺析

從Goroot的代碼出發,裏面有很多代碼非常複雜,一點點看吧。最重要的概念就是runtime,golang的程序都是在runtime的基礎上運行的(除了與底層直接交互的syscall)。

Runtime

在$goroot/pkg/runtime/中有三個文件非常重要:

proc.c

stack.h

runtime.h

 

在runtime.h中你能看到許多的數據結構和接口

這裏的數據結構就是go中的各種特定的結構對應的底層實現,比如slice:

1
2
3
4
5
6
7
struct   Slice
{                // must not move anything
     byte *   array;       // actual data
     uint32  len;         // number of elements
     uint32  cap;         // allocated number of elements
 
};

其中還有兩個重要的結構:

G

G代表的是goroutine。開啓一個goroutine實際就是實例化一個G

M

M代表的是Machine。M中存放go程序和機器CPU交互的數據結構

比如一個雙核CPU,在主routine外開啓了4個goroutine,那麼實際上就有2個M結構,6個G結構(1個是主routine,4個開啓的routine,最後一個是閒置的routine)

runtime和C標準庫起的作用是一樣的。都是爲了語言的跨平臺性。runtime可以運行在Windows和Unix平臺,可以運行在Intel或ARM處理器上。

clip_image001[4]

一個go程序都附帶一個Runtime,runtime負責與底層操作系統交互。

這篇文章給了一個清晰的runtime概念:http://pastebin.com/LEsB8FVW

啓動流程

回到$goroot/pkg/runtime/proc.c

裏面這麼個註釋:

// The bootstrap sequence is:

//

// call osinit

// call schedinit

// make & queue new G

// call runtime·mstart

//

// The new G calls runtime·main.

明確告訴我們go程序的啓動流程是:

1 調用osinit,操作系統級別的初始化

2 調用runtime·schedinit

在這個函數內做了許多預操作

獲取程序運行參數

獲取程序環境變量

(主要是有一個環境變量GOMAXPROCS,你可以使用runtime.GOMAXPROCS(int) 或者直接設置環境變量$GOMAXPROCS改變程序使用的CPU數量)

3 調用runtime·mstart啓動M

4 調用runtime·main

在runtime.main中有這麼兩行:

main·init(); //調用main包中的init函數

main·main(); //調用main包中的main函數

用gdb調試看trace看到調用棧

clip_image002[4]

關於啓動流程推薦一下這篇文章:http://www.cnblogs.com/genius0101/archive/2012/04/16/2447147.html

go中調用C程序

go中是可以調用C程序的,有兩種方法:

1 go程序使用import "C"

2 使用文件.goc(以前也叫做cgo)

第一種方法

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package main
 
/*
#include <stdlib.h>
*/
import  "C"
 
import  "fmt"
 
func main(){
     fmt.Println( int (C.random()))
}
 
func Seed(i  int ) {
     C.srandom(C. uint (i))
 
}</stdlib.h>

運行

clip_image003[4]

使用起來非常簡單,import "C"之後就有一個全局變量大寫C就包含了C庫中的函數, include的c庫作爲註釋放在import "C"上面

更多可以參考:

http://golang.org/doc/articles/c_go_cgo.html

http://golang.org/cmd/cgo/

第二種方法

直接創建goc文件,goc文件是C和go混合編寫的文件

參照$goroot/src/pkg/runtime/syscall_windows.goc

clip_image004[4]

這種方式不允許include C的標準庫,只能引用自定義的頭文件。這種方式很少使用,基本只需要知道一下就好了。