前段時(shí)間業(yè)務(wù)反映某類服務(wù)器上更新了 bash 之后,ssh 連上去偶發(fā)登陸失敗,客戶端吐出錯(cuò)誤信息如下所示:
iOS培訓(xùn),Swift培訓(xùn),蘋果開(kāi)發(fā)培訓(xùn),移動(dòng)開(kāi)發(fā)培訓(xùn)
圖 - 0

該版本 bash 為部門這邊所定制,但實(shí)現(xiàn)上并沒(méi)有改動(dòng)原有邏輯,只是加入了些監(jiān)控功能,那么這些錯(cuò)誤從哪里來(lái)呢?

是 bash 的鍋嗎

從上面的錯(cuò)誤信息可以猜測(cè),異常是 bash 在啟動(dòng)過(guò)程中分配內(nèi)存失敗所導(dǎo)致,看起來(lái)像是某些情況下該進(jìn)程錯(cuò)誤地進(jìn)行了大量?jī)?nèi)存分配,最后導(dǎo)致內(nèi)存不足,要確認(rèn)這個(gè)事情比較簡(jiǎn)單,動(dòng)態(tài)內(nèi)存分配到系統(tǒng)調(diào)用這一層上主要就兩種方式: brk() 和 mmap(), 所以只要統(tǒng)計(jì)一下這兩者的調(diào)用就可以大概估算出是否有大內(nèi)存分配了。

bash 是由 sshd 啟動(dòng)的,于是 strace 跟蹤了一下 sshd 進(jìn)程,結(jié)果發(fā)現(xiàn)異常發(fā)生時(shí),bash 分配的內(nèi)存非常地少,少到有時(shí)甚至只有幾十字節(jié)也會(huì)失敗,幾乎可以斷定 bash 在內(nèi)存使用上沒(méi)有異常,但在這期間發(fā)現(xiàn)一個(gè)詭異的現(xiàn)象,Bash 一直只用 brk 在分配小內(nèi)存,brk() 失敗后就直接退出了,一般程序使用的 libc 中的 malloc (或其它類似的 malloc) 會(huì)結(jié)合 brk 和 mmap 一起使用【0】,不至于 brk 一失敗就分配不到內(nèi)存,順手查看了下 bash 的源碼,發(fā)現(xiàn)它確實(shí)只基于 brk 做了自己的內(nèi)存管理,并沒(méi)有使用 malloc 或 mmap。

但那并不是重點(diǎn),重點(diǎn)是即使是只使用 brk,也不至于只能分配幾十字節(jié)的內(nèi)存。

進(jìn)程的內(nèi)存布局

進(jìn)程的內(nèi)存布局在結(jié)構(gòu)上是有規(guī)律的,具體來(lái)說(shuō)對(duì)于 linux 系統(tǒng)上的進(jìn)程,其內(nèi)存空間一般可以粗略地分為以下幾大段【1】,從高內(nèi)存到低內(nèi)存排列:
1、內(nèi)核態(tài)內(nèi)存空間,其大小一般比較固定(可以編譯時(shí)調(diào)整

網(wǎng)友評(píng)論