這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
從Goroot的代碼出發,裡面有很多代碼非常複雜,一點點看吧。最重要的概念就是runtime,golang的程式都是在runtime的基礎上啟動並執行(除了與底層直接互動的syscall)。
Runtime
在$goroot/pkg/runtime/中有三個檔案非常重要:
proc.c
stack.h
runtime.h
在runtime.h中你能看到許多的資料結構和介面
這裡的資料結構就是go中的各種特定的結構對應的底層實現,比如slice:
structSlice{// must not move anythingbyte*array;// actual datauint32len;// number of elementsuint32cap;// 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處理器上。
一個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看到調用棧
關於啟動流程推薦一下這篇文章:http://www.cnblogs.com/genius0101/archive/2012/04/16/2447147.html
go中調用C程式
go中是可以調用C程式的,有兩種方法:
1 go程式使用import "C"
2 使用檔案.goc(以前也叫做cgo)
第一種方法
例子:
package main/*#include */import "C" import "fmt"func main(){ fmt.Println(int(C.random()))}func Seed(i int) { C.srandom(C.uint(i))}
運行
使用起來非常簡單,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
這種方式不允許include C的標準庫,只能引用自訂的標頭檔。這種方式很少使用,基本只需要知道一下就好了。
參考文章
我之前寫了文章把所有golang的底層相關文章列出來了
http://www.cnblogs.com/yjf512/archive/2012/07/17/2595689.html
如果有更多的好資料麻煩各位貼出來下~