WSL - Windows Subsystem for Linux
- WSL Installation Guide for Windows 10
- WSL VSCode
- VSCode Remote Development
- VSCode Remote Development
- WSL VcXsrv + Linux XServer 图形界面支持
- linux GTK、KDE、Gnome、XWindows 图形界面
在 Windows 1607 x64 位版本后提供了 WSL - Windows Subsystem for Linux 功能,即在 Windows 运行的 Linux 开发环境,能原生运行 Linux ELF 格式可执行文件。
WSL 目的是运行 Bash 和 Linux 核心命令行工具,并不包含 GUI 组件,所以 Gnome, KDE 等子系统不能使用。对于不需要图形的开发,WSL 体验甚至超过了在纯 Linux 下开发,因为节省了 GUI 的消耗,使得系统意想不到的稳定。而且没有虚拟机那恶心的地址桥接、转换,Windows 的网络通信地址和端口直接可以在 WSL 上使用。
尽管 WSL 不支持完整的 GUI 桌面环境,但是,它可以正常工作,使用 XServer 等远程桌面就可以实现。
使用 Visual Studio Code 开发非常方便,只需要在主机上安装 VSCode,再安装 Remote Development extension pack 插件包,含有 Remote - WSL 插件,它可以处理映射到 Linux 系统的 /mnt/c
目录,使用 remote-wsl 菜单命令,或打开终端输入 wsl 即可以进行远程开发。
Remote Development extension pack 插件包:
- Remote - SSH 安全 Shell 可以打开远程系统的文件,包括虚拟机。
- Remote - Containers 提供 sandboxed 工具链和基于窗口的应用。
- Remote - WSL 使用集成于 Windows 的 Linux 子系统功能。
使用 Sublime Text 也可以结合 wsl 命令使用。
首先,打开 更新和安全 -> 针对开发人员 -> 开发人员模式,然后在 PowerShell 执行命令安装 WSL:
dism /online /enable-feature /featurename:microsoft-windows-subsystem-linux
打开 Microsoft store 选择 Linxu 系统进行安装。
wsl -ls -v
wsl --list --verbose
安装 GCC 开发工具:
wsl
sudo apt install gcc
sudo apt install g++
使用 cat 命令生成代码,再编译并运行示例程序:
cat > demo.c << END
#include <stdio.h>
int main()
{
printf ("%s\n", "hello");
}
END
gcc demo.c -o demo && ./demo
cat >>
表示附加内容到文件,cat >
表示覆盖文件内容,cat file
表示打印文件内容。<< END
表示设置一个结束标记,再次输入 END 就会停止 cat 命令。
使用 Sublime:
wsl gcc ../src/demo.c -o pr && wsl ./pr
升级到 WSL 2:
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
wsl --set-default-version 2
wsl --set-version <distribution name> <versionNumber>
下载文件较大,需要网络快速。安装成功后,打开 PowerShell,键入 bash 并回车,即可进入 Linux 子系统。使用 lsb_release -a 命令查看 Linux 子系统版本,目前已经支持的子系统如下:
- Ubuntu 16.04 LTS
- Ubuntu 18.04 LTS
- Ubuntu 20.04 LTS
- openSUSE Leap 15.1
- SUSE Linux Enterprise Server 12 SP5
- SUSE Linux Enterprise Server 15 SP1
- Kali Linux
- Debian GNU/Linux
- Fedora Remix for WSL
- Pengwin
- Pengwin Enterprise
- Alpine WSL
在 Windows 10 Build 19041,版本号 2004 或更高系统中,可以使用 WSL 2,可以通过 winver 命令查看当前系统版本。
WSL 版本功能对比:
Feature | WSL 1 | WSL 2 |
---|---|---|
集成 Windows & Linux | ✅ | ✅ |
Fast boot times | ✅ | ✅ |
Small resource foot print | ✅ | ✅ |
Managed VM | ❌ | ✅ |
Full Linux Kernel | ❌ | ✅ |
Full system call compatibility | ❌ | ✅ |
Runs with current versions of VMWare and VirtualBox | ✅ | ❌ |
Performance across OS file systems | ✅ | ❌ |
Linux 子系统的管理:
wsl -l --all
wsl --list --running
wsl --terminate Ubuntu
wsl --export <Linux_distrib> <export_file>
wsl --export Ubuntu C:\WSL\Ubuntu.tar
wsl --import <system_name> <save_path> <import_path>
wsl --import MyUbuntu C:\WSL\Ubuntu C:\WSL\Ubuntu.tar
wsl --distribution MyUbuntu
wsl --unregister MyUbuntu
DrvFs 是 WSL 提供的文件驱动器映射系统,通过它可以装饰各个磁盘分区映射到 /mnt/c
, /mnt/d
等目录上。
mount -l
sudo umount /mnt/c
sudo mount -t drvfs C: /mnt/c -o metadata
启动 WSL,Windows 的硬盘会自动 mount 到 Linux 系统下,但是早期版本所有 Windows 文件的 owner 和 group 都会设置为 root,读写权限则是从 Windows 系统下继承过来。经常可以看到一片绿油油的 777 权限的文件和文件夹列表,这显然和 Linux 系统中的最佳实践不符的,而且对这些文件使用 chmod 或者 chown 是不起作用的,简直没法忍。
或者使用添加 umask 和 fmask 等参数装载:
sudo mount -t drvfs C: /mnt/c -o metadata,uid=1000,gid=1000,umask=22,fmask=111
这些标记说明,umask=22 和 fmask=111 表示文件和目录有相应的 read/write/execute 权限:
- uid: the user ID used for the owner of all files
- gid: the group ID used for the owner of all files
- umask: an octal mask of permissions to exclude for all files and directories.
- fmask: an octal mask of permissions to exclude for all regular files.
- dmask: an octal mask of permissions to exclude for all directories.
但是每次使用时手动 mount 也太麻烦了,这时正好用上另一个新特性 Automatically Configuring WSL。把下面 automount 的选项添加到 wsl 配置文件中就可以了。
sudo cat > /etc/wsl.conf << END
[automount]
enabled = true
root = /mnt/
options = "metadata,umask=22,fmask=11"
mountFsTab = false
END
如果 sudo cat 执行不了,可以使用 sudo vim 进行编辑。
现在重启 WSL 的 console, Windows 硬盘上的文件和文件夹都拥有正常权限了。但是,用 mkdir 命令创建一个空文件夹,就会发现新的文件夹还是 777 权限。这可能是 wsl 的一个bug (Issue 1801, Issue 352),console 默认的 umask 值仍然是 0000。work-around 的方法是在 .profile、.bashrc、.zshrc 或者其他 shell 配置文件中重新设置一下 umask。
#Fix mkdir command has wrong permissions
if grep -q Microsoft /proc/version; then
if [ "$(umask)" == '0000' ]; then
umask 0022
fi
fi
paltform relialy preprocessor
平台依赖预处理示例:
#include <iostream>
#ifdef _WIN32
//define something for Windows (32-bit and 64-bit, this part is common)
#ifdef _WIN64
#define msg "for Windows (64-bit only)"
#else
#define msg "for Windows (32-bit only)"
#endif
#elif __APPLE__
#include "TargetConditionals.h"
#if TARGET_IPHONE_SIMULATOR
#define msg "for iOS Simulator"
#elif TARGET_OS_IPHONE
#define msg "for iOS device"
#elif TARGET_OS_MAC
#define msg "for Other kinds of Mac OS"
#else
#define msg "= "Unknown Apple platform""
#endif
#elif __ANDROID__
#define msg "for android"
#elif __linux__
#define msg "for linux"
#elif __unix__ // all unices not caught above
#define msg "for Unix"
#elif defined(_POSIX_VERSION)
#define msg "for POSIX"
#else
#define msg "Unknown compiler"
#endif
int main()
{
std::cout << msg << std::endl;
}
可以参考 Qt 的 qglobal.h 头文件。
GUI - X Windows 图形协议
- X Window 系统的窗口显示原理
- The Xlib Manual
- Dear imgui
- Dear ImGUI 在线演示
- Nuklear UI
- Nuklear UI Doc
- VcXsrv Windows X Server
- WSL Terminal
GUI 程序是指某一类带有图形界面的程序,和控制台程序的区别就是图形处理的差别。在传统 DOS 系统中,可以通过硬件中断的方式设置显卡工作在图形模式下,程序通过写显卡内存数据实现图形显示。
而在现代的操作系统中,通过新的 API 实现,或者通过现成的图形库实现 GUI 程序。如果是 Windows 系统,可以选择 MFC 或 ALT,或更新的 .Net 框架。
在 Linux 下选择也很多,但 X Windows 是通用性最好的一下图形界面协议。
此外,还有大量可跨平台的 GUI 图形库,如基于 OpenGL 的 IMGUI、Nuklear UI 等,还有 Qt、wxWidgets 等。
用 C++ 从零编写 GUI 这种想法是每个好奇者都会有的想法,但是要从头实现一款自己的界面库,你需要了解界面库是如何运作的,消息机制、绘图机制,字体处理,甚至多语言处理。另外一个层面上讲,程序终归是要依赖系统运行,底层部分肯定是要基于系统 API 之上。
即使作一层抽象,像 IMGUI 这类直白图形库,也是需要处理与系统的关系的。Immediate Mode GUI 是一种简化的图形架构,这种类型的更多的适用于显示区域实时刷新的程序里面,应用于游戏界面的实现上,如著名的游戏引擎 Unity 就是用 IMGUI 模式写的 GUI。
IMGUI 这种实现模式的优势在于他在实现和实用上都会比传统的 Retained Mode GUI,例如 Qt、 MFC 等,要简单不少,不用去管理图形组件的生存周期。IMGUI 模式没有图形控件对象,不保存任何状态,不用单独的去实现 UI 和程序间数据的交换,甚至都不需要单独为事件写回调函数。每个控件都通过绘图函数实现,直接在程序的 Draw() 函数里要哪个控件就调用哪个函数绘图。也因此,在 IMGUI 中实现带状态的图形会显得麻烦,比如动画白控件。
基于系统 API 调用实现 GUI 图形界面,在 Windows 系统中 GUI 编程采用的是消息循环机制,通过 API 向系统注册窗口类,并设置好消息处理的回调函数,处理好用户与系统 GUI 交互过程中产生的事件,这就是一个基本程序流程。而 MFC 则是使用各种类帮你组织好了系统 API,这样开始 GUI 程序就会比直接使用 API 更方便。MFC 作为最经典的 Windows GUI 框架,现在已经不更新了,但是其中的框架思想是值得学习的,台湾的侯捷老师编写了一本《深入浅出 MFC》可以参考,此书是讲原理更关心 MFC 的框架设计。如果要快速上手则合适参考李久进的《MFC 深入浅出》 或《Windows 程序设计》。
而 X Window 系统是一个基于网络的图形界面系统,说它是图形协议自然是因为它的架构特别。它于 1984 年在麻省理工学院开发,有将近 20 年的应用历史,X Window 系统广泛的应用于桌面 Linux(如 Fedora、Debian、Ubuntu 等),嵌入式 Linux(如 Nokia 的 Maemo、Intel 的 Moblin 等)。随着 Nokia 和 Intel 高调的将 Maemo 和 Moblin 合并为 Meego,X Window 系统的应用将被推向一个新的高潮。
X Window 是 C/S 架构,涵盖 X Server、X 协议、X Client 三部分内容。X Client 有三种开发模式:基于 XLib、基于 GTK、基于 Qt。
X Windows 图形程序基本运行过程:
- 用户通过鼠标键盘对 X server 下达操作命令
- X server 利用 Event 传递用户操作信息给 X client
- X client 运算相应的程序运算
- X client 利用 Request 传回所要显示的结果
- X server 将结果显示在屏幕上
X Client 客户端提供界面实现,执行各种 X 程序,创建一些图形相关资源如 XImage;
常见的情况是 X server 与 X client 都在同一台电脑上运行,分别运行于网络上不同的电脑上即远程桌面。X client 是与硬件无关的,它并不关心你使用的是什么显卡什么显示器什么键盘鼠标,这些只与 X server 相关。服务器端运行在有显示设备的主机上,控制输入输出,维护字体,颜色等相关资源,为客户端提供 GC、Pixmap、Window 等资源。例如,使用 XFree86 桌面环境,运行 xf86config 或 xf86cfg 进行的配置实际上只是与 X server 有关。X protocol 就是 X server 和 X client 之间通信的协议,支持现在常用的网络通信协议,如 TCP/IP,默认 X server 侦听 tcp 6000 端口。
从控制台进入 X 图形环境一般是用 startx 命令:
startx [[client] options .....] [-- [server] options ....]
xinit [[client] options ] [-- [server] [display] options]
把上面 [client] 和 [server] 分别称为 client 程序和 server 程序。
X window system 使用 C/S 结构设计的好处:
- 采用 C/S 架构可以解耦,client 可以采用任意语言开发,只要符合 X protocol 要求。
- 资源统一管理,方便共享。X server 接管硬件及输入事件,clinet 可以方便共享使用,也可主动给各个 clients 发消息。
- 远程显示支持,一般来说 server 和 client 是在同一台电脑上,在不同网络的电脑上运行就是远程登录。
常用的 GTK+,Qt 就是很流行的 x toolkit,实现了常用的组件,而 xlib 封装 X 协议中的打包、解包等操作。所以平时基于 Qt 等框架开发应用的时候,无需理会 X server 的存在。
XLib 就是 C Language X Interface 客户端的 C 语言接口库,它封装了 X 协议,并对应用程序提供方便使用的 API。使用 X-Lib,应用程序不用直接向服务器发送请求与处理回复。
在 Windows 10 中,可以通过 WSL 提供的运行环境安装和运行 X Windows,常用的 X Server 有 Xmanager, Xming, VcXsrv 等:
- Xmanager 是商业软件,需要付费。
- Xming 是开源软件,从 2007 年最后一个免费版本 (6.9.0.31) 之后,就需要捐助才能下载。
- VcXsrv 为开源免费软件,使用方式及界面与 Xming 极为相近。
在 WSL 安装 xfce desktop 这个软件在后台运行就可以提供 Linux 的图形界面,它的优点是轻量、美观、占用系统资源少:
sudo apt-get install xfce4-terminal
sudo apt-get install xfce4
在 Windows 系统安装 VcXsrv 后,开始菜单里现在出现了一个文件夹 VcXsrv,选择里面的 XLaunch,一路选择下一步即可。
安装 xfce 后,退出 WSL 系统,再重新进入执行 xfce4-session 或者 startxfce4,XLaunch 窗口就会有图形界面。
可以将默认显示器配置写入配置文件:
echo "export DISPLAY=:0.0" >> ~/.bashrc
echo "export DISPLAY=192.168.0.97:0" >> ~/.bashrc
Ubuntu 默认源速度如果缓慢,可以切换到阿里源,使用 vim 编辑源配置:
sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak
sudo vim /etc/apt/sources.list
先备分配置文件,再将配置文件中的内容替换:
- cn.archive.ubuntu.com ---> mirrors.aliyun.com
- security.ubuntu.com ---> mirrors.aliyun.com
vim 的替换 substitute 命令 :s
用来查找和替换字符串,语法如下:
:{作用范围}s/{目标}/{替换}/{替换标志}
:%s/cn.archive.ubuntu.com/mirrors.aliyun.com
:%s/security.ubuntu.com/mirrors.aliyun.com
保存并退出,执行一下以下代码更新软件包到最新状态。
sudo apt update
sudo apt upgrade
安装中文语言包
sudo apt install language-pack-zh-hans language-pack-zh-hans-base
设置本地化环境变量
echo "LANG=zh_CN.UTF-8" >> ~/.profile
中文输入法
sudo apt install fcitx fcitx-pinyin
echo -e "export XMODIFIERS=@im=fcitx\nexport GTK_IM_MODULE=fcitx\nexport QT_IM_MODULE=fcitx\n" >> .profile