Go語言 main.main之前的準(zhǔn)備

2018-07-25 17:24 更新

main.main就是用戶的main函數(shù)。這里是指Go的runtime在進(jìn)入用戶main函數(shù)之前做的一些事情。

前面已經(jīng)介紹了從Go程序執(zhí)行后的第一條指令,到啟動(dòng)runtime.main的主要流程,比如其中要設(shè)置好本地線程存儲(chǔ),設(shè)置好main函數(shù)參數(shù),根據(jù)環(huán)境變量GOMAXPROCS設(shè)置好使用的procs,初始化調(diào)度器和內(nèi)存管理等等。

接下來將是從runtime.main到main.main之間的一些過程。注意,main.main是在runtime.main函數(shù)里面調(diào)用的。不過在調(diào)用main.main之前,還有一些工作要做。

sysmon

在main.main執(zhí)行之前,Go語言的runtime庫會(huì)初始化一些后臺(tái)任務(wù),其中一個(gè)任務(wù)就是sysmon。

newm(sysmon, nil);

newm新建一個(gè)結(jié)構(gòu)體M,第一個(gè)參數(shù)是這個(gè)結(jié)構(gòu)體M的入口函數(shù),也就說會(huì)在一個(gè)新的物理線程中運(yùn)行sysmon函數(shù)。由此可見sysmon是一個(gè)地位非常高的后臺(tái)任務(wù),整個(gè)函數(shù)體一個(gè)死循環(huán)的形式,目前主要處理兩個(gè)事件:對(duì)于網(wǎng)絡(luò)的epoll以及搶占式調(diào)度的檢測(cè)。大致過程如下:

for(;;) {
    runtime.usleep(delay);
    if(lastpoll != 0 && lastpoll + 10*1000*1000 > now) {
        runtime.netpoll();
    }
    retake(now);    // 根據(jù)每個(gè)P的狀態(tài)和運(yùn)行時(shí)間決定是否要進(jìn)行搶占
}

sysmon會(huì)根據(jù)系統(tǒng)當(dāng)前的繁忙程度睡一小段時(shí)間,然后每隔10ms至少進(jìn)行一次epoll并喚醒相應(yīng)的goroutine。同時(shí),它還會(huì)檢測(cè)是否有P長(zhǎng)時(shí)間處于Psyscall狀態(tài)或Prunning狀態(tài),并進(jìn)行搶占式調(diào)度。

scavenger

scavenger是另一個(gè)后臺(tái)任務(wù),但是它的創(chuàng)建跟sysmon有點(diǎn)區(qū)別:

runtime·newproc(&scavenger, nil, 0, 0, runtime·main);

newproc創(chuàng)建一個(gè)goroutine,第一個(gè)參數(shù)是goroutine運(yùn)行的函數(shù)。scavenger的地位是沒有sysmon那么高的——sysmon是由物理線程運(yùn)行的,而scavenger只是由goroutine運(yùn)行的。接下來的章節(jié)會(huì)說明goroutine與物理線程的區(qū)別。

那么,scavenger執(zhí)行什么工作?它又為什么不像sysmon那樣呢?其實(shí)scavenger執(zhí)行的是runtime·MHeap_Scavenger函數(shù)。它將一些不再使用的內(nèi)存歸還給操作系統(tǒng)。Go是一門垃圾回收的語言,垃圾回收會(huì)在系統(tǒng)運(yùn)行過程中被觸發(fā),內(nèi)存會(huì)被歸還到Go的內(nèi)存管理系統(tǒng)中,Go的內(nèi)存管理是基于內(nèi)存池進(jìn)行重用的,而這個(gè)函數(shù)會(huì)真正地將內(nèi)存歸還給操作系統(tǒng)。

scavenger顯然沒有sysmon要求那么高,所以它僅僅是一個(gè)普通的goroutine而不是一個(gè)線程。

main.main在這些后臺(tái)任務(wù)運(yùn)行起來之后執(zhí)行,不過在它執(zhí)行之前,還有最后一個(gè):main.init,每個(gè)包的init函數(shù)會(huì)在包使用之前先執(zhí)行。

links


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)