关于Linux内核月报 Linux阅码场 Linux阅码场内核月报栏目,是汇总当月Linux内核社区最重要的一线开发动态,方便读者们更容易跟踪Linux内核的最前沿发展动向。 限于篇幅,只会对最新技术做些粗略概括,技术细节敬请期待后续文章,也欢迎广大读者踊跃投稿为阅码场社区添砖加瓦。 本期月报(总第1期)主要贡献人员: 张健、宋老师、廖威雄、理查德、Dog250、Bob (月报的完善和专业,离不开大牛们的持续贡献,欢迎更多大牛加入月报贡献团队) 1. 体系结构 1.1 MTE(Memory Tagging Extension)近期Linux社区在大量讨论ARM v8.4和v8.5的扩展特性,例如v8.4的嵌套虚拟化和v8.5的MTE(Memory Tagging Extension) 。MTE是硬件支持的memory tag,目的是解决spatial safety和temporal safety两类安全性问题。 所谓的memory tag是指利用地址中固定的无用的bit传递更多信息(即tag)的方法。例如,在64位系统下,实际只有最高位63bit用于表示内核和用户空间,假设系统是48位VA,最多[62:49]可以用于做tag。ARM的MTE特性使用[59:56]传递tag。 用户可以通过为mmap,mprotect添加的新的flag PROTMTE指定使用tag的range。补丁同时还需要考虑所有与用户空间相关的page操作,例如fork进程导致的 copy on write;page migration;page比较(memcmppages)等方面。这个系列的补丁是由ARM64 maintainer catalin主导的,如果没有什么意外,计划在5.9合入. 参考资料:MTE社区支持情况,MTE白皮书等等: https://developer./tools-and-software/open-source-software/linux-kernel/memory-tagging 1.2 Support new pmem flush and sync instructions for POWER1.3 arm64: add the time namespace support2. 驱动和工具 2.1 Data Access MONitor (DAMON)DAMON这个工具主要提供跟踪一个特定用户进程的内存访问pattern的功能,这个功能对于性能优化非常有意义。 一个最直接的用户case就是对程序的行为进行分析,根据DAMON的输出,我们能确定一个程序是否按照预期在运行。 对于系统管理员而言,你可以利用监控的结果数据,确定你的workload的动态working set size。 对于程序员而言,你可以根据监控结果反映出来的实际data访问pattern,来对你的程序的内存进行管理。比如,你可以用DAMON获知热点数据,从而用mlock()把热点锁入内存,或者用MADV_PAGEOUT参数的madvise()来激进地回收冷数据。 DAMON向用户汇报哪些pages被频繁地访问,它采用了一个“Region Based Sampling”的技术,把相邻的pages绑定在一起成为一个group,假定整个region有相同的访问频率,从而避免了一页一页扫描accessed bit的开销。 2.2 Netgpu: networking between NIC and GPU/CPU这个patchset提供了一个功能:在网卡和GPU之间实现数据的DMA 零拷贝,但是协议的处理仍然保留在主机的CPU上面进行。 2.3 iommu: Shared Virtual Addressing for SMMUv3(PT sharing part)SVA的主要目的是让设备和CPU里面运行的进程共享页表,从而让进程的地址空间直接对设备的DMA可见。 自从V7版本开始,这个patchset被分为3个部分: 1.加page table共享的功能到SMMUv3 ; 2.增加基于PRI、stall的IO Page fault支持; 3.附加的以及可选的特性,如DVM,VHE和HTTU 3. 内存管理 3.1 workingset protection on anonymous LRU list 为了更好的利用内存,内核会将“冷”页释放挪作他用。而这个“冷热”的区分是用过不同的LRU链表实现的。 最近内核开发者发现匿名页的冷热判断在某些情况下会把“热”页挤到”冷”页的队列里,这样就会导致“热”页的再次需要通过缺页中断回到系统中。 下面我们将用一个简单的图展示这种特殊情况下LRU链表的变化: 开始有50个热页
然后来了50个新的页,但是只需要用一次
接着又来了新的一批50个新的,但是只用一次的页
上面的示例使用的标记方式是:
可以看到,在这个情况下真正的热页将被挤出LRU链表,下次需要使用时则需要再次通过缺页中断。 那内核开发者是如何避免这样的情况发生的呢?
调整后整个过程就变成了:
这是一个历经了13版,还在review的patch set。从整个patch set来说,最核心的目标是这个patch中想要做的。 mm/lru: replace pgdat lru_lock with lruvec lock 就像这个patch中描述的一样,这个patch的目的是
用一个简图解释一下这个变化。 原来操作lruvec的锁每个node上只有一把,在pg_data_t结构体中。这样明显竞争会比较大。 作者则把这个锁放到了lruvec结构体中,这样每次去抢的锁就是在自己的lruvec上了。以此来减少锁的竞争。 而且作者在使用了这组patch后,测试的结果非常惊人。 With this and later patches, the readtwice performance increases about 80% within concurrent containers 3.3 memcg: Slow down swap allocation as the available space gets depleted 当系统的swap空间耗尽时,系统的状态会有一个非常突然的变化。整个系统的匿名页变得不可管理,甚至会crash整个系统。当前业界采用了一个叫 oomd的用户态程序来监控swap空间,当发现swap空间变小时就选择一些低优先级的进程杀死。这个oomd的地址是 https://github.com/facebookincubator/oomd 内核开发者提出了优化,可以不借助oomd来应对swap空间耗尽。内核开发者提出的方式是借用了memcg的接口,除了检测内存分配的警戒线之外,还检测swap使用的情况。只要其中之一处于高位,那么就开启回收进程来避免swap耗尽。
3.4 make dma_alloc_coherent NUMA-aware by per-NUMA CMA 这个patchset的作用,是给每个NUMA节点分配一个默认的CMA区域,这样保证设备dma_alloc_coherent()的时候,可以申请到本地NUMA节点的dma buffer。使得ARM SMMU的command queue等可存放于本地内存,避免跨NUMA NODE进行远程访问。对IOMMU passthrough的场景,也会有性能提升。 4. 文件系统和Block Layer 4.1 Enable ext4 support for per-file/directory DAX operations 跟 xfs 一样,最新代码也已经在ext4上支持单个文件、文件夹设置 DAX 特性了。DAX 指 Direct Access for file,即不需要缓存,直接访问存储设备上的文件。 我们知道,目前常见的 内存(dram)的性能远大于 存储(HDD\SSD\Nand\Emmc),所以一般会使用内存作为缓存(PageCache),把磁盘的数据缓存起来,这样的设计的确极大提高了系统的IO性能,但对新出的 NVDIMM 设备而言,缓存却显得多余了。 NVDIMM 是 non-volatile dual in-line memory module 的缩写,中文翻译为非易失性双列直插式内存模块。从技术上来说,这实际是 Dram + Nand + 超级电容 实现 内存的高速,存储的掉电非易失性。原理可以简述为,正常工作时,外部供电,数据存储在 NVDIMM 的 Dram 部分;在掉电时,超级电容供电,把 NVDIMM 的 Dram 数据 写入 NVDIMM 的 Nand ,在下次启动时恢复到 NVDIMM 的 Dram。 NVDIMM 设备具有内存的高速,此时再使用 PageCache 缓存数据就很累赘了,因此有了 DAX 技术,不使用缓存,直接访问设备。除了 NVDIMM 这样的设备之外,对虚拟机也有很大作用,可以避免虚拟机内部和主机上产生两份缓存。 xfs 上很早就支持了单个文件、文件夹设置 DAX 属性,而ext2/4还只是全局的 DAX 挂载属性,现在只是在 ext4 上也支持了单个文件、文件夹操作。 4.2 support batching dispatch from scheduler在之前的实现中,为了尽可能在IO调度中合并请求,调度器每次只从队列中获取和分发一个请求,但实际上越来越多的设备支持批处理多个请求,每次只处理一个请求会造成性能浪费。这个 patchset 就实现了在IO电梯调度器中支持批量分发IO请求,只要设备还是空闲,就可以把多个IO请求分发下去,充分利用设备的批处理资源。 除了 mmc 驱动、一些基于tcp的存储驱动之外,virtio-scsi、virtio-blk等虚拟设备批处理能力更强,这个 patchset 能发挥非常大的作用。在virtio-scsi 上测试IO性能提高 5%~10%。 4.3 Inline Encryption support4.4 kernfs: proposed locking and concurrency improvement5. 网络 5.1 bpf:Add support for XDP programs in DEVMAP entries 增加了一个新的eBPF程序的挂载点,使XDP在基于DEVMAP的REDIREC决策被作出之后运行一个eBPF程序成为可能。该特性允许新挂载点上的eBPF程序可以同时看到Rx和Tx设备端口。 bpf: introduce support for XDP programs in CPUMAP与 bpf: Add support for XDP programs in DEVMAP entries 类似,在基于CPUMAP的REDIREC决策被作出之后,在目标CPU上允许运行一个eBPF程序。 5.2 Strict mode for VRF 该新特性提供了一种在VRF和其使用的路由表之间创建严格一对一映射关系的方法。strict mode增强了VRF路由表的隔离性,在多个VRF隔离的进程操作相同路由表时,消除了误操作,有效降低了造成冲突的机会。同时,SRv6也将从该特性中获得收益,详情参见: https:///lkml/2020/6/12/566 5.3 implement bpf iterator for tcp and udp sockets 使用eBPF来遍历系统中的TCP/UDP socket,增强了灵活性。该特性旨在替换传统的基于硬编码的TCP/UDP socket遍历方式,比如当前/proc/net/tcp的实现。 5.4 net: tso: expand to UDP support 该patch为UDP提供了和TCP一样的卸载设施。patch本身是简单的,但它的背景很有意思。随着Quic越来越被各类云厂商关注和部署,有越来越多的针对它的传输协议UDP的优化手段被提了出来。关于UDP的优化,目前仅仅是个开始,我们会持续关注。 5.5 multi release pacing for UDP GSO这是针对UDP的一个具体优化patch。简单来讲,该patch使UDP在GSO开启的情况下增强了pacing发送的效果,相当于为一个UDP GSO段配置了多个发送时间,有效避免了属于同一个GSO段的所有数据包同时以burst方式发送。无论是pacing还是GSO,均可以有效提高包括Quic在内的协议处理性能以及端到端性能,在以往,这两个特性是无法共存的,甚至是矛盾的,该patch的意义在于将两者结合了起来。 5.6 ptq: Per Thread Queues该patch涉及Linux内核网卡多队列技术的增强。此前的网卡队列只能和CPU进行对应,该patch允许具体的Thread直接和网卡队列进行绑定。 6. 虚拟化和容器 6.1 KVM: Dirty ring interface 当前KVM使用bitmaps来跟踪脏内存,当用户态查询kvm的脏页信息时,这些bitmaps需要从内核拷贝到用户态。在一些场景下(比如内存很大但是脏页很少),频繁的拷贝和查询bitmap可能效率会不高。 这个系列patch实现一种新的收集虚拟机脏页的接口,旨在想解决当前dirty logging的缺点。 新的接口主要有三方面差异: - 数据格式: 脏数据通过per-vcpu的ring格式管理,而不再是per-vm的bitmap格式 - 数据拷贝: 脏页sync时不再需要通过数据拷贝的方式,而是让ring在用户空间和内核态直接共享 - 接口: 引入新的KVM_RESET_DIRTY_RINGSioctl接口 不过作者在24G guest上的测试结果还没有发现很有说服力的测试数据,原因可能是因为dirty bitmap才1M本身就不大,还需要更多有价值的测试才行 2. vfio: expose virtual Shared VirtualAddressing to VMs 虚拟地址共享Shared Virtual Addressing (SVA)是指设备dma能够直接使用应用程序的虚拟地址,这样能够增强安全性和降低编程的复杂性。 这个系列patch是要让guest里面的应用程序也能和透传的设备直接共享虚拟地址(vSVA),涉及到QEMU/VFIO/IOMMU等模块的改动 vSVA的大概架构如下,主要是要使能IOMMU的二级地址转换能力: 6.3 vhost: ring format independence 这个系列patch比较直观,主要是为了让vhost能够支持更多的ring格式。所以抽象出来一层通用结构,给virtqueue引入一个通用的struct vhost_desc数组,通过这个数组再去找到真正的描述符,虽然这样增加了额外的消耗,但是能够批量的拿到描述符能够提高cache的命中率,在实际测试中只有很小的性能影响 6.4 Add support for Nitro Enclaves 挺有意思的一个patch,给linux内核增加Nitro Enclaves的支持,Nitro Enclaves (NE) 是Amazon EC2实例的一个新能力,允许客户在Amazon EC2实例内再分割出来一个独立隔离的运行环境。 例如Amazon EC2 实例中的某个应用程序要处理些敏感数据时,就可以让这个应用程序在一个独立的新隔离环境(Nitro Encalve)中运行。 Nitro Enclaves 提供了隔离的、增强的且约束性很高的环境,可帮助客户减少他们用于处理最敏感数据的应用程序的攻击面。 Enclaves运行时所要的cpu/memory等资源都来自主EC2实例。 感兴趣的读者可以猜猜看是如何实现的,再去看看具体的Patch。 |
|
来自: 西北望msm66g9f > 《编程》