windows上的linux子系統(WSL)
原文:
https://www.pianshen.com/article/5064324329/
目錄
一 介紹
Windows Subsystem for Linux(WSL)是一個用於在本地執行linux二進位制可執行檔案(ELF格式)的相容層。與虛擬機器相比,wsl沒有虛擬硬體的過程,而是直接在windows上虛擬一個linux核心,模擬linux系統呼叫,以執行linux執行檔案。因此效率要比虛擬機器高,但是它使用的是自己實現的init程序而不是發行版的init程序,並且幾乎沒有實現任何系統服務,因此只適用於軟體的開發,而不是作為桌面環境或生產性的伺服器。
- 並且wsl的目的也是如此,可以簡單的將它理解為可以執行linux可執行檔案的、類似於powershell的shell,具有互操作性(在linux中執行windows命令,在windows中執行linux命令)。
- 在我看來,失去了發行版的init後,我們主要用到的是發行版的包管理器。
二 原理
2.1 wsl元件
wsl實現的元件涉及到了使用者和核心模式。在Windows NT核心模式中,LXCore,LXSS這兩個驅動提供了linux核心呼叫的實現,即將linux呼叫轉化為對應的windows NT核心呼叫;還提供了兩種檔案系統:VolFs(掛載在/
目錄上,支援linux檔案系統所有特性)和DriverFs(掛載在/mnt/c
/mnt/d
等等windows分割槽,主要為了支援系統間的互操作性);驅動還會模擬核心的行為,對linux程序進行排程。
在使用者模式下,windows提供了一種特殊的程序型別:Pico程序,來支援linux程序的執行。windows會 “放鬆” 對該型別程序的控制,主要交由linux虛擬核心呼叫和管理,即隔離性(因此需要系統的支援,低版本的系統不能使用wls的功能)。pico會將ELF二進位制可執行檔案裝入到自己的地址空間,然後執行在linux虛擬核心提供的相容層上。一個pico對應一個linux程序,並且pico程序也是windows的一種特殊程序,因此你可以在工作管理員上看到linux程序。
無論exe還是elf格式的二進位制檔案,原理上都可以在同架構的cpu上執行,只是結構不同作業系統不能解析罷了。而Pico能夠解析ELF格式的二進位制檔案,只需要linux虛擬核心能夠提供正確的系統呼叫,就能夠執行大部分linux命令。
LXSS管理服務主要用於協調windows和linux程序之間的關係,和給於Bash.exe(並不是shell,只是我們訪問wsl的入口)呼叫linux命令的介面。所有的執行的linux程序都會被加入到叫Linux例項(應該有LXSS記錄的)中,只有第一次請求訪問linux程序時才會建立Linux例項,才會建立init程序;當window關機時,會自動關閉linux例項,即關閉linux所有程序。
也就是wsl不會隨windows系統自啟而自啟,同時沒有使用發行版的init程序,導致wsl中沒有服務的存在。
2.2 wsl執行過程
linux中正常的啟動過程是載入程式載入核心,核心初始化後載入init程序,init程序開啟各項服務,將系統配置到使用者可用的狀態,如多使用者登入、圖形介面登入等。此時linux自啟完成,接著等待使用者的登入,並且登入方式多種,如控制檯登入、ssh登入、虛擬終端登入等等。
而wsl並不是一個真正的系統,而只是windows的一部分,可以執行linux二進位制可執行檔案。核心也是虛擬出來的,但是具有一定隔離性,如linux程序由虛擬核心排程,也具有互操作性。
因此當windows自啟結束並載入了上述LxCore、LXSS兩個驅動後,已經能夠提供linux程序系統呼叫了。此時wsl的init程序(windows自己實現的)並不會立刻執行,即暫時沒有一個linux例項。只有當第一次訪問wsl時(執行Bash.exe),才會建立linux例項,執行init服務程序(圖中左邊)。這個init程序會伴隨linux例項,直到例項結束。然後再建立bash shell 和 另一個init 程序(圖中右邊),在本次會話結束時(關閉Bash.exe視窗)這兩個程序結束。之後再通過Bash.exe連線wsl,都只會建立bash和右邊的init程序。
目前官網聲稱,後臺程序能夠在會話結束後仍然執行(一般linux中會關閉),經測試,沒有標準輸出的後臺程序才能夠存活。還是建議使用nohup。
至於詳細過程,請看上圖。
2.3 檔案系統
上述講到了,wsl只有兩種windows設計的檔案系統:VolFs和DriverFs。其中VolFs檔案系統主要是為了支援linux檔案系統的全部特性,如linux的檔案許可權、符號連結、不同於windows的檔名、檔名大小寫敏感等等。
而DriveFs主要是為了掛載windows的分割槽,並且實現互操作性而存在。實際上就是NTFS檔案系統的包裝,能夠讓NTFS在linux中使用,即使也提供了大部分linux檔案系統特性,但是限制很多,如:
- 檔案目錄許可權全為777,實際上就算是root使用者,在windows分割槽中也只有開啟Base.exe命令擁有者的許可權。說明普通使用者使用root許可權也不能修改c盤中大部分檔案。
- 最好不要在windows下建立檔名只有大小寫不同的檔案,儘管NTFS支援了。
- 支援linux符號連結,為windows可執行檔案建立符號連結時,注意新增字尾
.exe
。不要與windows的快捷方式混淆,它們目的一致,但結構不一致,不能在linux中使用。
2.4 禁忌
不要在任何情況下,使用windows工具訪問、建立、修改linux發行版的檔案。再安裝了WSL後,可以在C盤中找到它的根目錄,含有linux標準目錄結構,但千萬不要修改它。
linux和windows檔案系統的資料存放形式是不同的,為了支援linux檔案系統,wsl實現了VolFs。VolFs本質上還是使用了windows的NTFS的檔案格式(因此你能夠找到它),只是將Linux檔案的元資料放入NTFS檔案的擴充套件屬性中。因此linux檔案系統可以正常執行,而在windows看來,它的檔案不存在或者空;而使用windows修改它的檔案時,不會保留它的擴充套件屬性,導致在linux中看起來不正常。
因此,如果想要實現兩個系統的互操作,應該將工作目錄置於windows分割槽內,linux資料夾外,在windows的資料夾中操作。
參考:Do not change Linux files using Windows apps and tools
三 使用
3.1 安裝
wsl需要系統支援,安裝之前最好將系統更新到最新版。
- 開啟linux子系統(WSL),使用管理員許可權開啟PowerShell,執行:
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
- 1
- 重啟
- 安裝發行版,這裡使用Ubuntu。開啟應用商店,然後下載
- 按win鍵,找到ubuntu,點選執行,它會進行初始化。然後提示輸入普通使用者名稱和密碼,這是預設登入使用者。ubuntu中預設root使用者不能登入。
- 進入Ubuntu後,更新發行版
sudo apt update && sudo apt upgrade
- 1
3.2 使用者賬戶和許可權
wsl與windows有一定隔離性,wsl的使用者對linux檔案、程序的許可權與linux一致。但對於/mnt/c
下windows的最高訪問許可權取決於執行Base.exe(即使使用Ubuntu.exe,最終一致)擁有者的許可權。即普通windows使用者以root身份執行wsl也不能隨意刪除、訪問、修改c盤檔案。
3.3 wsl管理
有三種執行wsl的方法:
- 發行版提供的app,如
ubuntu
:進入到linux家目錄 wsl.exe
或bash.exe
:linux置當前目錄為工作目錄wsl [command]
或bash -c [command]
:執行linux命令,當前目錄作為工作目錄
wsl中可以存在多個發行版,通過wslconfig管理,wslconfig /?
可以檢視具體功能:
wslconfig /list [/all]
:列出已註冊的發行版,/all
額外列出正在安裝和解除安裝的發行版。wslconfig /setdefault
:設定執行wsl時的預設發行版wslconfig /unregister
:解除安裝發行版
具體的發行版提供的入口,如ubuntu,可以設定預設使用者,詳細參考ubuntu /?
3.3 互操作
上面多次提到互操作性,也就是可以在windows中執行linux程序,在linux中執行windows程序,並且支援兩個不同程序間的輸入輸出重定向。
在windows中使用wsl [command]
執行linux命令,需要注意:
- linux命令使用當前目錄作為工作目錄
- 對於windows檔案,擁有執行WSL的windows使用者許可權;對於linux檔案擁有登入使用者許可權
- 檔案路徑使用linux格式
例子:
C:\temp> wsl ls -la
<- contents of C:\temp ->
C:\temp> wsl sudo apt-get update
[sudo] password for username:
Hit:1 https://archive.ubuntu.com/ubuntu xenial InRelease
Get:2 https://security.ubuntu.com/ubuntu xenial-security InRelease [94.5 kB]
C:\temp> wsl ls -la | findstr "foo"
-rwxrwxrwx 1 root root 14 Sep 27 14:26 foo.bat
C:\temp> dir | wsl grep foo
09/27/2016 02:26 PM 14 foo.bat
C:\temp> wsl ls -la > out.txt
C:\temp> wsl ls -la /proc/cpuinfo
-r--r--r-- 1 root root 0 Sep 28 11:28 /proc/cpuinfo
C:\temp> wsl ls -la "/mnt/c/Program Files"
<- contents of C:\Program Files ->
在linux中執行windows命令,使用[binary name].exe
(字尾不要省略),linux可以直接訪問windows命令的原因在於linux共享了windows的PATH
環境變數(我猜是linux中唯一的守護程序init做的)。需要注意:
- 一般windows命令的工作目錄為當前linux的工作目錄。如果linux工作目錄位於linux檔案系統內,則windows的工作目錄會改為Base.exe的工作目錄(原因見2.4小節)。
- 擁有與執行WSL擁有者一致的許可權
- 需要注意路徑,看下面的例子
例子:
$ notepad.exe
$ ipconfig.exe | grep IPv4 | cut -d: -f2
172.21.240.1
10.159.21.24
$ ls -la | findstr.exe foo.txt
$ cmd.exe /c dir
<- contents of C:\ ->
$#cmd 原生命名需要通過cmd.exe執行
$ cmd.exe /C dir
<- contents of C:\ ->
$ PING.EXE www.microsoft.com
Pinging e1863.dspb.akamaiedge.net [2600:1409:a:5a2::747] with 32 bytes of data:
Reply from 2600:1409:a:5a2::747: time=2ms
$ notepad.exe "C:\temp\foo.txt"
$ notepad.exe C:\\temp\\foo.txt
參考
- 微軟官方文件:介紹了安裝、使用
- Learn About Windows Console & Windows Subsystem For Linux (WSL):介紹了wsl原理
- wsl wiki
- Do not change Linux files using Windows apps and tools:來自Rich的警告
- wsl官方部落格集合
推薦閱讀
Setting Up WSL with Graphics and Audio:對WSL理解的很好