1. 程式人生 > 其它 >windows上的linux子系統(WSL)

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需要系統支援,安裝之前最好將系統更新到最新版。

  1. 開啟linux子系統(WSL),使用管理員許可權開啟PowerShell,執行:
    Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
    
    • 1
  2. 重啟
  3. 安裝發行版,這裡使用Ubuntu。開啟應用商店,然後下載
  4. 按win鍵,找到ubuntu,點選執行,它會進行初始化。然後提示輸入普通使用者名稱和密碼,這是預設登入使用者。ubuntu中預設root使用者不能登入。
  5. 進入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.exebash.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

參考

推薦閱讀

Setting Up WSL with Graphics and Audio:對WSL理解的很好