全文共6894字,預計學習時長18分鐘
圖源:unsplash
在十多年的開發生涯中,筆者熱衷于使用shell。命令永遠不變,筆者可以創建可靠、快捷的自定義快捷方式,但默認值欠佳。閱讀本文將帶你了解如何在系統上獲得很棒的shell +終端。
術語
shell用于執行命令。終端(terminal)是運行shell的包裝器。在終端上可以設置字體、字體大小、配色方案以及支持多個選項卡。終端仿真器的示例包括GNOME終端、KDE的Konsole,Terminator和XTerm。對于Linux系統,筆者建議保留默認值。Windows適用Windows Terminal;Mac適用iTerm2。
(Linux上的四個終端仿真器(Gnome Terminal、Konsole、XTerm、Terminator)。XTerm不直接支持標簽。其他的打開了2個選項卡。它們都運行Bash shell。| 圖源:MartinThoma)
系統的Shell包括ZSH、Bash、fish。Windows系統典型的shell是PowerShell。可以通過執行echo $ 0來查看正在運行的shell。Linux系統使用更多的是Bash shell。
(在Gnome終端中的三個Linux shell(ZSH、Bash、fish),ZSH shell經過了大量更改;Bash shell和fish shell顯示默認值。可見,fish shell具有其他兩個shell缺少的內聯自動提示功能。| 圖源:Martin Thoma。)
每個shell都有提示符(prompt)。提示符是光標之前寫入的內容。它表示可以輸入指令并提供有用的背景信息。在上面的示例中,提示符包含用戶名moose,當前計算機pc08 ,當前工作目錄 ~/GitHub/MartinThoma/flake8-simplify,活躍git分支feature/19以及進行了±修改的事實。
字體
無論選擇哪個,字體都很重要。你可能想要一個等寬字體,相信我一定要安裝powerline字體。powerline字體能使shell使用像圖像的字符。它可以使提示符效果更好。筆者比較喜歡UbuntuMono和DroidSans Mono:
上面一行是Ubuntu Mono,下面是Droid Sans Mono。二者都不錯,Ubuntu Mono略勝一籌。| 圖源:Martin Thoma
也有Fira Code、Jetbrains Mono 這樣的“編程字體”。筆者不喜歡它們,因為很難識別所寫內容。
Windows終端
首先確保已安裝Windows終端。啟動終端并找到設置。它是這個指下的“小箭頭”:
點擊“Settings”。| 圖源:MartinThoma
可以選擇JSON文件隨自己喜好而更改。如下:
// This file was initially generated byWindows Terminal 1.2.2381.0
// It should still be usable in newerversions, but newer versions might have additional
// settings, help text, or changes thatyou will not see unless you clear this file
// and let us generate a new one foryou.
// To view thedefault settings, hold "alt" while clicking onthe "Settings" button.
// For documentation on thesesettings, see: https://aka.ms/terminal-documentation
{
"$schema": "https://aka.ms/terminal-profiles-schema",
"defaultProfile": "{2c4de342-38b7-51cf-b940-2309a097f518}",
"initialCols": 120,
"initialRows": 30,
//Youcanaddmoreglobalapplicationsettingshere.
//Tolearnmoreaboutglobalsettings,visithttps://aka.ms/terminal-global-settings
//Ifenabled, selectionsareautomaticallycopiedtoyourclipboard.
"copyOnSelect": false,
//Ifenabled,formatteddataisalsocopiedtoyourclipboard
"copyFormatting": false,
//Aprofilespecifiesacommandtoexecutepairedwithinformationabouthowitshouldlookandfeel.
//Eachoneofthemwillappearinthe'NewTab'dropdown,
// andcanbeinvokedfromthecommandlinewith`wt.exe-pxxx`
//Tolearnmoreaboutprofiles,visithttps://aka.ms/terminal-profile-settings
"profiles":
{
"defaults":
{
//Putsettingsherethatyouwanttoapplytoallprofiles.
},
"list":
[
{
//Makechangesheretothepowershell.exeprofile.
"guid": "{61c54bbd-c2c6-5271-96e7-009a87ff44bf}",
"name": "WindowsPowerShell",
"commandline": "powershell.exe",
"hidden": false,
"fontFace": "DejaVuSans Mono for Powerline"
},
{
//Makechangesheretothecmd.exeprofile.
"guid": "{0caa0dad-35be-5f56-a8ff-afceeeaa6101}",
"name": "CommandPrompt",
"commandline": "cmd.exe",
"hidden": false
},
{
"guid": "{2c4de342-38b7-51cf-b940-2309a097f518}",
"hidden": false,
"name": "Ubuntu",
"source": "Windows.Terminal.Wsl",
"fontFace": "DejaVuSans Mono for Powerline",
"colorScheme": "Solarized Dark",
},
{
"guid": "{b453ae62-4e3d-5e58-b989-0a998ec441b8}",
"hidden": false,
"name": "AzureCloud Shell",
"source": "Windows.Terminal.Azure"
}
]
},
//Addcustomcolorschemestothisarray.
//Tolearnmoreaboutcolorschemes,visithttps://aka.ms/terminal-color-schemes
"schemes": [
{
"background": "#073642",
"black": "#073642",
"blue": "#268BD2",
"brightBlack": "#002B36",
"brightBlue": "#839496",
"brightCyan": "#93A1A1",
"brightGreen": "#586E75",
"brightPurple": "#6C71C4",
"brightRed": "#CB4B16",
"brightWhite": "#FDF6E3",
"brightYellow": "#657B83",
"cyan": "#2AA198",
"foreground": "#FDF6E3",
"green": "#859900",
"name": "Solarized Dark",
"purple": "#D33682",
"red": "#D30102",
"white": "#EEE8D5",
"yellow": "#B58900"
},
{
"background": "#FDF6E3",
"black": "#073642",
"blue": "#268BD2",
"brightBlack": "#002B36",
"brightBlue": "#839496",
"brightCyan": "#93A1A1",
"brightGreen": "#586E75",
"brightPurple": "#6C71C4",
"brightRed": "#CB4B16",
"brightWhite": "#FDF6E3",
"brightYellow": "#657B83",
"cyan": "#2AA198",
"foreground": "#073642",
"green": "#859900",
"name": "Solarized Light",
"purple": "#D33682",
"red": "#D30102",
"white": "#EEE8D5",
"yellow": "#B58900"
},
],
//Addcustomkeybindingstothisarray.
//Tounbindakeycombinationfromyourdefaults.json,setthecommandto"unbound".
//Tolearnmoreaboutkeybindings,visithttps://aka.ms/terminal-keybindings
"keybindings":
[
//CopyandpasteareboundtoCtrl+Shift+CandCtrl+Shift+Vinyourdefaults.json.
//ThesetwolinesadditionallybindthemtoCtrl+CandCtrl+V.
//Tolearnmoreaboutselection, visithttps://aka.ms/terminal-selection
{ "command": {"action": "copy", "singleLine": false }, "keys": "ctrl+c" },
{ "command": "paste", "keys": "ctrl+v" },
//PressCtrl+Shift+Ftoopenthesearchbox
{ "command": "find", "keys": "ctrl+shift+f" },
//PressAlt+Shift+Dtoopenanewpane.
//-"split":"auto"makesthispaneopeninthedirectionthatprovidesthemostsurfacearea.
//-"splitMode":"duplicate"makesthenewpaneusethefocusedpane'sprofile.
//Tolearnmoreaboutpanes, visithttps://aka.ms/terminal-panes
{ "command": { "action": "splitPane", "split": "auto", "splitMode": "duplicate" },
"keys": "alt+shift+d" },
{"command": "closeTab", "keys": "ctrl+w"},
{"command": "newTab", "keys": "ctrl+t"}
]
}
下載并安裝所有4種“ DejaVu Sans Mono Powerline”字體。在已知的所有系統上,字體安裝都是一個流程:雙擊字體,然后跳出一個有“安裝”按鈕的窗口。
Linux和Windows終端:Aminal
Aminal是用Go語言編寫的終端仿真器。可用于Linux、Windows和Mac。它允許通過配置文件完成顏色、鍵盤快捷鍵等配置。首先需要在系統中安裝并配置Go語言。Ubuntu的示例如下:
$ sudo apt-get install golang libgl1-mesa-dev xorg-dev
$ export GOPATH="$HOME/go"
$ export GOBIN=$(go env GOPATH)/bin
接著就可以安裝并運行aminal了:
$ go get -u github.com/liamg/aminal
$ aminal
Linux系統:Gnome終端
可以通過編輯文件來自定義Gnome終端。這里筆者用12號字設置了Ubuntu Mono衍生的powerline常規字體。
圖源:Martin Thoma
命令是為了zsh而設置,因為這是筆者最喜歡的shell。
圖源:Martin Thoma
顏色設置為solarized dark(從左到右、從上到下)
· 背景: #2e3436 / #555753
· 深紅: #cc0000 / 淺紅: ef2929
· 深綠: #4e9a06 / 淺綠: #8ae234
· 深黃: #c4a000 / 淺黃: #fce94f
· 深藍: #3465a4 / 淺藍: #729fcf
· 深紫: #75507b / 淺紫: #ad7fa8
· 深藍綠: #06989a / 淺藍綠: #34e2e2
· 深灰: #d3d7cf /淺灰: #eeeeec
Linux系統:fish shell
安裝fish shell:
sudo apt-get install fish
更改終端仿真器的默認shell為fish。在Gnome終端叫做“自定義命令”
接著安裝“Oh My Fish”
curl -L https://get.oh-my.fish | fish
然后將主題設置為agnoster:
omf install agnoster
omf theme agnoster
別名
要使終端表現出色,核心部分的命令就要簡短。因此為命令創建一個別名,即簡短版的原命令。最常見是將目錄更改為上一級。假如是在 /home/user/foo/bar中,則要轉到 /home/user/foo。大多數shell都必須輸入cd .. 。我喜歡將其縮寫為 ..。所以別名就是alias ..='cd ..' 。
語法可能不同,具體取決于shell。對于Bash、ZSH和fish:
alias short='long'
在bash中要插入到 ~/.bashrc,ZSH中則是 ~/.zshrc,fish中也不相同。一些別名如下:
# Shorten things
alias ..='cd ..'
alias ...='cd ../../'
alias ll='ls -alF'
alias la='ls -A'
alias l='ls -CF'
alias c='clear'# If your terminal supports colors, use them!
alias ls='ls --color=auto'
alias grep='grep --color=auto'
alias fgrep='fgrep --color=auto'
alias egrep='egrep --color=auto'
alias diff='colordiff'# Works only if you have notify-send
alias alert='notify-send --urgency=low -i "$([ $?=0 ] && echoterminal || echo error)" "$(history|tail -n1|sed -e'\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'
總結一下:
· 使用不錯的終端仿真器。建議Linux系統使用Gnome終端,Mac系統使用iTerm 2,Windows系統使用Windows終端。
· 安裝比較好的powerline字體,比如Ubuntu Mono Powerline。
· 在終端仿真器中按照喜好調整字體、字號以及顏色。
· 安裝一個好的shell。建議Linux系統使用fish shell,Windows系統使用PowerShell。
· 按需調整shell的提示符。筆者個人喜歡agnoster主題。
留言點贊關注
我們一起分享AI學習與發展的干貨
如轉載,請后臺留言,遵守轉載規范
如果我們將兩個4G內存插入內存插槽,得到的內存地址空間是0到8G嗎?是不是0到4G是第一根內存,4到8G是第二根內存呢?實際情況相差甚遠,內存在物理地址空間的映射是分散的。一部分原因是4G以下有Memory map IO(mmio)空間和PCIe的配置空間,另一個原因是Interleaving會打撒內存地址到各個Channel、DIMM甚至是Rank和bank上。今天我們就一起來了解一下x86系統的地址空間分布。
一個典型的物理地址空間是這樣的:
其中只有灰色部分是真正的內存,其余都是MMIO。而內存被分為High DRAM和Low DRAM,如圖:
為什么要把內存強行分割成兩塊呢?因為歷史的包袱。最早內存都很小,32位的地址(4G)空間看起來永遠也用不完,低地址被分配給內存用,高地址就自然而然被分配用來給Memory map IO。既然已經分給它們了,為了兼容以前的驅動,這一塊就被固定下來。再有內存就只能從4G以上分配了。
Low MMIO結構如下圖:
其中有幾塊要特別說明一下:
1.Boot Vector的空間是BIOS內容映射的地址,它的大小是可以調節的,為了滿足不同大小的BIOS。
2.Local APIC是APIC中斷模式各個內核local APIC寄存器的映射地址。
3.PCI ECAM也有叫做PCIBAR,是PCIe配置地址空間的映射地址。它的起始地址可調,臺式機BIOS一般會把它設置得很高,這樣4G以下內存會比較大,方便32位Windows使用。舉個例子,如果我們把PCIe BAR(BEGREG)設為0x80000000,那么盡管插了8G DIMM,4G以下也不會超過2G的內存可以使用,而2到8G的真實內存都被映射到在4G地址空間以上了,而這些是32位Windows使用不了的。所以有的主板運行32位操作系統發現可用內存小了一大塊就是這個原因。它的大小可以修改,一般可以設為64MB和128MB。
High MMIO被BIOS保留作為64位mmio分配之用,例如PCIe的64位BAR等。
4G以下內存最高地址叫做BMBOUND,也有叫做Top of Low Usable DRAM (TOLUD) 。BIOS也并不是把這些都報告給操作系統,而是要在里面劃分出一部分給核顯、ME和SMM等功能:
紅框中是在low DRAM被“偷”的部分
4G以上的內存最高端叫做Top of Up Usable DRAM (TOUUD) ,再上面就是High MMIO了。
1MB以下比較特殊,里面全部都是已經被淘汰的傳統BIOS和DOS關心的內容,我們叫它DOS Space或者Legacy Region:
在那里,我們習慣用傳統的實模式地址來劃分它們的具體內容:
1.0~640KB,傳統DOS空間。
2.A段和B段,傳統SMM空間。VGA的MMIO也被映射到這里,可以通過寄存器切換。
3.C段和D段,legacy opROM映射空間和EBDA空間。
4.E段和F段,BIOS空間的Lower和Upper映射地址。BIOS的rom內容也會被映射到這里,方便Legacy BIOS實模式跳轉到保護模式。
從前面可以看出內存在地址空間上被拆分成兩塊:Low DRAM和High DRAM。那么在每塊地址空間上分配連續嗎?現代內存系統在引入多通道后,為了規避數據的局部性(這也是Cache為什么起作用的原因)對多通道性能的影響,BIOS基本缺省全部開啟了Interleaving,過去美好的DIMM 0和DIMM 1挨個連續分配的日子一去不復返了。
什么是Interleaving?簡單來說,就是讓內存交錯起來,如下面的動圖:
來自wikipedia, 參考資料1
這是一個bank層級的模4的interleaving。在桌面電腦上,常見的還有Channel級的、DIMM級的和Rank級的。
服務器上Interleaving更是不可或缺,它的粒度更細,可以達到數十bytes層級的interleave,它和內存的其他特性,如類似磁盤陣列RAID的內存spare, mirror特性,構成了復雜異常的內存映射系統。在BIOS里面,臺式機/筆記本內存映射相對簡單,只有一個大表和數十個寄存器;而在服務器BIOS中,有數個相互關聯的大表和寄存器陣列來解碼(decode)內存的請求,代碼的硬件邏輯也是相當復雜。關于它,我會有一篇專欄文章討論地址譯碼和地址反向解碼,詳細內容那里再說,這里只需要知道,物理內存分布在各個DIMM上就夠了。
BIOS實際上一手導演的內存的分配,它當然可以從任何物理地址反推回內存的單元地址。我們可以用下面一組數據來唯一確定某個內存單元:
Channel #;DIMM #; Rank #;Bank #;Row #;Column #
在內存分配表缺失的情況下,BIOS甚至可以通過它填過的寄存器重建這個映射表。但實際上BIOS并不希望一般用戶知道這些信息,因為有安全性問題。
暴露內存信息容易招來內存側信道攻擊(Side Channel),比較有名的有Row hammer攻擊。簡單的來說它是通過反復寫某個內存單元,借助內存的特性,希望影響相鄰Row/Column的內容。詳細內容可以參考這里:
內存不刷新會怎樣?有趣的內存物理攻擊和旁路攻擊
有些情況確實需要知道這些信息,就是內存出錯的時候。和大家想象的不同,內存是會出錯的。尤其云服務器中內存的出錯是十分頻繁的。出錯起來也千奇百怪,開始可能是偶爾的隨機錯誤,經過ECC等校正后,就再也不會復現;而有時是某個Bit總是出錯,進而慢慢的整個row、column或者相鄰的cell開始出錯,從可以糾正的錯誤變成不可修正的錯誤,導致服務器必須停機。這時候就必須知道哪個內存壞了,進而換掉它。BIOS的報錯是通過WHEA:
報告給操作系統,但這個信息里面只有物理地址,如何才能知道是哪個內存單元壞了呢?在Linux上面可以通過edca(參考資料4),有編程經驗的同學可以通過edca的程序接口(參考資料3),可以得到更加豐富的信息。
對內存有特殊需求的朋友,如果希望內存連續,可以在BIOS里面關閉所有的Interleaving來達成這個目標:
注意是所有的。之后可以通過SMBIOS來看到內存分布信息(dmidecode)。
BIOS作為內存的大管家,也負責內存的分配和映射memory map。它會把這些信息通過E820, GetMemoryMap函數和SMBIOS傳遞給操作系統。操作系統在此基礎上再建立頁表,產生虛擬地址。