go語言檢查磁盤分區(qū)使用情況
創(chuàng)新互聯(lián)建站長期為1000多家客戶提供的網(wǎng)站建設(shè)服務(wù),團隊從業(yè)經(jīng)驗10年,關(guān)注不同地域、不同群體,并針對不同對象提供差異化的產(chǎn)品和服務(wù);打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為柯城企業(yè)提供專業(yè)的做網(wǎng)站、網(wǎng)站設(shè)計,柯城網(wǎng)站改版等技術(shù)服務(wù)。擁有十余年豐富建站經(jīng)驗和眾多成功案例,為您定制開發(fā)。
利用系統(tǒng)調(diào)用syscall.Statfs獲取磁盤分區(qū)使用情況
函數(shù)PartitionUsage()返回分區(qū)的使用百分比。參數(shù)path是分區(qū)的路徑,返回使用的四舍五入百分比值。
其中函數(shù)round就是模擬四舍五入的運算。
運行結(jié)果:
首先你的理解是錯的,不管用戶態(tài)的API(syscall)是否是同步還是異步,在kernel層面都是異步的。
其實實現(xiàn)原理很簡單,就是利用C(嵌入?yún)R編)語言可以直接修改寄存器(setcontext/setjmp/longjmp均是類似原理,修改程序指針eip實現(xiàn)跳轉(zhuǎn),棧指針實現(xiàn)上線文切換)來實現(xiàn)從func_a調(diào)進去,從func_b返回出來這種行為。對于golang來說,func_a/func_b屬于不同的goroutine,從而就實現(xiàn)了goroutine的調(diào)度切換。
另外對于所有可能阻塞的syscall,golang對其進行了封裝,底層實際是epoll方式做的,注冊回調(diào)后切換到另一個runnable的goroutine。
在golang中加載dll并調(diào)用函數(shù)流程如下:
1.加載dll動態(tài)庫到內(nèi)存 syscall.LoadLibrary
2.獲取函數(shù)地址 syscall.GetProcAddress
3.執(zhí)行系統(tǒng)調(diào)用,傳入?yún)?shù) syscall.Syscall6
一個系統(tǒng)消息框函數(shù)的調(diào)用示例:
一般來說,進程的操作使用的是一些系統(tǒng)的命令,所以go內(nèi)部使用os包,進行一些運行系統(tǒng)命令的操作
os 包及其子包 os/exec 提供了創(chuàng)建進程的方法。
一般的,應(yīng)該優(yōu)先使用 os/exec 包。因為 os/exec 包依賴 os 包中關(guān)鍵創(chuàng)建進程的 API,為了便于理解,我們先探討 os 包中和進程相關(guān)的部分。
Unix :fork創(chuàng)建一個進程,(及其一些變種,如 vfork、clone)。
Go:Linux 下創(chuàng)建進程使用的系統(tǒng)調(diào)用是 clone。
允許一進程(父進程)創(chuàng)建一新進程(子進程)。具體做法是,新的子進程幾近于對父進程的翻版:子進程獲得父進程的棧、數(shù)據(jù)段、堆和執(zhí)行文本段的拷貝??蓪⒋艘暈榘迅高M程一分為二。
終止一進程,將進程占用的所有資源(內(nèi)存、文件描述符等)歸還內(nèi)核,交其進行再次分配。參數(shù) status 為一整型變量,表示進程的退出狀態(tài)。父進程可使用系統(tǒng)調(diào)用 wait() 來獲取該狀態(tài)。
目的有二:其一,如果子進程尚未調(diào)用 exit() 終止,那么 wait 會掛起父進程直至子進程終止;其二,子進程的終止?fàn)顟B(tài)通過 wait 的 status 參數(shù)返回。
加載一個新程序(路徑名為 pathname,參數(shù)列表為 argv,環(huán)境變量列表為 envp)到當(dāng)前進程的內(nèi)存。這將丟棄現(xiàn)存的程序文本段,并為新程序重新創(chuàng)建棧、數(shù)據(jù)段以及堆。通常將這一動作稱為執(zhí)行一個新程序。
沒有直接提供 fork 系統(tǒng)調(diào)用的封裝,而是將 fork 和 execve 合二為一,提供了 syscall.ForkExec。如果想只調(diào)用 fork,得自己通過 syscall.Syscall(syscall.SYS_FORK, 0, 0, 0) 實現(xiàn)。
os.Process 存儲了通過 StartProcess 創(chuàng)建的進程的相關(guān)信息。
一般通過 StartProcess 創(chuàng)建 Process 的實例,函數(shù)聲明如下:
它使用提供的程序名、命令行參數(shù)、屬性開始一個新進程。StartProcess 是一個低級別的接口。os/exec 包提供了高級別的接口,一般應(yīng)該盡量使用 os/exec 包。如果出錯,錯誤的類型會是 *PathError。
屬性定義如下:
FindProcess 可以通過 pid 查找一個運行中的進程。該函數(shù)返回的 Process 對象可以用于獲取關(guān)于底層操作系統(tǒng)進程的信息。在 Unix 系統(tǒng)中,此函數(shù)總是成功,即使 pid 對應(yīng)的進程不存在。
Process 提供了四個方法:Kill、Signal、Wait 和 Release。其中 Kill 和 Signal 跟信號相關(guān),而 Kill 實際上就是調(diào)用 Signal,發(fā)送了 SIGKILL 信號,強制進程退出,關(guān)于信號,后續(xù)章節(jié)會專門講解。
Release 方法用于釋放 Process 對象相關(guān)的資源,以便將來可以被再使用。該方法只有在確定沒有調(diào)用 Wait 時才需要調(diào)用。Unix 中,該方法的內(nèi)部實現(xiàn)只是將 Process 的 pid 置為 -1。
通過 os 包可以做到運行外部命令,如前面的例子。不過,Go 標(biāo)準(zhǔn)庫為我們封裝了更好用的包: os/exec,運行外部命令,應(yīng)該優(yōu)先使用它,它包裝了 os.StartProcess 函數(shù)以便更容易的重定向標(biāo)準(zhǔn)輸入和輸出,使用管道連接 I/O,以及作其它的一些調(diào)整。
exec.LookPath 函數(shù)在 PATH 指定目錄中搜索可執(zhí)行程序,如 file 中有 /,則只在當(dāng)前目錄搜索。該函數(shù)返回完整路徑或相對于當(dāng)前路徑的一個相對路徑。
func LookPath(file string) (string, error)
如果在 PATH 中沒有找到可執(zhí)行文件,則返回 exec.ErrNotFound。
Cmd 結(jié)構(gòu)代表一個正在準(zhǔn)備或者在執(zhí)行中的外部命令,調(diào)用了 Run、Output 或 CombinedOutput 后,Cmd 實例不能被重用。
一般的,應(yīng)該通過 exec.Command 函數(shù)產(chǎn)生 Cmd 實例:
用法
得到 * Cmd 實例后,接下來一般有兩種寫法:
前面講到,通過 Cmd 實例后,有兩種方式運行命令。有時候,我們不只是簡單的運行命令,還希望能控制命令的輸入和輸出。通過上面的 API 介紹,控制輸入輸出有幾種方法:
參考資料: