W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
main.main就是用戶的main函數(shù)。這里是指Go的runtime在進入用戶main函數(shù)之前做的一些事情。
前面已經(jīng)介紹了從Go程序執(zhí)行后的第一條指令,到啟動runtime.main的主要流程,比如其中要設(shè)置好本地線程存儲,設(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之前,還有一些工作要做。
在main.main執(zhí)行之前,Go語言的runtime庫會初始化一些后臺任務,其中一個任務就是sysmon。
newm(sysmon, nil);
newm新建一個結(jié)構(gòu)體M,第一個參數(shù)是這個結(jié)構(gòu)體M的入口函數(shù),也就說會在一個新的物理線程中運行sysmon函數(shù)。由此可見sysmon是一個地位非常高的后臺任務,整個函數(shù)體一個死循環(huán)的形式,目前主要處理兩個事件:對于網(wǎng)絡的epoll以及搶占式調(diào)度的檢測。大致過程如下:
for(;;) {
runtime.usleep(delay);
if(lastpoll != 0 && lastpoll + 10*1000*1000 > now) {
runtime.netpoll();
}
retake(now); // 根據(jù)每個P的狀態(tài)和運行時間決定是否要進行搶占
}
sysmon會根據(jù)系統(tǒng)當前的繁忙程度睡一小段時間,然后每隔10ms至少進行一次epoll并喚醒相應的goroutine。同時,它還會檢測是否有P長時間處于Psyscall狀態(tài)或Prunning狀態(tài),并進行搶占式調(diào)度。
scavenger是另一個后臺任務,但是它的創(chuàng)建跟sysmon有點區(qū)別:
runtime·newproc(&scavenger, nil, 0, 0, runtime·main);
newproc創(chuàng)建一個goroutine,第一個參數(shù)是goroutine運行的函數(shù)。scavenger的地位是沒有sysmon那么高的——sysmon是由物理線程運行的,而scavenger只是由goroutine運行的。接下來的章節(jié)會說明goroutine與物理線程的區(qū)別。
那么,scavenger執(zhí)行什么工作?它又為什么不像sysmon那樣呢?其實scavenger執(zhí)行的是runtime·MHeap_Scavenger函數(shù)。它將一些不再使用的內(nèi)存歸還給操作系統(tǒng)。Go是一門垃圾回收
的語言,垃圾回收會在系統(tǒng)運行過程中被觸發(fā),內(nèi)存會被歸還到Go的內(nèi)存管理系統(tǒng)中,Go的內(nèi)存管理是基于內(nèi)存池進行重用的,而這個函數(shù)會真正地將內(nèi)存歸還給操作系統(tǒng)。
scavenger顯然沒有sysmon要求那么高,所以它僅僅是一個普通的goroutine而不是一個線程。
main.main在這些后臺任務運行起來之后執(zhí)行,不過在它執(zhí)行之前,還有最后一個:main.init,每個包的init函數(shù)會在包使用之前先執(zhí)行。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: