slub工作原理详解

合集下载

bootloader原理

bootloader原理

bootloader原理引言:在计算机系统中,bootloader(引导加载程序)是启动计算机操作系统的第一个程序。

它的主要作用是初始化系统硬件并加载操作系统内核,使计算机能够正常启动。

本文将详细介绍bootloader的原理和工作流程。

一、bootloader的作用bootloader是计算机启动过程中的重要组成部分,其作用主要有以下几个方面:1. 初始化硬件:bootloader负责初始化计算机系统的硬件设备,包括CPU、内存、外设等。

通过与硬件交互,确保系统能够正常运行。

2. 加载操作系统内核:bootloader从硬盘或其他存储设备中读取操作系统内核的镜像文件,并将其加载到内存中。

加载完成后,将控制权交给操作系统。

3. 提供启动选项:bootloader可以提供多个启动选项,允许用户选择不同的操作系统或系统配置。

这在多系统或多配置的计算机中尤为重要。

二、bootloader的工作流程1. 加电自检:当计算机加电时,CPU会首先执行自检程序,检测硬件设备是否正常工作。

自检完成后,将转移到bootloader程序上。

2. 加载bootloader:在计算机的硬盘或其他存储设备中,有一个固定的位置存放着bootloader程序。

CPU会通过读取存储设备上的引导扇区,将bootloader加载到内存中。

3. 初始化硬件:bootloader会初始化计算机的硬件设备,包括CPU、内存、硬盘、显示器等。

这些初始化操作是为了确保系统能够正常运行,并为操作系统的加载做好准备。

4. 加载操作系统内核:bootloader会从存储设备中读取操作系统内核的镜像文件,并将其加载到内存中的指定位置。

加载完成后,bootloader将控制权交给操作系统。

5. 启动操作系统:操作系统接管控制权后,会执行自己的初始化操作,并进入正常的工作状态。

至此,计算机的启动过程完成。

三、bootloader的实现方式bootloader的实现方式因计算机架构和操作系统而异。

l-bus工作原理

l-bus工作原理

l-bus工作原理L-Bus工作原理L-Bus是一种用于数据传输和通信的总线协议,它具有高效、可靠和灵活的特性。

本文将介绍L-Bus的工作原理,包括其传输方式、通信协议和数据处理流程。

一、传输方式L-Bus采用串行传输方式,即将数据位逐位地通过一根传输线进行传输。

传输线上通过不同的电平表示0和1,即逻辑低和逻辑高。

传输线由发送器和接收器连接,通过发送器将数据转换为电平信号发送到传输线上,接收器则将传输线上的电平信号转换为数据。

二、通信协议L-Bus使用一种简单而高效的通信协议,其中包括数据帧的格式和通信规则。

1. 数据帧的格式L-Bus的数据帧由起始位、数据位、校验位和停止位组成。

起始位用于标识数据帧的开始,数据位包含要传输的数据,校验位用于检验数据的正确性,停止位用于标识数据帧的结束。

2. 通信规则L-Bus的通信规则包括数据的发送和接收过程。

发送过程中,发送器将数据按照数据帧的格式进行编码,并通过传输线发送出去。

接收过程中,接收器从传输线上接收数据,并按照数据帧的格式进行解码。

解码后,接收器可以获得发送器发送的原始数据。

三、数据处理流程L-Bus的数据处理流程主要包括数据发送和数据接收两个步骤。

1. 数据发送数据发送的过程如下:1) 发送器准备要发送的数据,并按照数据帧的格式进行编码。

2) 发送器将编码后的数据逐位地发送到传输线上。

3) 接收器从传输线上接收数据,并按照数据帧的格式进行解码。

4) 解码后,接收器获得发送器发送的原始数据。

2. 数据接收数据接收的过程如下:1) 接收器从传输线上接收数据,并按照数据帧的格式进行解码。

2) 解码后,接收器获得发送器发送的原始数据。

3) 接收器对接收到的数据进行处理,可以根据需要进行存储、分析或进一步传输。

四、总结L-Bus是一种高效、可靠和灵活的总线协议,通过串行传输方式实现数据的传输和通信。

它采用简单而高效的通信协议,包括数据帧的格式和通信规则。

usb hub 工作原理

usb hub 工作原理

usb hub 工作原理USB Hub 工作原理USB Hub(通用串行总线集线器)是用来扩展计算机USB接口的设备。

它可以将一个USB接口扩展为多个,从而实现同时连接多个USB设备的功能。

本文将从浅入深,逐步解释USB Hub的工作原理。

什么是USB Hub?USB Hub是一种设备,它具有一个Upstream口和多个Downstream 口。

Upstream口用于连接到主机电脑的USB接口,而Downstream口则用于连接其他USB设备,如鼠标、键盘、摄像头等。

USB Hub的作用是将主机电脑的一个USB接口扩展为多个接口,便于用户连接更多的USB 设备。

Hub的架构一个USB Hub内部包含多个端口。

当USB设备插入Hub的端口时,Hub会根据设备的需求进行交互,并提供适当的电力和数据传输速率。

Hub与主机电脑之间通过Upstream口进行通信,而与其他USB设备之间通过Downstream口进行连接。

数据传输流程当用户将USB设备插入到Hub的一个空闲端口时,数据传输流程如下:1.用户将USB设备插入Hub的端口。

2.Hub检测到设备插入并发送插入事件给主机电脑。

3.主机电脑收到插入事件后,发送初始化命令给Hub。

4.Hub根据设备的需求,向主机电脑请求为该设备分配适当的电力和速率。

5.主机电脑通过配置命令告知Hub分配的电力和速率。

6.Hub向设备提供适当的电力,并根据配置信息设置数据传输速率。

7.设备与主机电脑之间开始进行数据传输。

设备的供电USB Hub不仅可以传输数据,还可以为连接的USB设备提供电力。

Hub根据设备的需求动态分配电力,以满足设备的工作要求。

总线带宽管理USB Hub能管理其所有连接设备之间的数据传输。

如果多个设备同时发送数据,Hub会依照USB规范的带宽分配方法,协调数据传输,确保传输的稳定和流畅。

总结USB Hub是一种用于扩展计算机USB接口的设备。

通过将一个USB 接口扩展为多个接口,用户可以连接更多的USB设备。

libusb原理

libusb原理

libusb原理
libusb是一个开源的跨平台的USB库,它提供了一套统一的API,可以让开发者方便地访问和控制USB设备。

libusb的原理是通过操作USB总线上的传输层来实现设备的
访问和控制。

它通过USB设备驱动程序提供的底层接口,与USB设备进行通信。

libusb将USB设备的功能抽象成一组统
一的接口,让开发者可以直接使用这些接口来进行设备的读写、配置、控制等操作,而无需关心USB协议的细节。

libusb的工作流程如下:
1. 初始化libusb库,并打开USB设备。

2. 通过libusb提供的接口,获取USB设备的描述信息、配置
信息等。

3. 根据设备描述信息和配置信息,进行设置和控制USB设备。

4. 进行数据的读写操作。

5. 关闭USB设备,并清理libusb库。

libusb的原理是基于USB协议规范的,它将复杂的USB通信
协议封装成了一组简单易用的API接口,让开发者可以方便
地进行USB设备的访问和控制。

同时,libusb还提供了一些
方便的函数和工具,帮助开发者处理USB设备插拔事件、枚
举USB设备等。

通过libusb,开发者可以跨操作系统平台,
实现与USB设备的通信,方便地进行硬件开发和测试。

动态链接库so打包原理

动态链接库so打包原理

动态链接库so打包原理
动态链接库(Dynamic Link Library,简称DLL)是一种在Windows操作系统中常见的共享库文件格式,而在类Unix系统中通常使用的是共享对象(Shared Object,简称SO)文件。

这些库文件包含了可被程序调用的函数和资源,允许多个程序共享同一个库文件,从而节省内存和磁盘空间。

动态链接库的打包原理涉及到编译、链接和加载等多个方面。

首先,在编写程序时,开发人员会使用编程语言(如C、C++)编写源代码文件,然后通过编译器将源代码文件编译成目标文件。

接下来,编译器会将目标文件中的函数调用和外部依赖解析成符号,并生成符号表。

在链接阶段,链接器会将符号表与其他库文件进行匹配,并将程序中需要调用的函数符号与动态链接库中的函数地址进行关联,生成可执行文件。

在这个过程中,动态链接库中的函数并没有被复制到可执行文件中,而是在程序运行时动态加载。

在程序运行时,操作系统的动态链接器会根据程序中的动态链接库依赖信息,将相应的动态链接库加载到内存中,并将程序中的函数调用指向这些动态链接库中的函数地址。

这样,程序就可以在运行时动态地调用动态链接库中的函数,实现了共享和动态加载的
功能。

总的来说,动态链接库的打包原理涉及到编译、链接和加载等多个阶段,通过符号表和动态链接的方式实现了程序与动态链接库之间的关联,从而实现了动态加载和共享的功能。

云厂商slb 负载均衡原理

云厂商slb 负载均衡原理

云厂商slb 负载均衡原理
云厂商的SLB(Server Load Balancer)负载均衡原理主要是根据流量分发策略,将进入的流量按需分发到不同的后端服务器上。

这一过程主要涉及以下步骤:
1. 客户端发送请求至SLB负载均衡IP。

2. SLB根据负载均衡算法,选择一台合适的后端服务器,将请求转发至该服务器。

3. SLB会根据负载均衡算法,将请求均匀分配至后端服务器,确保每台服务器的负载均衡。

4. 后端服务器接收到请求并处理,然后将响应返回给SLB。

5. SLB再将响应返回给客户端。

通过这种方式,SLB可以有效地扩展应用系统的吞吐能力,并消除单点故障,提升系统的可用性。

同时,SLB还支持自定义访问控制策略,允许用户设置访问权限,保护敏感数据不被非法访问。

云厂商的SLB负载均衡可以根据不同场景分为不同的类型,如面向7层(http/https)的应用型负载均衡ALB,具备处理复杂业务路由能力,与云原生服务深度集成,支持http/https/http2/grpc等协议;兼顾4层和7层
的传统型负载均衡CLB,通过设置虚拟服务地址,将同一地域的多台云服务器虚拟成一个高性能和高可靠的后段服务池;以及其他类型的负载均衡器。

以上内容仅供参考,如需更多信息,建议查阅云厂商相关资料或咨询专业技术人员。

USB工作原理

USB工作原理

USB工作原理USB(Universal Serial Bus)是一种用于连接计算机和外部设备的通用串行总线接口标准。

它提供了一种简单、快速和可靠的数据传输方式,广泛应用于计算机、打印机、摄像头、键盘、鼠标等各种外部设备。

USB工作原理主要涉及以下几个方面:物理层、数据链路层、传输层和应用层。

1. 物理层:USB使用四根线缆进行数据传输,其中两根用于数据传输(D+和D-),一根用于电源供电(VCC),一根用于地线(GND)。

数据传输使用差分信号,可以有效反抗干扰,提高传输速率和可靠性。

2. 数据链路层:USB使用一种称为“8b/10b编码”的技术来进行数据传输。

该编码将8位数据转换为10位编码,提供了数据的同步和错误检测功能。

同时,USB还使用令牌传输和数据传输两种传输方式。

3. 传输层:USB支持多种传输方式,包括控制传输、中断传输、批量传输和等时传输。

控制传输用于设备初始化和配置,中断传输用于传输实时数据,批量传输用于大容量数据传输,等时传输用于对传输时间要求严格的数据传输。

4. 应用层:USB定义了一套标准的设备类别和协议,以便不同类型的设备可以在不同的操作系统上进行通信。

例如,USB定义了HID(Human Interface Device)类别,用于键盘、鼠标等输入设备,定义了MSC(Mass Storage Class)类别,用于存储设备等。

USB工作原理的核心是主从设备的通信。

计算机作为主设备,负责发送命令和控制数据传输,外部设备作为从设备,负责响应命令和传输数据。

USB使用“令牌-数据-握手-状态”四个阶段来完成数据传输。

1. 令牌阶段:主设备发送令牌包,用于指定传输的目标设备和传输类型。

令牌包包含同步字节、PID(Packet ID)和CRC(Cyclic Redundancy Check)校验位。

2. 数据阶段:主设备发送数据包或者接收数据包,用于传输实际的数据。

数据包包含同步字节、PID、数据和CRC校验位。

USB传输工作原理

USB传输工作原理

USB传输工作原理USB(Universal Serial Bus,通用串行总线)是一种广泛应用的计算机外部接口标准,广泛用于个人电脑及其外围设备之间的数据传输和通信。

本文旨在介绍USB传输的工作原理,从物理连接、数据传输、电源供应以及协议控制几个方面进行讲解。

一、物理连接USB传输的物理连接方式采用了一对差分信号线来传输数据,其中包括一个用于发送数据的正向差分信号线(D+)和一个用于接收数据的反向差分信号线(D-)。

这对差分信号线以双绞线的形式进行布线,以减少电磁干扰和信号失真的影响。

此外,USB接口还包括公共地线(GND)和电源线(Vcc),用于提供电源供应和信号屏蔽。

二、数据传输USB传输采用了主从设备的工作模式。

在数据传输过程中,主设备负责控制与调度,而从设备负责接受和响应主设备的指令。

USB传输支持两种模式:同步传输(Synchronous Transfer)和批量传输(Bulk Transfer)。

同步传输用于传输对实时性要求较高的数据,如音频和视频等,而批量传输适用于对实时要求较低的数据传输,如打印机的数据传输等。

数据传输过程分为三个阶段:令牌阶段、数据阶段和握手阶段。

令牌阶段由主设备发出令牌包,用于指定传输的方向和地址。

数据阶段用于实际的数据传输,其中包括数据包和错误检测码等信息。

握手阶段用于确认数据传输的成功与否,并进行必要的错误处理。

三、电源供应USB接口不仅可以传输数据,还可以为外部设备提供电源供应。

根据电源供应的要求,USB接口定义了四种不同的电源供应模式:总线供电模式、自供电模式、远程供电模式和混合供电模式。

总线供电模式中,主设备向从设备提供电源供应,常用于对功耗要求较低的设备。

自供电模式中,从设备自行提供电源供应,适用于对功耗要求较高的设备。

远程供电模式中,主设备向从设备提供电源供应,且从设备能够回馈部分电能,常见于USB充电设备。

混合供电模式则是上述模式的组合,灵活应用于各种不同的设备需求。

内存管理-slab[原理]

内存管理-slab[原理]

内存管理-slab[原理]前⾔主要讲解原理,基于2.6.32版本内核源码。

本⽂整体思路:先由简单内存模型逐渐演进到当下通⽤服务器⾯对的内存模型,讨论每⼀个内存模型下slab设计需要解决的问题。

历史简介linux内核运⾏需要动态分配内存,有两种分配⽅案:第⼀种:以页为单位分配内存,⼀次申请内存的长度必须是页的整数倍第⼆种:按需分配内存,⼀次申请内存的长度是随机的。

第⼀种分配⽅案通过buddy⼦系统实现,第⼆种分配⽅案通过slab⼦系统实现。

slab⼦系统随内核的发展衍⽣出slub⼦系统和slob⼦系统。

最新通⽤服务器内核⼀般默认使⽤slub⼦系统,slob⼦系统⼀般⽤在移动端和嵌⼊式系统,较⽼内核默认⽤slab。

slab,slob,slub功能相同,但效率上的偏重点不⼀样。

现下内核提供编译选项,供⽤户选择⽤三者中的哪⼀个。

slab⼦系统是内核使⽤的原始⽅案,经过相当长⼀段时间演进,因此本系列博客讲解slab⼦系统的实现。

充分理解slab后,理解slub和slob就很简单了。

slab和buddy的关系,以及slab存在的必要性让我们考察buddy⼦系统和slab⼦系统提供的接⼝函数:buddy⼦系统主要接⼝1//分配2的order次⽅个物理地址相邻的页⾯,返回第⼀个页的page描述符虚的拟地址2static inline struct page *alloc_pages(gfp_t gfp_mask, unsigned int order)3//释放2的order次⽅个物理地址相邻的页⾯,addr指向第⼀个页中第⼀个byte的虚拟地址4void free_pages(unsigned long addr, unsigned int order)slab⼦系统接⼝1/* 分配size字节⼤⼩的内存,返回这段内存的虚拟地址 */2static __always_inline void *kmalloc(size_t size, gfp_t flags)3/* 释放objp指向的⼀段内存 */4void kfree(const void *objp)两者之间的关系:slab⼦系统基于buddy⼦系统系统实现。

slb用法 -回复

slb用法 -回复

slb用法-回复SLB用法详解SLB(Server Load Balancer)是一种在现代计算机网络中广泛使用的负载均衡技术。

负载均衡是指在服务器集群中将请求均匀分发到各个服务器节点上,以提高系统的可扩展性、可靠性和性能。

在本文中,我们将详细介绍SLB的定义、原理、分类及使用方法。

一、SLB的定义SLB是一种通过软硬件组合实现的高可用、高性能和高稳定性的负载均衡解决方案。

它可以将流量在多个服务器间进行均衡分发,从而提高服务器资源的利用率,缩短用户对服务器的响应时间,确保系统的高可用性。

通过使用SLB,我们可以轻松实现流量分发、健康检查、故障切换等功能,使得服务器集群能够更好地应对大量请求的压力。

二、SLB的原理SLB的核心原理是将请求分发到多台服务器上,以提高服务器集群的整体性能。

其工作原理如下:1. 客户端向SLB发送请求。

2. SLB收到请求后,根据事先设置的分发策略,选择合适的服务器节点进行请求转发。

3. 选定的服务器节点接收到请求后,执行相应的处理逻辑,并将结果返回给SLB。

4. SLB再将结果返回给客户端。

三、SLB的分类根据负载均衡的实现方式和功能特点,SLB可以分为以下几类:1. 基于硬件的SLB:通过使用专用硬件设备(如F5、H3C等)来实现负载均衡功能。

硬件SLB具有高性能、高并发处理能力和丰富的负载均衡算法,但价格较高且配置较为复杂。

2. 基于软件的SLB:通过在普通服务器上部署负载均衡软件(如Nginx、HaProxy等)来实现负载均衡功能。

软件SLB具有灵活性高、成本较低的特点,但并发处理能力相对较弱。

3. 全局负载均衡(GSLB):用于将请求分发到不同的数据中心或地理位置的服务器上。

GSLB可以实现跨地域的负载均衡,提高系统的可靠性和容灾能力。

四、SLB的使用方法使用SLB可以分为以下几个步骤:1. 部署SLB:根据实际需求选择硬件SLB或软件SLB,并部署到服务器集群中。

bootloader工作原理

bootloader工作原理

bootloader工作原理Bootloader,也称为引导程序,是一种小型软件程序,旨在启动计算机系统并加载操作系统(OS)。

Bootloader的工作原理类似于人类的大脑和身体。

大脑(BIOS,UEFI)将发送指令控制器(芯片)的运转,并将指令传达给身体部分来执行。

这些身体部分包括磁盘,内存和其他外设。

因此,Bootloader的作用是确保操作系统在计算机启动时可以正常加载和运行。

对于x86计算机,Bootloader通常存储在主引导分区的MBR(主引导记录)中,它是硬盘上的第一个扇区。

MBR由446字节的Bootloader程序和64字节的分区表组成。

当计算机启动时,BIOS会读取MBR并将Bootloader程序加载到计算机内存中。

一旦加载到内存中,Bootloader会执行以下任务:1. 检测计算机硬件的配置及其能力(例如CPU类型,内存大小,外部设备等)以及给定的启动选项(例如启动设备,内核的位置等)2. 加载操作系统内核。

在内核加载之前,Bootloader需要在硬件上启用适当的模式来为内核提供访问硬件和操作系统服务的权限。

3. 将操作系统内核传递给内核自身的启动代码。

4. 配置启动参数并将控制转移给操作系统内核。

这意味着操作系统接管了计算机的控制权。

如果Bootloader错误或无法启动,则计算机将无法启动操作系统,从而使其失去使用价值。

尽管大多数现代操作系统具有自己的Bootloader,但很多嵌入式设备,例如路由器,IP电话和数字录音机等,仍然需要使用独立的Bootloader。

在这种情况下,Bootloader包括在开发板或FPGA中,通常由固件工程师编写。

这些独立的Bootloader可以进行自定义编程,与特定的硬件设备配合使用,并使系统具有更好的启动性能和更高的稳定性。

综上所述,Bootloader是启动计算机系统和加载操作系统的必要组件,它实现了在启动时对硬件进行配置和对操作系统进行加载的功能。

阿里云lbs 负载均衡 原理

阿里云lbs 负载均衡 原理

阿里云lbs 负载均衡原理阿里云LBS(Location-Based Service)负载均衡是一种将网络流量分发到多个服务器上的技术,以提高系统的可用性和性能。

它通过将用户流量分配到多个服务器上,从而实现负载均衡,以避免单个服务器的过载和故障。

阿里云LBS负载均衡的原理是基于分布式系统的思想,它由多个服务器节点组成,每个节点都具有相同的应用程序和数据。

当用户发送请求时,负载均衡器会根据一定的算法(如轮询、最小连接数等)将请求分发给服务器节点。

这样,每个服务器节点都可以处理一部分用户请求,从而实现负载均衡。

在阿里云LBS负载均衡中,有两个重要的概念:前端和后端。

前端是指用户请求的入口,可以是一个域名、一个IP地址或一个端口。

后端是指实际处理请求的服务器节点。

负载均衡器会将前端请求转发给后端服务器节点,并将响应结果返回给用户。

阿里云LBS负载均衡有多种算法可以选择,每种算法都有自己的优缺点。

常见的算法包括轮询、最小连接数、加权轮询和加权最小连接数。

轮询算法会按照顺序将请求发送给每个服务器节点,逐个循环。

最小连接数算法会将请求发送给当前连接数最少的服务器节点。

加权轮询和加权最小连接数算法会根据服务器节点的权重来分配请求。

阿里云LBS负载均衡还支持会话保持功能,即将同一用户的请求发送给同一服务器节点处理。

这样可以保证用户在同一个会话中的数据一致性,提高用户体验。

除了负载均衡外,阿里云LBS还提供了其他功能,如健康检查和故障切换。

健康检查功能可以定期检测服务器节点的健康状态,如果某个节点出现故障,负载均衡器会自动将请求转发给其他健康的节点。

故障切换功能可以及时发现服务器节点的故障,并将请求转发给备用节点,以提高系统的可用性。

总结来说,阿里云LBS负载均衡通过将用户请求分发到多个服务器节点上,实现了负载均衡,提高了系统的可用性和性能。

它采用多种算法来分配请求,并支持会话保持、健康检查和故障切换等功能,以提供更稳定和可靠的服务。

区分几种动态卷的工作原理

区分几种动态卷的工作原理

区分几种动态卷的工作原理动态卷是一种基于软件实现的存储技术,可以将多个磁盘组合成一个逻辑卷。

在操作系统层面上,动态卷可以对存储资源进行灵活管理,提供了更高的容错性、可用性和性能。

根据实现方式的不同,可以将动态卷的工作原理分为以下几种:1. 基本动态卷(Simple Dynamic Volume):基本动态卷是最简单的一种动态卷方式,它只使用一个物理磁盘或磁盘分区。

操作系统将该磁盘或磁盘分区直接映射为一个逻辑卷,不提供冗余或性能优化功能。

2. 跨区动态卷(Spanned Dynamic Volume):跨区动态卷通过将多个物理磁盘或磁盘分区组合在一起,形成一个大型逻辑卷。

数据会被分布存储在不同的物理磁盘上,从而提供更大的存储空间。

但是,跨区动态卷没有提供冗余功能,当一个磁盘故障时,整个卷的数据可能会丢失。

3. 镜像动态卷(Mirrored Dynamic Volume):镜像动态卷通过将数据复制到多个物理磁盘上,来提供冗余保护。

当一个磁盘故障时,可以使用镜像磁盘中的数据恢复卷的完整性。

镜像动态卷可以提供较高的数据可用性,但是需要更多的物理磁盘资源。

4. 条带化动态卷(Striped Dynamic Volume):条带化动态卷将数据分割成多个条带,并将每个条带写入到不同的物理磁盘上。

该方式可以提高数据读写性能,因为数据可以同时从多个磁盘上读取或写入。

然而,条带化动态卷没有提供冗余功能,当一个磁盘故障时,可能会导致整个卷的数据丢失。

5. 杂排动态卷(RAID5 Dynamic Volume):杂排动态卷是一种组合了镜像和条带化的动态卷方式。

它将数据条带化地写入到多个物理磁盘上,并通过添加冗余校验信息来实现数据的冗余保护。

当一个磁盘故障时,可以使用校验信息从其他磁盘中恢复丢失的数据。

杂排动态卷提供了较高的性能和冗余性。

这些动态卷方式可以根据实际需求进行选择和组合,以满足不同的存储需求,提供更高的性能、可用性和冗余保护。

slab算法原理(一)

slab算法原理(一)

slab算法原理(一)Slab算法:内存管理的高效选择1. Slab算法简介Slab算法是一种高效的内存管理算法,用于解决操作系统中的内存分配问题。

它通过将内存划分为不同大小的 slab(内存块),并维护不同大小的对象缓存,在内存分配和释放过程中提供了快速的性能。

2. Slab算法原理2.1 内存的划分Slab算法将内存划分为三个不同的区域:1.Slab:由连续的物理页面组成,用于存储对象的内存块。

2.Cache:由多个 Slab 组成,用于管理不同大小对象的内存分配。

3.Page:操作系统将物理内存按页面大小进行管理,每个页面包含多个 slab 或部分 slab。

2.2 对象的分配在使用Slab算法进行对象分配时,通过以下步骤实现:1.检查 Cache 中是否存在所需大小的 Slab,即检查是否有足够的内存供应。

2.如果存在所需大小的 Slab,从中分配一个自由的内存块给对象。

3.如果不存在所需大小的 Slab,则分配一个新的 Slab,并从中分配一个内存块给对象。

2.3 对象的释放在使用Slab算法进行对象释放时,通过以下步骤实现:1.找到对象所属的 Slab。

2.将对象标记为自由,表示该内存块可重新使用。

3.检查 Slab 中的所有内存块是否都为空,如果是,则释放该Slab。

3. Slab算法的优势3.1 快速对象分配和释放由于Slab算法预先分配了内存块,对象的分配和释放过程可以通过简单的指针操作进行。

这种预分配避免了频繁的内存管理操作,提高了分配和释放的速度。

3.2 高效的内存利用率Slab算法通过将相同大小的对象存储在相同的 Slab 中,避免了内存碎片的产生,提高了内存的利用率。

同时,当对象被释放时,内存块可以被重新利用,进一步提高了内存的利用效率。

3.3 减少内存分配的系统调用由于Slab算法预先分配了内存块,对象的分配过程不需要频繁地调用系统分配器。

这减少了系统调用的次数,降低了系统开销,提高了系统的性能。

slub中的kmalloc和kfree学习笔记

slub中的kmalloc和kfree学习笔记

slub中的kmalloc和kfree学习笔记2.6.26中的内存管理大概分为3个层次SLUB,伙伴系统和ZONE,其中SLUB在最高层,这里通过分析kmalloc和kfree来分析SLUB的模型,在内存管理中还有NUMA系统,但是NUMA不是必须得,所以以下笔记建立在无SMP和不使用NUMA的环境下,并且不运行DEBUG 设置SLUB主要对1页以下的内存进行管理,将1页内存分成相同大小的块,SLUB将这些块称为object,内核进行内存申请时则分配1个块,也就是1个object在x86下的32位处理器中,SLUB由13个缓冲结构组成,每个缓冲结构管理大小不同的object,其中0号归NUMA使用,其它12个按顺序分别为96,192,8,16,32,64,128,256,512,1024,2048,4096,如下图所示:举例来说,第5个缓冲结构管理object大小为16的页面,对于该缓冲来说,将1页内存按16的大小分成了256项,当内核申请1个大小为9-16大小的内存时,SLUB就根据第5个缓冲结构中的空闲object指针freelist取出1个object交给内核这里可以发现,申请大小为9时,返回16的大小,申请大小为15时,也返回16的大小,大家会认为如果申请的内存都在9到10大小左右徘徊的时候就会浪费大概50%的内存空间,对的,所以学习SLUB就更有必要了嘛,如果都在9-10大小的话就自己更改SLUB缓冲的结构,设置1个9-10大小的缓冲区,专门负责这些内存申请.避免浪费对每页内存进行分块,虽然在一定程度上浪费了内存,但是方便了内存的申请与回收,提高了效率,下面就对SLUB的这种管理进行分析首先是SLUB的缓冲结构kmalloc_caches[]数组的初始化,该初始化在kmem_cache_init中进行kmem_cache_init在/mm/slub.c中,代码如下:void __init kmem_cache_init(void){int i;int caches = 0;init_alloc_cpu();#ifdef CONFIG_NUMAcreate_kmalloc_cache(&kmalloc_caches[0],"kmem_cache_node",sizeof(struct kmem_cache_node), GFP_KERNEL);kmalloc_caches[0].refcount =-1;caches++;hotplug_memory_notifier(slab_memory_callback,SLAB_CALLBACK_PRI);#endifslab_state = PARTIAL;//如果kmalloc的最小object小于64//则初始化1号和2号kmalloc_caches的大小为96和192if(KMALLOC_MIN_SIZE <= 64){create_kmalloc_cache(&kmalloc_caches[1],"kmalloc-96", 96, GFP_KERNEL);caches++;create_kmalloc_cache(&kmalloc_caches[2],"kmalloc-192", 192, GFP_KERNEL);caches++;}//按照kmalloc的最小object初始化kmalloc_cachesfor(i = KMALLOC_SHIFT_LOW; i <= PAGE_SHIFT; i++){create_kmalloc_cache(&kmalloc_caches[i],"kmalloc", 1 << i, GFP_KERNEL);caches++;}BUILD_BUG_ON(KMALLOC_MIN_SIZE > 256 ||(KMALLOC_MIN_SIZE &(KMALLOC_MIN_SIZE - 1)));//按照kmalloc的最小object重新设置size_indexfor(i = 8; i < KMALLOC_MIN_SIZE; i += 8)size_index[(i - 1)/ 8]= KMALLOC_SHIFT_LOW;if(KMALLOC_MIN_SIZE == 128){for(i = 128 + 8; i <= 192; i += 8)size_index[(i - 1)/ 8]= 8;}slab_state = UP;//按照kmalloc的最小object重新设置kmalloc_caches的名字for(i = KMALLOC_SHIFT_LOW; i <= PAGE_SHIFT; i++)kmalloc_caches[i]. name =kasprintf(GFP_KERNEL,"kmalloc-%d", 1 <<i);#ifdef CONFIG_SMPregister_cpu_notifier(&slab_notifier);kmem_size =offsetof(struct kmem_cache, cpu_slab)+nr_cpu_ids *sizeof(struct kmem_cache_cpu *);#elsekmem_size =sizeof(struct kmem_cache);#endifprintk(KERN_INFO"SLUB: Genslabs=%d, HWalign=%d, Order=%d-%d, MinObjects=%d,"" CPUs=%d, Nodes=%d\n",caches, cache_line_size(),slub_min_order,slub_max_order,slub_min_objects,nr_cpu_ids, nr_node_ids);}由于不使用NUMA系统,所以这里不会执行#ifdef CONFIG_NUMA中的代码,也就不会初始化0号缓冲所有缓冲结构的初始化都是由create_kmalloc_cache负责create_kmalloc_cache在/mm/slub.c中,代码如下:const char*name,int size, gfp_t gfp_flags){unsigned int flags = 0;//检测是否为DMA缓冲结构if(gfp_flags & SLUB_DMA)//是则加上DMA标志flags = SLAB_CACHE_DMA;down_write(&slub_lock);//分配一个缓冲if(!kmem_cache_open(s,gfp_flags,name,size, ARCH_KMALLOC_MINALIGN,flags,NULL))goto panic;//将该缓冲挂载到slab_caches链表中list_add(&s->list,&slab_caches);up_write(&slub_lock);if(sysfs_slab_add(s))goto panic;return s;panic:panic("Creation of kmalloc slab %s size=%d failed.\n", name, size);}主要的初始化在kmem_cache_open中进行kmem_cache_open在/mm/slub.c中,代码如下:static int kmem_cache_open(struct kmem_cache *s, gfp_t gfpflags,const char*name,size_t size,size_t align,unsigned long flags,void(*ctor)(struct kmem_cache *,void*)){//初始化kmem缓冲,将内容全部清零memset(s, 0, kmem_size);//设置缓冲的名字s->name = name;//设置缓冲的object初始化函数s->ctor = ctor;//设置缓冲的object大小s->objsize = size;//设置缓冲的对齐s->align = align;//设置缓冲的标志s->flags = kmem_cache_flags(size, flags, name, ctor);//根据object的大小计算对应的object数目if(!calculate_sizes(s,-1))goto error;s->refcount = 1;#ifdef CONFIG_NUMAs->remote_node_defrag_ratio = 100;#endif//初始化邻居页面链表calculate_sizes负责计算object的大小,就是对kmem_cache结构中oo,max,min成员的赋值,以及对object大小进行边界和字对齐,但是对边界和字对齐还不熟悉,所以我就不分析了 = 3=接下来是init_kmem_cache_nodes, init_kmem_cache_nodes负责对邻居页面链表进行初始化init_kmem_cache_nodes在/mm/slub.c中,由于这里不使用NUMA系统,所以代码如下:init_kmem_cache_node在mm/slub.c中,代码如下:主要进行了一下初始化工作回到kmem_cache_open中,现在到alloc_kmem_cache_cpus, alloc_kmem_cache_cpus负责CPU私有缓冲的初始化工作alloc_kmem_cache_cpus在mm/slub.c中,由于不使用SMP,所以代码如下:初始化完成后, kmem_cache_open和create_kmalloc_cache也执行完了,返回到kmem_cache_init中,接下来kmem_cache_init主要执行缓冲名字的设置工作下图是第6个缓冲结构,也就是object大小为32的缓冲初始化后的结构图kmem_cache_init执行完成后,SLUB的初始化就完成了,就接下来我们就能使用kmalloc进行内存的分配了假设kmalloc申请的大小为32,标志为GFP_KKERNEL,GFP_KERNEL是标志_GFP_WAIT , _GFP_IO 和_GFP_FS的集合,也就是kmalloc(32,GFP_KERNEL)下面就进入到kmalloc的分析中kmalloc在/mm/slub.c中,代码如下:{//也就是检测size是变量还是常量//为常量则执行ifif(__builtin_constant_p(size)){//检测申请的大小是否超过1页内存的大小if(size > PAGE_SIZE)//调用大块内存分配return kmalloc_large(size, flags);//检测申请的内存是否用于DMAif(!(flags & SLUB_DMA)){//根据申请的大小选取对应的缓冲结构struct kmem_cache *s = kmalloc_slab(size);//检测kmem缓冲取得是否成功if(!s)return ZERO_SIZE_PTR;//使用缓冲结构取得内存return kmem_cache_alloc(s, flags);}}//变量及DMA使用__kmalloc分配内存return __kmalloc(size, flags);}__builtin_constant_p检测参数是变量还是常量,举个例子说kmalloc(i,GFP_KERNEL)就是变量,kmalloc(32,GFP_KERNEL)就是常量这里先看常量,进入if中,这里先说一下kmalloc_large, kmalloc_large负责超过1页内存的申请,超过1页的内存分配由伙伴系统进行,不由SLUB进行.接下来到if (!(flags & SLUB_DMA)),这里我们申请的内存标志为GFP_KERNEL,没有DMA标志,所以进入到if中首先根据申请的大小选取对应的缓冲序号,进入到kmalloc_slab中kmalloc_slab在include /linux/slub_def.h中,代码如下:kmalloc_index在include /linux/slub_def.h中,代码如下:return 0;//检测大小是否小于kmalloc的最小objectif(size <= KMALLOC_MIN_SIZE)//小于则返回最小object的对数return KMALLOC_SHIFT_LOW;//检测kmalloc的最小object是否小于64#if KMALLOC_MIN_SIZE <= 64//大于64而小于96则使用1号kmemif(size > 64 && size <= 96)return 1;//大于128而小于192则使用2号kmemif(size > 128 && size <= 192)return 2;#endif//以下根据大小的不同,返回对应的kmem缓冲号if(size <= 8)return 3;if(size <= 16)return 4;if(size <= 32)return 5;if(size <= 64)return 6;if(size <= 128)return 7;if(size <= 256)return 8;if(size <= 512)return 9;if(size <= 1024)return 10;if(size <= 2 * 1024)return 11;if(size <= 4 * 1024)return 12;得到缓冲结构后,就来到了kmem_cache_alloc中kmem_cache_alloc在mm/slub.c中简单的调用, __builtin_return_address产生的值用于DEBUG,这里我们并不会使用到,继续来到slab_alloc中slab_alloc在mm/slub.c中,代码如下:{void**object;struct kmem_cache_cpu *c;unsigned long flags;unsigned int objsize;//保存并关闭中断local_irq_save(flags);//取得kmem缓冲中对应当前CPU序号的私有kmem缓冲c = get_cpu_slab(s, smp_processor_id());//取得缓冲中object的大小objsize = c->objsize;//检测CPU的私有kmem缓冲的空闲object指针是否为空if(unlikely(!c->freelist ||!node_match(c, node)))//为空则新申请1块页面object =__slab_alloc(s,gfpflags,node,addr, c);//不为空则使用object指针所指的objectelse{//取得空闲的objectobject = c->freelist;//object指针指向下1个空闲的objectc->freelist = object[c->offset];//设置ALLOC_FASTPATH状态计数器加1get_cpu_slab负责取得CPU的私有kmem缓冲get_cpu_slab在mm/slub.c中,代码如下由于不使用SMP,所以这里很简单,返回缓冲结构中的CPU私有缓冲结构接下来到node_match , node_match在mm/slub.c中,代码如下因为这时候是第1次调用kmalloc,所以CPU的私有kmem缓冲中的freelist指针为空所以我们进入到__slab_alloc中__slab_alloc在mm/slub.c中,代码如下:if(unlikely(!node_match(c, node)))goto another_slab;stat(c, ALLOC_REFILL);load_freelist://取得页面的空闲object指针object = c->page->freelist;//检测空闲object是否为空if(unlikely(!object))//为空则使用别的goto another_slab;if(unlikely(SlabDebug(c->page)))goto debug;//CPU的私有缓冲的object指针指向下1个空闲的objectc->freelist = object[c->offset];//设置页面的使用计数器为页面的object数目c->page->inuse = c->page->objects;//设置页面的空闲object指针为空c->page->freelist =NULL;c->node = page_to_nid(c->page);unlock_out://解除页面的锁slab_unlock(c->page);stat(c, ALLOC_SLOWPATH);return object;another_slab:deactivate_slab(s, c);new_slab://检测是否有邻居页面new= get_partial(s, gfpflags, node);//检测邻居页面取得是否成功if(new){//连接邻居页面到CPU得私有kmem缓冲上c->page =new;//ALLOC_FROM_PARTIAL状态计数器加1stat(c, ALLOC_FROM_PARTIAL);//跳转到load_freelistgoto load_freelist;}//检测是否可以中断,可以则打开IRQif(gfpflags & __GFP_WAIT)local_irq_enable();//取得1块新的页面new= new_slab(s, gfpflags, node);//关闭IRQif(gfpflags & __GFP_WAIT)local_irq_disable();//检测取得页面是否成功if(new){//取得当前CPU的私有kmem缓冲c = get_cpu_slab(s, smp_processor_id());//ALLOC_SLAB状态计数器加1stat(c, ALLOC_SLAB);//检测当前CPU的私有kmem缓冲的页面是否为空if(c->page)//释放该页面flush_slab(s, c);//为将要操作的页面上锁slab_lock(new);//设置页面属性,设置PG_active属性SetSlabFrozen(new);//连接该页面到CPU的私有kmem缓冲c->page =new;goto load_freelist;}return NULL;debug:if(!alloc_debug_processing(s, c->page, object, addr))goto another_slab;c->page->inuse++;c->page->freelist = object[c->offset];c->node =-1;goto unlock_out;}这时候CPU的私有kmem缓冲中的页面还为空,所以我们来到了new_slab标号处这里首先检测是否有邻居页面,刚初始化完出来,还没邻居呢,所以会返回空,以后我们再来分析有邻居的时候是如何分配的呢么就来到new_slabnew_slab在/mm/slub.c中,代码如下:static struct page *new_slab(struct kmem_cache *s, gfp_t flags,int node){struct page *page;void*start;void*last;void*p;BUG_ON(flags & GFP_SLAB_BUG_MASK);//取得1块新的页面page = allocate_slab(s,flags &(GFP_RECLAIM_MASK | GFP_CONSTRAINT_MASK), node);//检测取得页面是否成功if(!page)goto out;inc_slabs_node(s, page_to_nid(page), page->objects);//连接缓冲结构到该页面page->slab = s;//设置页面的slab属性page->flags |= 1 << PG_slab;if(s->flags &(SLAB_DEBUG_FREE |SLAB_RED_ZONE | SLAB_POISON |SLAB_STORE_USER | SLAB_TRACE))SetSlabDebug(page);//取得页面的起始地址start = page_address(page);if(unlikely(s->flags & SLAB_POISON))memset(start,POISON_INUSE,PAGE_SIZE << compound_order(page));//下面进行页面的object设置//首先取得页面的起始地址last = start;//按照object的大小将页面分成对应的块数//历遍块数大小//p指向页面的起始地址,每次自增object的大小for_each_object(p, s, start, page->objects){//使用缓冲的ctor函数对object进行初始化setup_object(s, page, last);//设置last所指的内容为p所指向的地址//也就是将所有object连接成1个单向链表set_freepointer(s, last, p);//设置last为plast = p;allocate_slab取得一个空的页面,并进行一下初始化,主要是将page->objects设成了缓冲成员oo中的x,这里也就是128,因为涉及到kmem_cache结构中oo成员,这个成员和边界对齐有些关系,我对边界对齐还不熟悉,就暂时不分析这个函数,不过并不会影响到下面的分析下面主要分析SLUB对页面object的初始化,也就是如何将页面分成1个个的objectfor_each_object是一个宏,在mm/slub.c中,代码如下:setup_objec在mm/slub.c中,代码如下:什么都没执行,所以这相等于一个空函数set_freepointer在mm/slub.c中,代码如下:呢么展开这几个函数,就是下列代码再将缓冲结构中的数值代入,得出这里也是SLUB最主要的部分,我们用图来说明,首先先看一下逻辑上的视图这其实连接成了1个单向链表,用链表的视角来看的话如下然后我们假设页面的起始地址为0x0000,呢么该页面的内存视图如下初始化完成后将页面的空闲object指针指向第1个object,如下然后返回到__slab_alloc中,现在跳转到标号load_freelist处首先将当前page->freelist的值赋给了将要返回的指针然后将CPU的私有kmem缓冲中的freelist,也就是空闲object 指针指向了下一项,如下将空闲object指针指向下一项的代码为c->freelist = object[c->offset] 由于c->offset为0,所以这里为c->freelist = object[0],这句代码困惑了我很久,多亏了chinaunix的dreamice和fera的提示,才顺利解决这句代码主要就是提取object指针所指的内容,object[0]也就是提取偏移为0的内容,这里object指向了第一项object,呢么object[0]就是第一项object中的下一项object地址,也就是相当于读取了一个链表节点的next节点然后将页面的freelist指针设为NULL我认为这里设为NULL的意思也就是该页面所有的项都由SLUB来管理,所以页面没有空余的项然后返回到slab_alloc中,根据__GFP_ZERO标志来判断是否需要将得到的object进行清零,然后再返回object的地址到这里kmalloc的操作就完成了现在回头看看是变量或者DMA的情况下如何进行的这种情况下会进入__kmalloc中__kmalloc在mm/slub.c中,代码如下首先进到get_slab中get_slab在mm/slub.c中,代码如下:{int index;//检测大小是否小于192if(size <= 192){//大小为0或者NULL则返回(void *)16if(!size)return ZERO_SIZE_PTR;//取得对应的kmem序号index = size_index[(size - 1)/ 8];}else//将大小转化为2进制,取得最后1位的位置index = fls(size - 1);#ifdef CONFIG_ZONE_DMAif(unlikely((flags & SLUB_DMA)))return dma_kmalloc_cache(index, flags);#endif//返回对应序号的kmem缓冲return&kmalloc_caches[index];}然后执行slab_alloc, slab_alloc在之前已经分析过了,这里就不再复述了以上只说明了第1种分配方法,根据程序的走向,kmalloc一共有4种分配方法:1. 页面为空2. 页面未满3. 页面已满4. 邻居页面未满下面分析先分析第2和第3种分配方法首先是第2种,假设还是使用kmalloc(32,GFP_KERNEL),呢么第6个缓冲结构进行第二次分配工作一路来到slab_alloc中,这次不会进入__slab_alloc了,因为这时c->freelist并不为空,它指向了页面的第二个object,然后执行下列代码: //取得空闲的objectobject = c->freelist;//object指针指向下1个空闲的objectc->freelist = object[c->offset];执行完成后的视图如下:c->freelist指向了第3个object,这里需要注意的是第1项,也就是最早分配的object,他的下一项空闲object指针也许被冲掉了,主要有2个原因,1是标志ZERO,将这个object初始化为0,2是程序的读写将指针改写了,所以如果使用kmalloc申请小于1页的内存时不使用GFP_ZERO标记,然后马上对得到的内存进行读取,呢么就能得到下一项空闲object的地址第2种分配方法一直会持续到c->freelist指向最后一项,也就是NULL,这个时候第3种分配方法就要执行了还是来到slab_alloc中,这个时候c->freelist为NULL,进入到__slab_alloc中由于这个时候CPU的私有kmem缓冲中的页面并不为空,但是页面的freelist指针为空,所以会执行if (unlikely(!object))//为空则使用别的goto another_slab;跳转到标号another_slab处执行标号another_slab处只有一个deactivate_slab函数deactivate_slab在mm/slub.c中,代码如下:static void deactivate_slab(struct kmem_cache *s,struct kmem_cache_cpu *c){struct page *page = c->page;int tail = 1;if(page->freelist)stat(c, DEACTIVATE_REMOTE_FREES);//检测object是否已经使用完了while(unlikely(c->freelist)){void**object;tail =0;/* Hot objects. Put the slab first *//* Retrieve object from cpu_freelist */object = c->freelist;c->freelist = c->freelist[c->offset];/* And put onto the regular freelist */object[c->offset]= page->freelist;page->freelist = object;page->inuse--;}由于这时c->freelist为NULL,所以不会执行while中的内容,来到unfreeze_slab中unfreeze_slab在mm/slub.c中,代码如下:static void unfreeze_slab(struct kmem_cache *s,struct page *page,int tail){struct kmem_cache_node *n =get_node(s, page_to_nid(page));struct kmem_cache_cpu *c =get_cpu_slab(s, smp_processor_id());//清除页面的PG_active属性ClearSlabFrozen(page);//检测页面的使用计数器if(page->inuse){//检测页面的空闲object指针是否为空if(page->freelist){//不为空则添加到邻居页面链表中add_partial(n, page, tail);stat(c,tail ?DEACTIVATE_TO_TAIL :DEACTIVATE_TO_HEAD);}else{stat(c, DEACTIVATE_FULL);if(SlabDebug(page)&&(s->flags & SLAB_STORE_USER))add_full(n, page);}slab_unlock(page);}else{stat(c, DEACTIVATE_EMPTY);//检测缓冲中的邻居页面计数器是否达到了最小值if(n->nr_partial < MIN_PARTIAL){//加入到邻居页面链表中add_partial(n, page, 1);slab_unlock(page);}else{slab_unlock(page);stat(get_cpu_slab(s,freelist为NULL,所以进入到else中else中主要执行了状态计数器的增加和DEBUG测试,并没有什么实质性的工作,然后就退出了回到__slab_alloc中,又来到了new_slab,这个时候邻居页面链表还是为空,所以又执行了1次第1种分配方法,分配了1个新的页面接下来先分析kfree,然后再看第4种分配方法kfree负责回收使用的内存,kfree在mm/slub.c中,代码如下:这里假设使用kfree回收的地址的页面结构属于SLUB管理的页面,也就是具有pageslab属性,不会进入到if中__builtin_return_address产生的值用于DEBUG,这里我们并不会使用到然后进入到slab_free中slab_free在mm/slub.c中,代码如下如果为当前页面,假设c->freelist指向第3项object,我们所要回收的是第1项object,呢么视图如下:这里主要将设置object所指的object中的空闲object指针指向c->freelist,然后再将c->freelist指向object,指向完毕后的视图如下: 当不为当前页面的时候,则进入到__slab_free中__slab_free在mm/slub.c中,代码如下:void*x,void*addr,unsigned int offset){void*prior;void**object =(void*)x;struct kmem_cache_cpu *c;//取得当前CPU的kmem缓冲c = get_cpu_slab(s, raw_smp_processor_id());stat(c, FREE_SLOWPATH);//将页面上锁slab_lock(page);if(unlikely(SlabDebug(page)))goto debug;checks_ok://将object的下一空闲object指针指向页面的下一空闲object//并且将页面的下一空闲object保存在priorprior = object[offset]= page->freelist;//将页面的下一空闲object指针指向当前objectpage->freelist = object;//减少页面的使用计数器page->inuse--;//检测页面是否有PG_activeif(unlikely(SlabFrozen(page))){stat(c, FREE_FROZEN);goto out_unlock;}//检测页面的使用计数器是否为0if(unlikely(!page->inuse))goto slab_empty;//检测页面原来的下一空闲object指针是否为NULLif(unlikely(!prior)){//将该页面添加到缓冲的邻居页面中add_partial(get_node(s,page_to_nid(page)), page, 1);stat(c, FREE_ADD_PARTIAL);}out_unlock:slab_unlock(page);return;slab_empty://检测页面原来的下一空闲object指针是否为NULLif(prior){//从邻居页面链表中移除该页面remove_partial(s, page);stat(c, FREE_REMOVE_PARTIAL);}__slab_free首先进行再连接过程,就如上面为当前页面差不多,然后有两种选择,1种是加入到邻居页面链表中,另1种是释放该页面先看加入到邻居页面链表中当检测使用计数器不为0,并且原下一空闲object指针为NULL的时候(不为NULL说明已经加入到邻居页面链表中了,不需要再加1次),就会执行add_partial不过首先先看get_nodeget_node在/mm/slub.c中,代码如下:由于我们不使用NUMA,所以不论node的结果如何,get_node都返回&s->local_node然后到add_partial,add_partial在mm/slub.c中,代码如下连接完成后的结构图如下:然后看释放该页面如果使用计数器为0则跳转到标号slab_empty处首先检测是否在邻居页面链表中,如果在则执行remove_partial函数remove_partial在mm/slub.c中,代码如下:简单的将页面移除并减少邻居页面计数器最后执行discard_slab释放页面,由于discard_slab和伙伴系统牵涉较深,等之后的伙伴系统学习笔记再分析吧 = 3=好,现在邻居页面链表中有存货了~ 我们看看第4种分配方法当第2种分配方法一直持续到c->freelist指向最后一项,也就是NULL,并且邻居页面链表中有存货的时候,就会进入到第4种分配方法第4种分配方法其实属于第3种方法的分支,当第3种方法进入到标号new_slab处时,进入get_partial从邻居页面链表中取得页面成功就为第4种分配方法现在进入get_partial函数中get_partial在mm/slub.c中,代码如下:get_node在之前已经分析过了,他会返回&s->local_node; 然后到get_partial_node中get_partial_node在mm/slub.c中,代码如下主要就是历遍partial链表寻找对应的页面,视图如下:红线是prev,蓝线是next, partial以next为顺序进行历遍,因为最后1个page是最后加入的然后执行lock_and_freeze_slablock_and_freeze_slab在mm/slub.c中,代码如下如果页面锁定属性为0则锁定并返回操作成功如果页面锁定属性已经为1,则不能操作该页面,返回0表示失败get_partial返回页面后跳转到load_freelist处,接下来的执行就和之前的几种方法一样了= 3= 笔记就到此结束了在这次分析中心中还是有不少疑问的,像page中的inuse属性,这个属性目前分析是只在初始化中复制,只有每次kfree的时候减一,而从不自增,如果一个页面一直减一,但其内容一直为满的话,如果最后inuse 属性为0的时候,不就把页面所有的内容都释放掉了,呢正在使用中的object也释放掉了,呢么不就导致内存同步错误了还有分析过程中的一些函数不能理解是什么时候才调用的看来光有理论还不行啊~ 还需要多实践才能搞明白 T 3T希望大家喜欢~ = 3=)/。

slb原理

slb原理

slb原理SLB原理。

SLB(Server Load Balancing)是一种用于分发网络流量、提高服务器性能和可用性的技术。

它通过将流量分发到多台服务器上,从而实现了负载均衡,提高了系统的整体性能和可靠性。

SLB原理是如何实现的呢?下面我们将详细介绍SLB的原理和工作方式。

首先,SLB通过一组负载均衡器(Load Balancer)来实现流量的分发。

负载均衡器可以是硬件设备,也可以是软件实现。

它会根据预先设定的算法,将流量分发到多台服务器上。

这些算法可以是轮询、最小连接数、最少负载等,根据实际情况选择合适的算法来实现负载均衡。

其次,负载均衡器会监控服务器的健康状态,当某台服务器出现故障或不可用时,负载均衡器会自动将流量重新分发到其他健康的服务器上,从而保证系统的可用性。

这种自动的故障转移能力是SLB的重要特点之一,可以有效地避免单点故障对系统造成的影响。

另外,SLB还可以实现会话保持(Session Persistence),确保用户的请求在整个会话期间都被分发到同一台服务器上。

这对于一些需要保持状态的应用(如在线游戏、电子商务网站等)非常重要,可以避免用户在不同服务器之间切换导致的状态丢失问题。

此外,SLB还可以实现内容分发网络(CDN)功能,通过缓存静态内容、压缩数据等方式来加速用户对网站的访问。

负载均衡器可以根据用户的地理位置、网络状况等因素,将用户的请求分发到最近的服务器上,从而提高访问速度和用户体验。

总的来说,SLB通过负载均衡器的分发算法、健康状态监控、会话保持和CDN等功能,实现了对服务器流量的智能分发和管理,提高了系统的性能、可用性和安全性。

它已经成为现代互联网架构中不可或缺的一部分,为用户提供了更快、更稳定的在线体验。

以上就是关于SLB原理的详细介绍,希望能对您有所帮助。

如果您对SLB还有其他疑问或需要进一步了解,欢迎随时与我们联系。

感谢阅读!。

slb转发规则-概述说明以及解释

slb转发规则-概述说明以及解释

slb转发规则-概述说明以及解释1.引言1.1 概述在计算机网络中,负载均衡是指将网络请求均匀地分发到多个服务器上,以实现资源的合理利用和提高系统的可用性和性能。

而SLB(Server Load Balancer)作为一种常见的负载均衡设备,起着至关重要的作用。

SLB转发规则是指在SLB设备上配置的一系列规则,用于决定网络请求应该转发到哪个服务器上。

这些转发规则可以基于多种因素进行,如IP 地址、端口号、会话状态等。

通过灵活配置这些规则,可以实现灵活的请求转发和负载均衡策略,以满足不同应用场景的需求。

本文将深入探讨SLB转发规则的重要性及其在网络应用中的作用。

通过理解和掌握SLB转发规则的相关知识,可以更好地使用和配置SLB设备,提高网络的可靠性和性能。

同时,我们还将展望SLB转发规则的发展方向,探讨可能的改进和创新,以应对不断变化的网络需求和技术挑战。

接下来,我们将首先介绍SLB的定义和作用,了解其在负载均衡领域的地位和作用。

然后,重点讨论SLB转发规则的重要性,探究其在负载均衡策略中的关键作用和影响。

最后,通过对SLB转发规则的总结和展望,对未来SLB技术的发展方向进行展望,以期为读者提供有价值的参考和指导。

通过本文的阅读,读者将能够全面了解SLB转发规则的概念、重要性和作用,为自身在网络应用中的实践提供指导和启发。

现在,让我们深入探索SLB转发规则的奥秘吧!1.2 文章结构文章结构是指文章整体的框架和组织方式。

一个良好的文章结构能够使读者更好地理解文章的内容,并能够有条理地阐述观点。

在本文中,我们将讨论SLB转发规则,因此文章结构应包括以下几个部分:引言、正文和结论。

引言部分主要介绍文章的背景和重要性。

我们将在本节中概述SLB的定义及其作用,以及本文将要探讨的SLB转发规则的重要性。

正文部分是文章的主体,我们将深入探讨SLB转发规则。

在本节中,我们将首先介绍SLB的定义和作用,以便读者可以对SLB有一个基本的了解。

l-bus工作原理

l-bus工作原理

l-bus工作原理L-Bus工作原理L-Bus(Local-Bus)是一种局域总线,广泛应用于工业自动化、机器人控制、自动化仪器等领域。

它是一种串行通信总线,用于连接各种设备和模块,实现数据的传输和控制。

L-Bus的工作原理基于主从架构,其中包括一个主站和多个从站。

主站负责发送指令和接收数据,从站负责接收指令和发送数据。

主站和从站之间通过L-Bus进行通信。

L-Bus使用差分信号传输数据,其中包括正向信号和负向信号。

正向信号和负向信号的电平差异表示二进制数据的0和1。

这种差分信号传输方式具有抗干扰能力强、传输距离远等优点,适用于工业环境中的噪声和干扰较大的场景。

L-Bus采用主机轮询的方式进行通信。

主站按照一定的时间间隔轮询各个从站,发送指令并接收数据。

从站在接收到指令后,根据指令内容执行相应的操作,并将执行结果发送给主站。

主站根据从站的响应情况,决定是否继续轮询下一个从站。

L-Bus的通信速率可以根据具体的应用需求进行调整。

通常情况下,L-Bus的通信速率较低,一般在几千位每秒到几十万位每秒之间。

这种较低的通信速率可以确保通信的可靠性和稳定性,避免数据传输过程中的错误和丢失。

除了基本的数据传输功能,L-Bus还支持多种通信方式,如广播通信、单点通信和多点通信。

广播通信是指主站向所有从站发送相同的指令,适用于需要同时控制多个设备的场景。

单点通信是指主站与某个指定的从站之间进行通信,适用于只需要与某个特定设备进行交互的场景。

多点通信是指主站与多个从站之间进行独立的通信,适用于需要与多个设备同时进行交互的场景。

总结起来,L-Bus是一种基于串行通信的局域总线,采用差分信号传输数据。

它具有抗干扰能力强、通信稳定可靠的特点。

通过主从架构和主机轮询的方式实现数据的传输和控制。

除了基本的数据传输功能,还支持广播通信、单点通信和多点通信等多种通信方式。

L-Bus在工业自动化、机器人控制等领域发挥着重要的作用,为各种设备和模块之间的通信提供了可靠的解决方案。

lsusb 原理

lsusb 原理

lsusb 原理
lsusb 原理:
lsusb是Linux系统中的一个命令行工具,用于列出系统中连接的USB设备信息。

它通过读取系统中的USB设备文件,从而得到设备的相关信息。

lsusb在执行时,会扫描/sys/bus/usb/devices/目录下的所有USB设备节点文件。

每个USB设备都有一个唯一的节点文件,其中包含了设备的厂商ID、产品ID、
设备类型、设备接口等信息。

lsusb命令输出的结果包含了几个重要的信息:
1. Bus号和设备号:每个USB设备都与主机通过USB总线进行连接,每个总
线上有多个设备。

Bus号表示设备所在的USB总线号,设备号表示设备在该总线
上的编号。

2. 设备的厂商ID和产品ID:厂商ID由USB论坛分配给设备制造商,用于唯
一标识设备制造商;产品ID由设备制造商分配给设备型号,用于唯一标识设备型号。

3. 设备类型和设备接口:设备类型表示USB设备的功能类型,例如存储设备、音频设备等;设备接口表示设备所支持的USB接口类型。

通过lsusb命令,我们可以快速了解系统中连接的USB设备的基本信息。

对于
开发人员和系统管理员来说,lsusb命令是一个非常有用的工具,可以帮助他们诊
断USB设备的连接问题、查找特定设备的详细信息,以及进行设备的管理和配置。

总结起来,lsusb命令使用简单,通过读取USB设备文件得到设备的相关信息。

它可以帮助用户快速了解系统中连接的USB设备的基本信息,为故障排除和设备
管理提供便利。

b s架构的工作原理

b s架构的工作原理

b s架构的工作原理
B/S架构(Browser/Server架构)是一种基于浏览器和服务器之间的交互模式,它的工作原理可以分为以下几个步骤:
1. 用户在浏览器(Client)上输入网址或点击链接,发送HTTP请求到服务器。

2. 服务器(Server)接收到请求后,根据请求的信息进行处理和分析,比如请求的页面、数据等。

3. 服务器根据处理结果生成HTML、CSS、JavaScript等前端代码,构建成一个完整的网页,并将生成的网页作为响应返回给浏览器。

4. 浏览器接收到服务器响应后,解析HTML结构,并请求加载其中包含的CSS、JavaScript等静态资源。

5. 浏览器根据解析到的HTML、CSS、JavaScript等代码,渲染页面,呈现给用户。

6. 当用户与页面进行交互时,浏览器会执行JavaScript脚本,与服务器进行异步请求,发送表单数据或获取页面数据。

7. 服务器接收到浏览器发送的请求,进行处理和分析,比如处理表单数据,查询数据库等。

8. 服务器将处理结果生成的数据或页面,作为响应返回给浏览
器。

9. 浏览器接收到服务器响应后,根据响应的内容进行更新,例如更新页面内容、显示数据等。

这样,B/S架构通过浏览器和服务器之间的交互,实现了客户
端/服务器端的分工,将前端负责用户界面显示、交互逻辑,
后端负责数据处理、业务逻辑。

这样的架构能够提高系统的可维护性、跨平台性,并且能够方便地实现多用户同时访问系统。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Overall structure
UMA, SMP
per cpu name size align … cpu0 cpu1
cpu2
cpu3
kmem_cache
kmem_cache_cpu per node
kmem_cache
kmem_cache
node0 kmem_cache_node
kmem_cache
struct page
Per cpu structure
free objects from slab1
freelist
tid cpu slab partial slabs kmem_cache_cpu slab2
slab1
slab3
free object
slab
Allocation: fast-path
• limit
– size less than page size
What is the SLAB allocator?
• The SLAB allocator
– in-kernel library like in-userspace library malloc() – kmalloc() = malloc() – kmem_cache_create(), kmem_cache_alloc(), …
acquire freelist of slab
read freelist, counter of slab insert object into freelist of slab read freelist, counter of slab
attach one object(A)
acquire freelist cmpxchg_double_slab: new freelist(NULL), new counter retry fail allocation path no need “lock” cmpxchg_double_slab: new freelist(A), new counter success free path
return this object
freelist
tid cpu slab partial slabs kmem_cache_cpu slab
slab
slab
free object
slab
Allocation: slow-path
freelist
tid cpu slab partial slabs kmem_cache_cpu slab 2 4
How does the SLUB allocator work
Joonsoo Kim LGE CTO SWP Lab. iamjoonsoo.kim@ js1304@
Contents
• • • • Memory allocation hierarchy Implementation – the SLUB Difference between the SLAB and the SLUB Current status
freelist
tid cpu slab partial slabs kmem_cache_cpu slab2
slab1
slab3
free object
slab
Free: slow-path
cpu0 cpu1
case 1. remote cpu slab slab
slab add a slab to cpu partial list
return from interrupt
this_cpu_cmpxchg_double: new freelist(B),new tid
return object(A)
no need “irq disable”
Performance optimization: freelist of a slab
• • • • • kmalloc alignment fallback order slab kmem_cache alignment debugging feature NUMA
CURRENT STATUS
Trends
• per cpu partial lists • common sl[aou]b • slab accounting for memcg
get a new slab from page allocator
per node
kmem_cache
lock
node0
kmem_cache_cpu
6
kmem_cache_node slab 2 slab 3 slab 4 slab 5
Free: fast-path
object from slab1
MEMORY ALLOCATION HIERARCHY
Page allocator
• page allocator
– fundamental memory allocator – manage all physical memory in system – page size = 4096 bytes – allocate 2order pages at once
cpu2
kmem_cache
cpu3
case 4. first free object
node0 kmem_cache_node slab case 2. normal case
slab
discard
case 3. inuse = 0
Performance optimizatiocaches slab slab slab
slab
slab
object
Slab
1 page
1 page fragmentation freelist inuse
1 page
slab
index
slab
_mapcount
objects
lru

overload
frozen
lru
… struct page
– avoid disabling interrupt
• cmpxchg_double
– avoid taking a lock
Performance optimization: freelist of kmem_cache_cpu
allocation request
new allocation request read freelist of kmem_cache_cpu
• The object allocator providing same API
– The SLAB allocator: traditional allocator – The SLOB allocator: for embedded system – The SLUB allocator: default, for large system
Allocation hierarchy
generic kernel code
object allocator
page allocator (buddy allocator)
physical page frame
Warning: term
• “the SLAB allocator” vs “the slab”
1 slab try on node partial slabs
slab
3
free object
slab
Allocation: very slow-path
per cpu name size align … cpu0 cpu2 cpu1 freelist
tid
cpu slab partial slabs 1
Free object management
cpu object cache
data structure max number of objects size (64bits)
The SLAB
array 120 120 * 8 bytes
The SLUB
list don’t care 8 byte
– the SLAB allocator
• one of the object allocator
– the slab
• just data structure • used by the slab allocator and the slub allocator
IMPLEMENTATION - SLUB
interrupt
read freelist, tid of kmem_cache_cpu detach first object(A)
detach first object(A) this_cpu_cmpxchg_double: new freelist(B),new tid retry fail
slab
data structure max number of objects size (64bits)
The SLAB
array 202 202 * 4 bytes
The SLUB
list don’t care 8 byte (overload “struct page”)
Miscellaneous
A DIFFERENCE BETWEEN THE SLAB AND THE SLUB
Caching policy
cpu0
cpu1
kmem_cache
In case of the SLAB
cpu2
cpu3
node0 kmem_cache_node slab
In case of the SLUB
相关文档
最新文档