前文回顾:一起聊聊WSL的那些事儿(上)

文件系统

在WSL这个feature刚出来的时候,很多人都抢着装上了这个特性,包括笔者的同学们都争先恐后的体验这个特性,不过最后都成了黑子,因为大家发现File IO 在WSL中实在是太慢了。

* Picture 14 笔者在自己用vmware中的ubuntu和wsl 尝试解压同一个文件的差距

为了更好的介绍WSL进行了哪些操作,从而实现了Linux向Windows文件系统的兼容(同时却也没有很好的解决File IO问题),这里需要简单介绍一下Linux和Windows上对文件管理的接口,帮助大家理解。

Linux - VFS

Linux中使用了一种中抽象的虚拟文件系统,叫做VFS。它定义了一套接口让Linux上的应用能够调用对底层的磁盘文件系统中的文件进行操作,例如读写,打开等等,并且通过定义接口让不同的上层操作系统来实现对应的接口,从而实现将整个底层的文件系统抽象出来。

在VFS中,使用了如下列举的几种特性:

 Inode 这个结构体中存储了各种linux下的文件中被VFS使用的基本数据结构。比如说普通文件,符号文件,设备文件等等。每一个inode代表的是一个文件对象(而非文件名),里面主要记录的是文件关于存储的信息。

Directories entry存储的是每一个目录,存放了指向每一个inode的指针,并且这个对象会被存储在内存中,加快访问文件inode的速度。

File Object 这个是inode中通过open的方式获取的真实的文件对象,其中记录了文件对象在应用层面的相关信息,里面记录当前文件读/写指针,以及针对当前文件中定义的读写等各类操作。

File descriptors Linux也是实现了类似于Windows下的handle管理对象,通过对文件描述符的操作来实现对文件的管理。

Windows

Windows下的所有系统资源都是以对象的形式存在的。除了文件外,还包括线程,共享内存,计时器等。打开文件的操作其实就等价于打开NT kernel下的对象管理器,通过I/O管理器将当前的请求发送到正确的文件系统驱动中。因为在Windows中,不存在inode这样的结构体,不过Windows中存在Directory entry这样的结构,所以其会通过ntfs.sys这类驱动来解决路劲解析问题。

当文件被打开的时候,对象管理器将会创捷一个文件对象。与Linux中的文件描述符相对应,Windows中的称为句柄(Handles),句柄对应的是一个内核对象(Kernel Object)而不是文件描述符(File Descriptor)。当调用类似于NtReadFile 这类API去读取文件的死后,I/O 管理器将会创建一个IRP,发送至文件系统驱动,让文件对象能够执行请求。由于Windows下没有类似于inode的结构体,所以很多的文件请求都需要一个文件对象来完成。

WLS下的内部实现

可以看到,Windows和Linux下对于文件的操作存在很多不同的地方,所以Windows为了尽可能的实现Linux的文件操作,实现了一套VFS*相关的接口,模仿Linux中提出VFS来兼容底层文件系统的方式,实现了一个类似文件操作接口。

对于文件描述符的系统调用(比如read, write或者 sync),lxcore直接调用文件系统定义的相应操作。这个系统有意的使用近似Linux行为,从而WSL可以支持相同的语义。

* Picture 15 WSL下的类VFS文件系统(图片来自网络)

如上图, Procfs和Sysfs这些是直接实现的一些抽象,因为在Windows下并没有类似的文件结构。不过除去这些,有两个驱动是专门处理文件存储的,一个是用于处理WSL根目录下文件存储的VolFs,另一个是处理现有的分卷上文件存储的Drvfs。

VolFs

VolFs是用来挂载虚拟文件系统(VFS)的根目录的处理驱动,使用%LocalAppData%\lxss\rootfs作为备用存储器。其主存储放在                                          【C:\Users\Username\AppData\Local\Packages\CanonicalGroupLimited.UbuntuonWindows_*\LocalState】

不过由于文件系统的差异,所以如果直接使用Windows直接操作(非WSL环境下)创建的文件权限可能会有问题。。

Linux和Windows的文件系统有好几个方面的不同。所以VolFs必须对Windows不能直接支持的几个Linux特性提供支持。例如,由于Windows 中没有索引节点概念,VolFs 创建的索引节点会关联要给Windows 文件对象句柄。这些句柄的打开不需要任何的读/写文件,且只能用于元数据的请求。

* Picture 16 Inode中间其实维护了一个File Handle

Windows本身可以处理大小写敏感。正如前面提到的,Windows和NTFS实际上支持大小写敏感操作,所以,无论全局注册键如何控制,VolFs会请求对象管理器将路径看做是大小写敏感的。所以,切记不要再根目录以外的地方用WSL创建同名但是大小写不同的文件,这样对于Windows的文件管理会出现不可预计的后果。

Linux的文件名还支持将全部字符视为合法字符。NT中却有更多的限制,有些字符根本不允许作为文件名,还有些字符可能具有特殊含义(例如“:”表示数据流)。为了支持所有Linux文件名,VolFs将文件名中的非法字符进行转义。

Linux中的断开链接(unlinking)和重命名(renaming)有一些不同的语义。具体的说,某个文件即使有打开着的文件描述符指向它,也可以断开链接。同样,某个文件即使打开着,也可以对其进行重命名的操作。在Windows中,如果要请求删除一个文件,那它最终的状态必须是关闭着的,此时文件名在文件系统中可见。为了支持Linux中的断开链接语义,请求删除前,VolFs会将断开链接的文件重命名至一个隐藏的临时文件夹中。

Linux的索引节点具有一些Windows中不存在的属性,包括拥有者和组、文件模式等。这些属性存储在与磁盘文件相关联的NTFS扩展属性中。扩展属性中存储的信息如下:

· 模式(Mode):包括文件类型(普通文件、符号链接、FIFOs等)和该文件的权限位。

· 拥有者(Owner):拥有该文件的Linux用户ID和组ID。

· 设备ID(Device ID):设备文件的主设备号和次设备号。注意,WSL目前还不允许用户在VolFs中创建设备文件。

· 文件时间(File times):Linux中的文件访问时间、修改时间和改变时间所采用的格式和粒度与Windows中不同,所以,这些时间也存储在EAs(Extended Attributes)中。

其余的索引节点属性,例如索引节点号和文件大小, 都源自于NTFS中保存的信息。

所以,如果从Windows下直接操作一些WSL下的文件,就会导致很多这些基本信息未被更新到Volfs中,从而导致权限出现错乱。

Drvfs

为了便于和Windows系统之间文件存储的交互,WSL使用了DrvFs文件系统。WSL将具有可支持文件系统的卷自动挂载到/mnt目录中,例如/mnt/c、/mnt/d等。目前,仅能支持NTFS和ReFs两种类型的卷标。

DrvFs的操作方式和VolFs类似。当创建索引节点和文件对象时,打开指向Windows文件的句柄。但与VolFs相比,DrvFs遵循Windows规则。比如,DrvFs使用Windows权限,只允许使用合法的NTFS文件名;并且DrvFs不支持特殊的文件类型,比如FIFOs(命名管道)和sockets。

在DrvFs中,当打开一个文件时,会继承启动WSL的用户令牌的Windows权限,也就是说令牌是由用户执行bash.exe产生的。所以,在WSL中要访问C:\Windows目录下的文件,在bash环境中使用“sudo”还是不行的,虽然你拥有了root权限,但并没有改变你的Windows用户令牌,还必须启动bash.exe以便进一步获得合适的权限。

为了给用户关于他针对某个文件所拥有的权限的提示,DrvFs检查用户有效的文件权限,并将其转换成“读/写/可执行”位,例如执行“ls -l”命令可以看到。不过这其中也并不都是一对一的映射关系。例如,Windows中对于在目录中创建文件和子目录需要不同的权限。如果用户拥有任意一种权限,DrvFs都视为对目录拥有写访问权限,但实际上有些操作可能还是会因拒绝访问而失败。

* Picture 17 Drvfs尽可能的实现了一一映射

因为对文件的有效访问权限会因bash.exe是否启动是否提升了权限而不同,所以,DrvFs中显示的文件权限也会随着bash实例的权限提升与否而改变。

DrvFs支持区分大小写文件,这意味着可以创建两个文件名大小写不同的DrvFs。请注意,许多的Windows应用程序可能无法处理这种情况,并且可能无法打开一个或两个文件。(比如笔者测试的平台为1709,如果将两个exe文件改成同名但是大小写不同,会导致双击的时候两个软件都无法启动)。

* Picture 18 哦......WSL和Windows打架了

大小写敏感被禁用在卷根上,但其它地方可以用。因此,为了使用大小写敏感的文件。不要尝试创建/mnt/c,而是创建一个目录,在这个目录里可以创建文件。

和VolFs不同,DrvFs不会存储任何的额外信息。相反,所有的索引节点属性都是通过查询NT中使用的文件属性、有效权限以及其它的信息派生而来的。DrvFs还禁用了目录项缓存,以确保即使Windows进程对目录的内容进行了修改的情况下,它也总能提供正确的、最新的信息。因此,当使用DrvFs时,对Windows进程如何处理文件没有任何限制。

DrvFs还对文件使用了Windows删除语义,所以,如果某个文件存在任何打开着的文件描述符(或者Windows进程在处理着),那我们就不能取消对其的链接。

* Picture 19 导致WSL File IO慢的原因之一

回到本段开头提到的问题,为什么说WSL的File IO很慢呢?其实通篇看下来的话应该也猜到原因了:因为WSL只是简单的实现了Windows 文件系统的抽象,所以WSL的File IO慢,其实本质上是Windows的文件系统和Linux的文件系统的差异导致的。笔者做的实验中,使用的是一个目录很深并且有很多小文件的压缩包,对于这类量非常大的小文件处理,Windows本身就弱于Linux,这就导致了问题本身的出现。(当然,Windows Defender的扫描也是需要背锅的原因之一)

WSL一些现存的问题

虽然WSL目前设计以及趋于完善,不过本身却还有不少有问题的地方。比如说,目前所有的WSL中的进程再Windows操作系统中都是直接运行在内核态的,虽然这个进程本身是由Linux进行维护,不过一旦出现之前提到的那种CVE,直接使用攻击手法对lxcore翻译过程进行攻击,这个过程就会变得像是沙箱逃逸一样,对Windows本身的内核产生影响。

WSL中的elf以及其依赖的各类library在load的时候是没有设置SEC_IMAGE这个flag的,这意味着一些Windows的一些API和feature将会无法追踪这个image的映射过程。例如PsSetLoadImageNotifyRoutine将会无法追踪相关的elf映射这将导致一些杀毒软件的监控失效,并且AppLocker(AppLocker是Microsoft Windows 7操作系统引入的应用程序白名单技术)将会无法工作。并且其操作是强制大小写敏感的(除非在WSL的Linux中关闭这个特性),所以它能够绕过Windows中的注册表开关,强行执行大小写敏感。

WSL2

* Picture 20 WSL还没研究完呢又来了个WSL2

笔者在研究WSL的过程中遇到了蛮多的麻烦,在研究有了一些眉目的时候,BUILD2019宣布WSL2公布了。此时内心是十分复杂的。

随着6月13号WSL2的公布,很多爱好者也体验到了其中的特性。这里简单介绍一下WSL2中与WSL里不相同的部分:

1.     WSL2并非直接翻译Linux的内核中断调用,而是使用了类似虚拟机的技术。过去微软是通过将Linux的各种中断,文件系统等进行翻译,从而对Linux系统进行一个抽象。但是实际上这样做还是有很多的问题,直译这个过程中,有些内容,例如linux下的namespace,systemd,以及VBF+EXT4向NTFS的转型其实还是非常不便的。而新推出的WSL2则是会直接在Windows中内嵌一个Linux的内核,版本是4.19,一个LTS版本的Linux 内核版本。如果是Linux的内核的话,那就意味着不再需要lx*的内核驱动对中断/文件系统的各种映射进行翻译,能够原生的支持Linux下的各类中断调用。

2.     WSL依然会保留,并且可以和WSL2可以切换,甚至可以同时运行两种不同的WSL

3.     由于是一种轻量级的VM,其依赖于Hyper-v的内核,开启WSL2的时候,会与VBox和Vmware这类软件发生冲突

4.     WSL2使用了VHDX来存储根目录,从而让WSL2使用EXT4+VFS的文件系统,尽可能的和真正的Linux相符。

总的来说,WSL2目前已经出现了很多的新特性,但是好像还有不少问题(比如说不能调用GPU等相关硬件)目前还在开发中,之后的特性就让我们拭目以待吧。

参考网站:

http://www.alex-ionescu.com/publications/BlueHat/bluehat2016.pdf

https://devblogs.microsoft.com/commandline/announcing-wsl-2/

https://blogs.msdn.microsoft.com/wsl/

https://devblogs.microsoft.com/commandline/whats-new-for-wsl-in-windows-10-version-1903/

*以上部分图片来自网络

wsl ubuntu拒绝访问_一起聊聊WSL的那些事儿(下)相关推荐

  1. webbrowser 访问iframe拒绝访问_电脑无法删除文件访问被拒绝【解决方案】

    在使用时遇到了无法删除访问被拒绝 的问题,无法删除访问被拒绝 虽然不是大问题,但无法删除访问被拒绝 的问题会导致无法正常工作,那该怎么处理呢,下文给大家分享一下无法删除访问被拒绝 的具体解决方法: 无 ...

  2. 远程连接mysql拒绝访问_远程连接 Mysql 失败的解决方法

    原标题:远程连接 Mysql 失败的解决方法 今天在虚拟机Ubuntu上折腾了一晚上mysql,然后试着用java连接,搞了很久都没成功,但是同学配好的Debian上却连接成功了,也就是说我的配置有问 ...

  3. python输出结果存到文件拒绝访问_三步解决python PermissionError: [WinError 5]拒绝访问的情况...

    问题描述: 1.当你卸载python库的时候,如:pip uninstall pandas 2.当你想要更新python库的时候,如:pip install --upgrade pandas 等等- ...

  4. wordpress拒绝访问_如果您的网站被列入黑名单该怎么办

    黑名单是一种标记带有恶意内容的网站的做法,以防止用户意外下载恶意软件.但是,搜索引擎和防病毒供应商可能会因网络攻击而将您的网站列入黑名单.这可能会对您网站的声誉和知名度产生负面影响. 在互联网上,信誉 ...

  5. uniaccess进程无法结束 拒绝访问_嵌入式Linux编程——程序员小白不懂的进程、信号量、并发、互斥...

    所有学嵌入式Linux系统的看过来了,以下内容是每一位想学习Linux嵌入式系统想要了解的内容,真的很想要分享给大家! 本文分享的内容主要如下几个方面: 3.1 并发的原理 3.1.1 一个简单的例子 ...

  6. python os.remove拒绝访问_「进阶Python」第八讲:代理模式

    本文完整代码请查看github项目:advance-python,或者直接访问链接: https://github.com/Jackpopc/advance-python/blob/master/6- ...

  7. mbrfix修复拒绝访问_拒绝错误修复的一些正确原因

    mbrfix修复拒绝访问 当某些东西无法按预期工作时,存在一个错误. 漏洞修复基本上是对现有代码库的补丁(拉取请求),旨在解决问题并确保"某些操作"按预期工作. 通常,这样的修补程 ...

  8. java为什么说拒绝访问_拒绝访问??

    在命令行输入的时候为什么会出现这种情况? C:\Program Files\Java\jdk1.8.0_102\bin\corejava\v1ch02\RoadApplet>javac  Roa ...

  9. 手机访问网站提示拒绝访问_保持访问者参与和访问您网站的6条提示

    手机访问网站提示拒绝访问 It can be worrying when you put lots of time and effort getting visitors to your websit ...

最新文章

  1. java qq ui界面,java UI之QQ登录
  2. 每日一皮:一个项目开发的真实写照...
  3. redis的flushall命令
  4. C语言数组的一些运算*a,a+1,a+1,a+0
  5. uiautomation遍历windows所有窗口_万字长文!滑动窗口看这篇就够了!
  6. linux ping库函数,Linux 常用基本命令 ping ifconfig
  7. 【汇编语言与计算机系统结构笔记04】80x86计算机组织、保护模式、存储器、寄存器、计算机系统结构金字塔
  8. 力扣-989 数组形式的整数加法
  9. 菜鸟也玩系统安装盘的集成(图文教程)
  10. C#开发和调用Web Service
  11. 绕过卡巴斯基dump进程lsass.exe内存
  12. Ghost Win10 企业版LTSC 2020.05(32位+64位)
  13. mysql pxc 使用_PXC使用介绍
  14. 灰度发布、蓝绿发布、滚动发布
  15. kettle连接mysql 8.0以上数据库所需驱动包
  16. Cracking the Wall of Confinement: Understanding and Analyzing Malicious Domain Take-downs
  17. 无聊吗,写个【飞机大战】来玩吧(下)
  18. flv.js php,flv.js的使用详解
  19. 如何简单的运营企业群呼系统呼叫中心系统
  20. JPEG 标准推荐的亮度、色度DC、AC Huffman 编码表

热门文章

  1. 模型压缩的开源项目工具
  2. webpack2 实践
  3. Unity3D的坑系列:动态加载dll
  4. DDD 领域驱动设计-如何 DDD?
  5. IOS不同层的传输格式
  6. 使用Edge.js,在JavaScript中调用C# .Net
  7. 2011最新个人所得税计算器---起点3500元
  8. 程序员的灯下黑:不要忘记你的目标
  9. 开启一个新的spyder窗口
  10. Windows10如何设置系统保护色