原文:
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理解的很好