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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM