CN117908988A - 从服务器内存按需加载运行程序内容的方法及系统 - Google Patents
从服务器内存按需加载运行程序内容的方法及系统 Download PDFInfo
- Publication number
- CN117908988A CN117908988A CN202410077772.9A CN202410077772A CN117908988A CN 117908988 A CN117908988 A CN 117908988A CN 202410077772 A CN202410077772 A CN 202410077772A CN 117908988 A CN117908988 A CN 117908988A
- Authority
- CN
- China
- Prior art keywords
- program
- server
- client
- page
- memory
- Prior art date
- Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
- Pending
Links
- 238000000034 method Methods 0.000 title claims abstract description 97
- 238000011068 loading method Methods 0.000 title claims abstract description 33
- 238000013507 mapping Methods 0.000 claims abstract description 73
- 230000008569 process Effects 0.000 claims abstract description 56
- 230000006870 function Effects 0.000 claims description 44
- 230000005012 migration Effects 0.000 claims description 35
- 238000013508 migration Methods 0.000 claims description 35
- 238000012545 processing Methods 0.000 claims description 6
- 238000004590 computer program Methods 0.000 claims description 4
- 230000003068 static effect Effects 0.000 description 6
- 230000008901 benefit Effects 0.000 description 4
- 238000010586 diagram Methods 0.000 description 4
- 230000008859 change Effects 0.000 description 3
- 230000004048 modification Effects 0.000 description 3
- 238000012986 modification Methods 0.000 description 3
- 230000004044 response Effects 0.000 description 3
- 238000013461 design Methods 0.000 description 2
- 238000005516 engineering process Methods 0.000 description 2
- 239000013589 supplement Substances 0.000 description 2
- 239000000725 suspension Substances 0.000 description 2
- 101100348848 Mus musculus Notch4 gene Proteins 0.000 description 1
- 238000004458 analytical method Methods 0.000 description 1
- 238000013459 approach Methods 0.000 description 1
- 230000009286 beneficial effect Effects 0.000 description 1
- 238000004364 calculation method Methods 0.000 description 1
- 238000004891 communication Methods 0.000 description 1
- 238000001514 detection method Methods 0.000 description 1
- 230000006872 improvement Effects 0.000 description 1
- 238000009434 installation Methods 0.000 description 1
- 230000009191 jumping Effects 0.000 description 1
- 238000012423 maintenance Methods 0.000 description 1
- 230000007246 mechanism Effects 0.000 description 1
- 230000036316 preload Effects 0.000 description 1
- 230000001502 supplementing effect Effects 0.000 description 1
- 230000001960 triggered effect Effects 0.000 description 1
- 239000002699 waste material Substances 0.000 description 1
Classifications
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F9/00—Arrangements for program control, e.g. control units
- G06F9/06—Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
- G06F9/44—Arrangements for executing specific programs
- G06F9/445—Program loading or initiating
- G06F9/44521—Dynamic linking or loading; Link editing at or after load time, e.g. Java class loading
Landscapes
- Engineering & Computer Science (AREA)
- Software Systems (AREA)
- Theoretical Computer Science (AREA)
- Physics & Mathematics (AREA)
- General Engineering & Computer Science (AREA)
- General Physics & Mathematics (AREA)
- Memory System Of A Hierarchy Structure (AREA)
Abstract
本发明公开了从服务器内存按需加载运行程序内容的方法及系统,通过客户端截获目标程序映射中引发的缺页中断,所述映射在运行到目标程序入口地址前已经建立完毕;客户端将所述缺页中断的请求发送给所述服务器,所述请求包括发生缺页的进程名称以及本次缺页的地址;服务器根据所述请求从其内存中获取对应的页面,并将所述页面返回给所述客户端。相比现有技术,本发明控制客户端按需从服务器内存加载程序运行所需的代码和数据进入本地内存,整个过程不需要消耗本地存储资源,且从服务器的内存直接获取所需代码和数据,减小数据访问延迟。
Description
技术领域
本发明涉及计算机软件的加载方法,具体涉及从服务器内存按需加载运行程序内容的方法及系统。
背景技术
大规模的程序数量和不断膨胀的程序体积对终端设备的存储能力提出了越来越高的挑战。随着新技术的不断涌现,程序数量呈现出指数级的增长。根据谷歌商店应用数量的数据显示,自2010年以来,应用数量从不足10万迅速增长至2020年突破3百万,呈现出迅猛的增长趋势。与此同时,用户的需求和期望也在不断演变,这促使开发人员在程序代码中不断引入新的功能和特性,以满足市场需求。然而,这种快速的功能扩展和增加也带来了一个显而易见的结果,即程序文件的体积不断增加。
然而,就单个用户而言,并非所有程序的功能都会在其日常的任务中得到充分利用。在日常使用中,实际需要的代码和数据可能仅占整个存储内容的一小部分,存储在磁盘上的绝大多数内容在单次运行时都没有被使用,有些功能甚至可能永远不会被触发。这种情况导致了较低的存储资源利用率,将对终端设备的整体性能产生影响。对于硬件资源受限的轻量级终端设备来说,低存储利用率不仅是资源浪费,更是一种严重的性能制约。随着物联网应用的不断扩展,终端设备需要存储越来越多的数据,包括传感器数据、通信数据和运行结果。低存储利用率会直接影响终端有效地收集、处理和存储关键数据的能力,这对于它们在各种应用中的功能和效率至关重要。
另外,对于已经部署的终端设备,要安装新的应用程序以扩展其功能是一项繁琐的任务。这需要手动确定终端节点的位置,并逐个将程序安装到各个设备上。而当需要更新程序时,又需要重复这一过程,这足以让终端维护人员感到困扰。
发明内容
本发明提供了从服务器内存按需加载运行程序内容的方法及系统,用于解决现有的程序加载方式将为未被使用的程序代码和数据存储至本地磁盘,本地磁盘存储利用率低的问题。
为解决上述技术问题,本发明提出的技术方案为:
一种从服务器内存按需加载运行程序内容的方法,应用于Linux系统的ELF程序的运行过程中,包括:
客户端截获目标程序映射中的缺页中断,所述映射在运行到目标程序入口地址前已经建立完毕;
客户端将所述缺页中断的请求发送给所述服务器,所述请求包括发生缺页的进程名称以及本次缺页的地址;
服务器根据所述请求从其内存中获取对应的页面,并将所述页面返回给所述客户端;
客户端对接收所述页面,并完成所述目标程序的缺页中断。
优选的,所述映射包括文件映射,当所述映射为文件映射时,客户端截获目标程序运行映射中的缺页中断,通过修改VMA结构中的vm_ops成员,使其fault函数指针指向remote_filemap_fault函数来实现;所述remote_filemap_fault的功能是将本次缺页中断信息发送到服务器,并等待服务器数据返回,所述中断信息包括缺页地址和程序名。
优选的,所述映射包括匿名映射,所述匿名映射缺页中断的处理函数为do_anonymous_pages函数,所述do_anonymous_pages函数将本次缺页中断信息发送到服务器,并等待服务器数据返回;且本发明在内核VMA结构中增加remote_vma标志成员,所述remote_vma标志成员用来区分此VMA中的缺页中断是否需要被截获,所述中断信息包括缺页地址和程序名。
优选的,服务器根据所述请求从其内存中获取对应的页面前,还包括以下步骤:
客户端运行所述目标程序时,发送初始化信号给所述服务器;
所述服务器根据初始化信号运行所述目标程序,并在目标程序完成加载后将其暂停在入口地址上,为客户端建立起了完整的内存映射,供客户端获取页面。
优选的,所述服务器在load_elf_binary中调用elf_map函数进行内存映射,且所述elf_map函数包括MAP_POPULATE和MAP_LOCKED两个标志,所述MAP_POPULATE标志要求服务器内核在映射的同时完成数据到物理内存的加载过程,而不是之后发生缺页中断时才加载;所述MAP_LOCKED指示内核将该VMA中的页面锁定在内存中,阻止其交换到磁盘。
优选的,客户端将所述缺页中断的请求发送给所述服务器后,还包括以下步骤:
客户端轮询等待数据的到达,并在轮询前,请求与页面大小匹配的物理内存等待服务器的页面到达。
优选的,客户端对接收所述页面,并完成所述目标程序的缺页中断,包括以下步骤:
客户端将所述页面存于物理内存,并将物理页面返回给调用链的上一级函数,进入缺页中断的返回流程。
优选的,客户端存储的ELF程序为轻量级ELF程序,其可执行文件由以下部分组成:
位于文件开头标识该文件类型的ELF Header;紧随ELF头后面的程序头表;紧随程序头表后的是类型为INTERP的段。
优选的,所述服务器还将其程序入口处的内存映射迁移至所述客户端,所述内存映射迁移包括:VMA迁移、寄存器迁移、TLS描述符迁移以及VDSO信息迁移;
所述VMA迁移包括以下步骤:
服务器内核线程遍历目标进程所有的vm_area_struct结构并发送给所述客户端;
客户端停留在sys_execve中等待信息到达,并根据接收到的内容依次建立对应的VMA;
所述sys_execve的返回地址为程序入口;
所述寄存器迁移包括以下步骤:
在程序入口暂停RPF目标进程时,服务器使用ptrace获取其通用寄存器的值,并通过系统调用送入到内核线程中;
在发送完VMA结构后,内核线程继续向客户端发送寄存器信息;
客户端随后按顺序将接收到的所述寄存器信息替换内核栈中的原有寄存器值;
在程序从内核态返回到用户态的程序入口时,操作系统会将内核栈中的保存的寄存器值弹出到对应的寄存器中;
所述TLS描述符迁移包括:
服务器修改目标程序在入口位置的二进制指令,执行一个系统调用,所述二进制指令是保存当前GDT中0x33对应的描述符,随后由内核线程发送给客户端;
客户端接收到描述符后将其填充到GDT的对应位置;
所述VDSO信息迁移包括:
将服务器端的sysenter_return迁移到给客户端。
一种计算机系统,包括存储器、处理器以及存储在存储器上并可在处理器上运行的计算机程序,所述处理器执行所述计算机程序时实现上述方法的步骤。
本发明具有以下有益效果:
1、本发明通过客户端截获目标程序运行映射中的缺页中断,所述映射在运行到目标程序入口地址前已经建立完毕;客户端将所述缺页中断的请求发送给所述服务器,所述请求包括发生缺页的进程名称以及本次缺页的地址;服务器根据所述请求从其内存中获取对应的页面,并将所述页面返回给所述客户端,相比现有技术,本发明控制客户端按需从服务器内存加载程序运行所需的代码和数据进入本地内存,整个过程不需要消耗本地存储资源,且从服务器的内存直接获取所需代码和数据,减小数据访问延迟。
除了上面所描述的目的、特征和优点之外,本发明还有其它的目的、特征和优点。下面将参照附图,对本发明作进一步详细的说明。
附图说明
构成本申请的一部分的附图用来提供对本发明的进一步理解,本发明的示意性实施例及其说明用于解释本发明,并不构成对本发明的不当限定。在附图中:
图1是本发明的程序按需加载流程图。
图2是本发明中进行远程缺页中断的内核函数调用流程图。
图3是本发明中服务器预加载程序示意图。
图4是本发明中程序裁剪方法示意图。
图5是本发明中虚拟内存区域迁移示意图。
图6是本发明中暂停服务器上目标进程的方法示意图。
具体实施方式
以下结合附图对本发明的实施例进行详细说明,但是本发明可以由权利要求限定和覆盖的多种不同方式实施。
实施例一:
本发明中的从服务器内存按需加载运行程序内容的方法,主要包含三个组件:(1)远程缺页中断:这是实现按需加载的关键技术;(2)程序裁剪方法:将ELF程序裁剪以节省终端设备的存储;(3)虚拟内存区域迁移方法:补充终端缺失的内存区域。
(1)远程缺页中断
远程缺页中断(RPF)能够在程序运行时按需从服务器申请数据,在这里,数据的具体形式是页面,大小为4KB。具体来说,RPF将缺页中断页面的来源由本地硬盘重定位到了远程服务器,因此,客户端能够以页面为粒度从服务器获得所需要的代码和数据,完整的程序文件不需要存放在本地。RPF流程包含:客户端截获缺页中断、客户端发送缺页中断信息到服务器、服务器响应对应页面给客户端以及客户端接收页面完成本次缺页中断。接下来我们阐述每个步骤的设计。
截获:本发明截获原生的缺页中断的处理流程并插入设计好的远程缺页中断功能,来避免对内核代码的大量修改。由于文件映射和匿名映射的缺页中断处理方式不同,因此需要分别修改对应的缺页中断处理程序。首先需要区分哪些缺页中断需要截获,因为单纯截获所有缺页中断并进行远程页面获取将导致程序异常。例如,程序运行过程中可能申请新的匿名或文件映射,而在服务器端却不存在此映射,截获此处发生的缺页中断将导致服务器访存异常。另外,对于共享库申请的匿名映射则必须截获,因为其中填充有共享库运行所必须的数据。本发明选择截获所有运行到程序入口地址前已经建立完毕的映射。该解决方法来自这样一个事实:Linux程序运行到其入口地址时,其代码、数据的文件映射以及共享库的文件和匿名映射已经建立完毕,而其他映射将在程序逻辑的控制下建立。也就是说,而在入口地址之后建立的映射将随着程序执行自行建立起来,不需要通过远程获取。只要截获在入口地址前完成的映射,就能够获得程序文件的代码、数据以及共享库的代码和数据。选择程序入口地址作为分界的原因是共享库的链接工作在跳转到程序入口前完成。共享库占据动态链接程序体积的很大部分,为节约客户端的存储,能够使用RPF加载共享库的代码是很有必要的。
请求:截获缺页中断后需要将本次缺页的相关信息发送到服务器以获取对应的数据。最关键的信息是发生缺页的进程名称以及本次缺页的地址。因为本发明之后将会从服务器的内存获取数据,进程名称(程序名称)指示服务器使用哪个进程的虚拟内存空间,而缺页地址则表明应该从虚拟内存空间的何处获取页面。在本发明中,不同程序发送远程缺页中断请求的目标服务器可以灵活配置。换句话说,每个程序都可以选择从不同的服务器按需获取代码,这不仅能够均衡各服务器的负载,而且为终端功能扩展带来了灵活性和可扩展性等诸多好处。
响应:服务器根据客户端发来的缺页中断信息,获取对应页面返回给客户端完成响应。不同于通过I/O操作读取服务器硬盘的方式,本发明计划直接从服务器内存返回客户端所需页面,以节省等待I/O操作的时间,提供更出色的性能表现。直接从内存获取页面要求服务器预先加载程序文件到内存中。服务器可以直接使用mmap映射程序文件到内存中,但这会导致代码映射的地址与编译地址不同,需要额外进行一次从缺页地址到本地内存地址的重定位过程。本发明希望RPF的过程尽可能迅速,因此,本发明设计让服务器的映射地址与客户端保持一致。一种方法是仿照内核的load_elf_binary函数建立内存映射的逻辑,自己编写功能将程序文件映射到编译好的地址上,但是这会遗漏动态库的映射。动态库的链接是由动态链接器完成的复杂过程,发生完成程序文件映射之后。手动完成共享库的预加载功能意味着进行大量重复造轮子的工作,并且不利于向前兼容。为此,本发明决定“借用”Linux的程序加载功能。程序的加载过程在系统将程序投入运行后完成,本发明选择让服务器运行对应的程序,以此建立起完整的内存映射。但是,程序一但开始运行,就可能修改内存中的可写数据,客户端获取到这些修改过的脏页面会导致程序运行错误。在这里,一个关键的临界点是程序的入口位置。在运行到程序的入口地址前,程序的内存数据处于“纯净”的状态,此时各映射才刚刚建立。当程序从入口地址运行后才开始根据逻辑修改其数据。因此,本发明选择让程序暂停在其入口地址处,保证客户端能够获得未经修改的页面,而且不会再消耗服务器的CPU资源。在本发明中,客户端开始运行某程序时,向服务器发送一个初始化信号,指示服务器将对应的程序投入运行,并在程序完成加载后将其暂停在入口地址上。这样一来,服务器为客户端建立起了完整的内存映射,可以供客户端按需获取页面。注意,建立好内存映射并不代表对应数据真正被加载到了物理内存中,还需要一些额外的操作,告知Linux在加载这些RPF目标进程时就完成物理内存的分配和对应页面的载入。
接收:接收步骤主要进行物理内存的分配,并将执行流接回到缺页中断的返回流程。由于缺页中断的处理速度极大地影响了程序的运行效率,本发明让客户端在发送远程缺页中断请求后轮询等待数据的到达,以实现最快的响应时间。在轮询前,客户端会请求一块页面大小的物理内存,等待服务器的页面到达。随后,这个物理页面将返回给调用链的上一级函数,进入缺页中断的返回流程。至此,远程缺页中断流程完成。
(2)程序裁剪方法
程序裁剪将程序的完整的ELF可执行文件裁剪为一个轻量级的版本。这个轻量级文件体积很小,但使得客户端能够正常启动该程序并进行远程缺页中断过程,达到节省客户端存储的目的。研究一种程序裁剪方法是必要的,因为引发缺页中断的前提是正常启动程序并建立好内存映射。倘若客户端只能在拥有完整程序文件的情况下才能够正常建立内存映射,RPF将失去其价值。程序剪裁的灵感来自于这样一个发现:在引发第一个获取代码的缺页中断前,程序的内存映射已经全部完成。这意味着程序文件的代码和数据部分在程序加载阶段并没有被使用,可能可以从程序文件中分离,而会不影响程序启动和建立内存映射的过程。ELF可执行文件的结构天然支持本发明设想的裁剪想法:ELF文件将内存映射过程需要的信息保存在靠近文件头部的位置。因此,本发明仅保留程序文件的头部内容作为程序的轻量级版本,剪除二进制的代码和数据。同时,本发明修改了客户端内核中承担加载功能的几行代码以绕过对程序文件完整性的检测。
(3)虚拟内存区域迁移方法
虚拟内存区域迁移方法将服务器端程序的内存映射复制到客户端,确保客户端程序的内存布局与服务器相同,以便程序能通过RPF获取共享库代码。本发明的设计理念是不在本地存储程序文件以及共享库文件,这导致客户端程序不能正常经历链接过程,因此,动态链接器无法在链接阶段完成共享库的内存映射,结果是在入口地址处,客户端程序相比服务器缺失了属于共享库的VMA,程序无法正常运行。要解决这个问题需要做到两点,一是能够补充缺失的共享库的VMA,二是让主程序需要重定位的符号能够链接到内存中共享库符号所在的位置。本发明的解决方法是,将服务器端程序的内存映射迁移到客户端。如前所述,服务器程序启动后被暂停在程序入口地址,意味着它完成了动态链接建立映射的过程。这是由于Linux完成动态链接程序加载后,先调用动态链接器进行链接,再跳转到程序的入口地址。本发明选择在入口处迁移内存映射,一来,能够补充客户端缺失的共享库VMA,并且能够严格保证客户端和服务器的内存映射地址完全一致。二来,由于RPF使用的是服务器内存的数据,而服务器已经完成了符号的重定位的过程,因此,虚拟内存区域迁移让客户端直接享用了服务器链接的成果,可以省去本地处理器的链接过程。从这个角度来看,客户端好比服务器的一个分布式处理器,只需要进行程序计算,服务器则提供存储和内存资源。虚拟内存区域迁移是为动态链接程序而设计的。静态链接程序不存在上述问题,因为共享库在静态链接程序文件中被编译成为程序的一个段,所有符号解析都已经完成,不需要再进行链接。
在优选实施例中,本发明中的从服务器内存按需加载运行程序内容的方法,使用X86指令集架构,选择的Linux版本为2.6.34(32位),具体包括以下步骤:
(1)远程缺页中断
截获:动态链接程序的RPF过程需要捕获文件映射以及匿名映射的缺页中断,因为匿名映射中存有共享库运行的必要数据,另外,匿名映射也包括程序栈。由于服务器相比于客户端多执行了一段动态链接步骤,栈中的数据也会发生改变,因此捕获匿名映射的缺页中断同时帮助客户端获取最新的栈数据。
经修改后的内核处理页面首次引发的缺页中断的函数调用链如图2所示。在Linux中,文件映射的缺页中断将进入do_linear_fault,此函数继续调用__do_fault。__do_fault最终调用VMA结构成员vm_ops的fault来处理此缺页中断。vm_ops是特定于文件系统的结构,在ext4文件系统下,vm_ops指向ext4_file_vm_ops,其成员fault函数则指向filemap_fault,用于从文件系统中读取页面。
为截获缺页中断,本发明将vm_ops指向本发明设计的remote_ext4_file_vm_ops结构,其fault指向设计好的remote_filemap_fault函数,以进行后续的RPF流程。
匿名映射缺页中断的处理函数则是do_anonymous_pages,功能是申请物理内存并建立页表映射,本发明直接修改此函数,在此基础上添加RPF功能。由于在运行过程中新建立的映射处的缺页中断不能被截获,本发明在内核VMA的结构vm_area_struct中增加remote_vma标志成员,此标志用来区分此VMA中的缺页中断是否需要被截获。本发明在程序入口前已经建立的VMA以及从服务器迁移过来的VMA中置位remote_vma标志,此处发生的缺页中断会被截获;而自程序入口处执行后新产生的VMA则默认不带此标志,会进入默认缺页中断流程。
请求:客户端使用TCP协议向服务器发送缺页请求,这通过自定义的RPF函数使用内核socket接口来完成。客户端启动程序时可以通过参数配置RPF目标服务器的IP地址。客户端向服务器发送长度为128字节的缺页请求,其中,开头4字节(32位)为缺页地址,剩余字节为程序名称预留。
响应:本发明在服务器创建了一个内核线程来监听缺页中断请求并返回页面给客户端。内核线程的优点是拥有高特权级,可以访问属于其它进程的内存数据。本发明使用Linux内核模块来实现内核线程,可以根据需要,安装模块将某台机器变为RPF的服务器,或卸载模块将其从服务器群中移除。
服务器接收到来自客户端的初始化信号时会将对应的程序投入运行,开始建立内存映射。为保持请求信息的一致性,本发明复用上述128字节长度的缺页请求,以非法地址0作为程序的初始化信号。
为保证页面在映射建立初始就能一直驻留在内存中,本发明在load_elf_binary中调用elf_map进行内存映射时额外传入两个标志:MAP_POPULATE和MAP_LOCKED,如图3所示。其中,MAP_POPULATE要求内核在映射的同时完成数据到物理内存的加载过程,而不是之后发生缺页中断时才加载;MAP_LOCKED指示内核将该VMA中的页面锁定在内存中,阻止其交换到磁盘。建立完毕内存映射后,程序会被暂停在入口地址处。服务器使用哈希表来保存已启动的RPF目标进程的PCB。内核线程使用请求信息中的程序名称快速查找对应进程的PCB,随后使用此PCB和缺页地址作为内核函数get_user_pages的参数,获取不同进程的对应页面,通过已建立的TCP连接返回给客户端。
接收:在发送缺页请求后,客户端通过__get_free_page申请一物理页,准备接收来自服务器的页数据,然后轮询等待服务器响应。页面到达后,对于文件映射,直接将此页面返回给上一级函数,并进入原生缺页中断的返回流程完成缺页中断。而对于匿名映射,需要通过copy_to_user将此页面数据复制到刚刚完成页表映射的缺页地址。
(2)程序裁剪方法
本发明仅保留加载过程必需的ELF文件部分,将其余部内容从文件中裁剪。首先需要保留的是位于文件开头标识该文件类型的ELF Header,为固定的52字节(32位)。其次需要保留的是紧随ELF头后面的程序头表,内核函数load_elf_binary就是依据此表的表项来完成内存的映射,程序头表长度是可变的。紧随程序头表后的是类型为INTERP的段,load_elf_binary通过检查此段是否存在来判别是否是动态链接程序,本发明同样将其保留。本发明从INTERP段结尾处将程序文件截断,如图4所示,所保留的部分总大小约360字节。
(3)虚拟内存区域迁移方法
虚拟内存区域迁移分为4个步骤:1.VMA迁移。2.寄存器迁移。3.TLS描述符迁移。4.VDSO信息迁移,如图5。
VMA迁移:内核线程遍历RPF目标进程所有的vm_area_struct结构并发送给客户端,其中包含了VMA的开始地址、结束地址以及权限标志(读、写、执行)等。客户端则停留在sys_execv中等待信息到达,并根据接收到的内容依次建立对应的VMA。在此之前客户端可能已经建立起了部分内存映射,需要将其撤销。由于不需要经历链接过程,本发明将sys_execve的返回地址从动态链接器的入口改为程序入口,使得客户端完成加载后直接开始运行程序。此时,客户端与服务器的程序拥有完全相同的内存布局。
寄存器迁移:由于服务器执行了额外的链接代码,其寄存器中保存了最新的计算结果。客户端想要利用服务器的内存数据从程序入口处开始接力运行,需要迁移服务器的寄存器内容。在程序入口暂停RPF目标进程时,本发明使用ptrace获取其通用寄存器的值,并通过系统调用送入到内核线程中。在发送完VMA结构后,内核线程继续向客户端发送寄存器信息。客户端随后按顺序将它们替换内核栈中的原有寄存器值。在程序从内核态返回到用户态的程序入口时,操作系统会将内核栈中的保存的寄存器值弹出到对应的寄存器中。此时,客户端拥有了和服务器相同的寄存器状态以及内存布局,可以从程序入口处开始运行。
TLS描述符迁移:Linux使用段寄存器gs指向一个固定的全局描述符(gs=0x33)来实现TLS(Thread Local Storage,线程本地存储)。通过修改该全局描述符的基址,不同线程能够使用相同的线性地址来访问不同位置的内存值,从而实现线程数据私有。TLS描述符在链接过程中被创建,因此需要从服务器迁移。TLS描述符与当前执行线程挂钩,必须由本线程亲自收集而不能使用内核线程代为收集。本发明修改程序在入口位置的二进制指令,执行一个系统调用,其功能是保存当前GDT中0x33对应的描述符,随后由内核线程发送给客户端。客户端接收到描述符后将其填充到GDT的对应位置。
VDSO信息迁移:VSDO(Virtual Dynamic Shared Object,虚拟动态共享对象)是位于用户空间的映射,Glibc使用其进行快速系统调用。由于使用服务器的内存布局,客户端程序能成功访问VDSO进行系统调用,但接着会访问已经被撤销的本地VDSO区域,引发段错误。由此可推断VDSO的信息被存在了内核某处。经过对VDSO区域的反汇编发现,所有的快速系统调用都会跳转到同一个退出地址上,该地址的相对偏移与引发段错误的偏移相同,因此问题出在VDSO的退出机制。通过对内核源码的详细分析,本发明发现Linux-2.6下快速系统调用的统一退出地址被保存在PCB的父结构thread_info中的sysenter_return变量中,而客户端中该变量指向旧的VDSO区。通过将服务器端的sysenter_return迁移到给客户端,客户端上的RPF程序得以成功运行。
(4)程序暂停方法
本发明将服务器的RPF目标程序暂停在程序入口,并注入一个系统调用完成TLS描述符的收集。由于内核线程无法捕获到动态链接器跳转到程序入口的时机,因此本发明需要手动在程序入口打上断点。X86的断点指令为0xcc,对应于汇编指令int3。本发明创建一个父进程,它使用ptrace将RPF目标程序(子进程)入口地址处的四个字节代码改为0xcc0xcd 0x800xcc来完成上述任务,具体的流程如图6所示。
①子进程运行到入口地址的第一个字节(0xcc)时,进程暂停。父进程此时保存服务器当前寄存器值,并将eax寄存器的值修改为340(十进制),这是将要进行的系统调用号。之后,父进程向子进程发送CONTINUE信号,指示子进程继续运行。
②接下来,子进程将执行0xcd 0x80指令,即汇编代码int 0x80,引发340号系统调用。340号是本发明自定义的系统调用,它使用fill_user_desc来收集当前线程的TLS描述符。
③最后,子进程执行到第四个字节的0xcc指令,再次被暂停。父进程此时还原入口位置的4字节代码,并将保存的寄存器值发送到内核线程,内核线程随即开始迁移VMA。此时,本发明让父进程睡眠,子进程将不会被唤醒,完成了服务器程序的暂停。
(5)静态链接程序的按需加载运行实施方式
静态链接程序依赖的所有目标文件都被链接到可执行文件,所以程序头表中包含了完整的映射信息。因此,静态链接程序只需要截获文件映射引发的缺页中断,且不需要进行虚拟内存区域迁移。另外,静态ELF文件没有INTERP segment,切分时直接在程序头表后将程序截断,产生的轻量级文件大小平均约180字节。
最后,由于静态链接程序在完成加载后直接跳转到程序入口,因此本发明在内核函数sys_execve返回前直接让进程睡眠即可完成程序的暂停。
综上所述,本发明从服务器内存按需加载运行程序内容的方法,按需加载程序的代码和数据,节约本地存储空间。高效利用终端设备本地计算能力。从服务器的内存直接获取所需代码和数据,减小数据访问延迟。软件维护仅需要在服务器处进行,摆脱繁琐的软件部署流程。
以上所述仅为本发明的优选实施例而已,并不用于限制本发明,对于本领域的技术人员来说,本发明可以有各种更改和变化。凡在本发明的精神和原则之内,所作的任何修改、等同替换、改进等,均应包含在本发明的保护范围之内。
Claims (10)
1.一种从服务器内存按需加载运行程序内容的方法,应用于Linux系统的ELF程序的运行过程中,其特征在于,包括:
客户端截获目标程序映射中的缺页中断,所述映射在运行到目标程序入口地址前已经建立完毕;
客户端将所述缺页中断的请求发送给所述服务器,所述请求包括发生缺页的进程名称以及本次缺页的地址;
服务器根据所述请求从其内存中获取对应的页面,并将所述页面返回给所述客户端;
客户端对接收所述页面,并完成所述目标程序的缺页中断。
2.根据权利要求1所述的从服务器内存按需加载运行程序内容的方法,其特征在于,所述映射包括文件映射,当所述映射为文件映射时,客户端截获目标程序运行映射中的缺页中断,通过修改VMA结构中的vm_ops成员,使其fault函数指针指向remote_filemap_fault函数来实现;所述remote_filemap_fault的功能是将本次缺页中断信息发送到服务器,并等待服务器数据返回,所述中断信息包括缺页地址和程序名。
3.根据权利要求1所述的从服务器内存按需加载运行程序内容的方法,其特征在于,所述映射包括匿名映射,所述匿名映射缺页中断的处理函数为do_anonymous_pages函数,所述do_anonymous_pages函数将本次缺页中断信息发送到服务器,并等待服务器数据返回;且本发明在内核VMA结构中增加remote_vma标志成员,所述remote_vma标志成员用来区分此VMA中的缺页中断是否需要被截获,所述中断信息包括缺页地址和程序名。
4.根据权利要求1所述的从服务器内存按需加载运行程序内容的方法,其特征在于,服务器根据所述请求从其内存中获取对应的页面前,还包括以下步骤:
客户端运行所述目标程序时,发送初始化信号给所述服务器;
所述服务器根据初始化信号运行所述目标程序,并在目标程序完成加载后将其暂停在入口地址上,为客户端建立起了完整的内存映射,供客户端获取页面。
5.根据权利要求4所述的从服务器内存按需加载运行程序内容的方法,其特征在于,所述服务器在load_elf_binary中调用elf_map函数进行内存映射,且所述elf_map函数包括MAP_POPULATE和MAP_LOCKED两个标志,所述MAP_POPULATE标志要求服务器内核在映射的同时完成数据到物理内存的加载过程,而不是之后发生缺页中断时才加载;所述MAP_LOCKED指示内核将该VMA中的页面锁定在内存中,阻止其交换到磁盘。
6.根据权利要求4所述的从服务器内存按需加载运行程序内容的方法,其特征在于,客户端将所述缺页中断的请求发送给所述服务器后,还包括以下步骤:
客户端轮询等待数据的到达,并在轮询前,请求与页面大小匹配的物理内存等待服务器的页面到达。
7.根据权利要求1所述的从服务器内存按需加载运行程序内容的方法,其特征在于,客户端对接收所述页面,并完成所述目标程序的缺页中断,包括以下步骤:
客户端将所述页面存于物理内存,并将物理页面返回给调用链的上一级函数,进入缺页中断的返回流程。
8.根据权利要求1所述的从服务器内存按需加载运行程序内容的方法,其特征在于,客户端存储的ELF程序为轻量级ELF程序,其可执行文件由以下部分组成:
位于文件开头标识该文件类型的ELF Header;紧随ELF头后面的程序头表;紧随程序头表后的是类型为INTERP的段。
9.根据权利要求4所述的从服务器内存按需加载运行程序内容的方法,其特征在于,所述服务器还将其程序入口处的内存映射迁移至所述客户端,所述内存映射迁移包括:VMA迁移、寄存器迁移、TLS描述符迁移以及VDSO信息迁移;
所述VMA迁移包括以下步骤:
服务器内核线程遍历目标进程所有的vm_area_struct结构并发送给所述客户端;
客户端停留在sys_execve中等待信息到达,并根据接收到的内容依次建立对应的VMA;
所述sys_execve的返回地址为程序入口;
所述寄存器迁移包括以下步骤:
在程序入口暂停RPF目标进程时,服务器使用ptrace获取其通用寄存器的值,并通过系统调用送入到内核线程中;
在发送完VMA结构后,内核线程继续向客户端发送寄存器信息;
客户端随后按顺序将接收到的所述寄存器信息替换内核栈中的原有寄存器值;
在程序从内核态返回到用户态的程序入口时,操作系统会将内核栈中的保存的寄存器值弹出到对应的寄存器中;
所述TLS描述符迁移包括:
服务器修改目标程序在入口位置的二进制指令,执行一个系统调用,所述二进制指令是保存当前GDT中0x33对应的描述符,随后由内核线程发送给客户端;
客户端接收到描述符后将其填充到GDT的对应位置;
所述VDSO信息迁移包括:
将服务器端的sysenter_return迁移到给客户端。
10.一种计算机系统,包括存储器、处理器以及存储在存储器上并可在处理器上运行的计算机程序,其特征在于,所述处理器执行所述计算机程序时实现上述权利要求1至9任一所述方法的步骤。
Priority Applications (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN202410077772.9A CN117908988A (zh) | 2024-01-18 | 2024-01-18 | 从服务器内存按需加载运行程序内容的方法及系统 |
Applications Claiming Priority (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN202410077772.9A CN117908988A (zh) | 2024-01-18 | 2024-01-18 | 从服务器内存按需加载运行程序内容的方法及系统 |
Publications (1)
Publication Number | Publication Date |
---|---|
CN117908988A true CN117908988A (zh) | 2024-04-19 |
Family
ID=90691873
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
CN202410077772.9A Pending CN117908988A (zh) | 2024-01-18 | 2024-01-18 | 从服务器内存按需加载运行程序内容的方法及系统 |
Country Status (1)
Country | Link |
---|---|
CN (1) | CN117908988A (zh) |
-
2024
- 2024-01-18 CN CN202410077772.9A patent/CN117908988A/zh active Pending
Similar Documents
Publication | Publication Date | Title |
---|---|---|
US9497264B2 (en) | Apparatus, method and system for aggregating computing resources | |
US8689232B2 (en) | Object synchronization in shared object space | |
US6275893B1 (en) | Method and apparatus for providing seamless hooking and intercepting of selected kernel and HAL exported entry points in an operating system | |
US6848106B1 (en) | Snapshot restore of application chains and applications | |
US7543301B2 (en) | Shared queues in shared object space | |
KR101400286B1 (ko) | 다중 프로세서 시스템에서 작업을 이동시키는 방법 및 장치 | |
EP0466486A2 (en) | Distributed computing system | |
CN111431757B (zh) | 虚拟网络的流量采集方法及装置 | |
US8127273B2 (en) | Node selection for executing a Java application among a plurality of nodes | |
JP2004133894A (ja) | 仮想マシンをフォークまたはマイグレートするための方法 | |
US20090125611A1 (en) | Sharing loaded java classes among a plurality of nodes | |
US20020174265A1 (en) | Method and apparatus for caching active computing environments | |
Cabillic et al. | Stardust: an environment for parallel programming on networks of heterogeneous workstations | |
JP2004258840A (ja) | 仮想化されたi/oデバイスをもつ計算機システム | |
JPH1078873A (ja) | エミュレーション・システムで非同期信号を処理する方法 | |
US8239862B2 (en) | Apparatus, method, and computer program product for processing information | |
JP5030647B2 (ja) | 複数処理ノードを含むコンピュータ・システムでプログラムをロードする方法、該プログラムを含むコンピュータ可読媒体、及び、並列コンピュータ・システム | |
US6256752B1 (en) | Method and apparatus for dynamic swappable bytecode loop in java virtual machines | |
Lux | Adaptable object migration: concept and implementation | |
CN117908988A (zh) | 从服务器内存按需加载运行程序内容的方法及系统 | |
CN117407054A (zh) | 中断处理方法、电子设备和存储介质 | |
Dan et al. | Quasi-asynchronous migration: A novel migration protocol for PVM tasks | |
Göckelmann et al. | Plurix, a distributed operating system extending the single system image concept | |
Alali | Elastic Process: A Framework for Joint Disaggregation of Memory and Computation in Linux | |
Bielski | Novel memory and I/O virtualization techniques for next generation data-centers based on disaggregated hardware |
Legal Events
Date | Code | Title | Description |
---|---|---|---|
PB01 | Publication | ||
PB01 | Publication | ||
SE01 | Entry into force of request for substantive examination | ||
SE01 | Entry into force of request for substantive examination |