vm_pattr 系统调用和 kvm_pattr 内核服务

用途

查询或修改虚拟内存属性。

标准 C 库 (libc.a)

语法

#include <sys/vmpattr.h>
int vm_pattr (
long cmd,
pid_t pid,
void * attr,
size_t attr_size );

int kvm_pattr (
long cmd,
pid_t pid,
void * attr,
size_t attr_size );

描述

vm_pattr 系统调用查询或修改调用进程的地址空间或其他用户进程的地址空间的内存属性。

克夫 _pattr 内核服务向内核子系统 (内核扩展,内核进程等) 提供相同的功能,但它不能修改另一个内核进程的内存属性。

参数

描述
cmd 以下命令可以传递到:
VM_PA_SET_PSIZE 或 VM_PA_GET_PSIZE
这些命令将设置或检索用于指定内存范围的页面大小。
vm_pa_get_rmusage
此命令检索用于指定内存范围的实内存量 (以字节为单位)。
VM_PA_SET_PSPA 或 VM_PA_GET_PSPA
这些命令为指定的内存范围设置或检索页面大小提升积极性因子。
vm_pa_get_pspa_align
此命令检索在使用 VM_PA_SET_PSPA 命令时对 vm_pattr 内核服务指定的内存范围所必需的最小内存对齐。
vm_pa_check_psize
此命令报告是否可以将指定的页面大小用于内存范围。
vm_pa_set_lsa_policy
此命令允许根据进程需求对共享内存地址空间分配程序进行调整。 应该在创建任何共享内存区域之前运行此命令。
VM_PA_SET_PSIZE_EXTENDED 或 VM_PA_GET_PSIZE_EXTENDED
这些命令提供可变大页大小段支持。
pid 指定要对其内存属性进行查询或修改的进程的标识。 -1 的值表示调用进程。 root 用户可以指定任何进程标识,但其他用户只能指定他们拥有的进程 (即,目标进程的用户标识必须与调用进程的用户标识相匹配)。

vm_pattr 系统调用仅支持用户进程,而 kvm_pattr 内核服务可以针对用户进程或自己的内核进程(例如,pid = -1) )。

attr 一个指向结构的指针,该结构描述正在查询或修改的内存的有效地址范围以及附加数据 (取决于命令)。
范围是通过以下 vm_pa_range 结构指定的:
struct vm_pa_range
             {
                 ptr64_t  rng_start;
                 size64_t rng_size;
             };
指定的范围必须在目标进程的地址空间中,并且必须对应于下列其中一个进程区域:
  • 主程序数据 (已初始化, bss 或堆)。
  • 共享库数据或专用模块装入区域数据。
  • 私有装入的文本。
  • 初始线程堆栈区域。
  • 匿名共享内存 (System V 共享内存,通过 EXTSHM 共享的扩展 System V 和 POSIX 实时共享内存)。 为了更改共享内存范围的属性,目标进程必须具有对内存的写访问权。
  • 匿名 mmap 内存。
如果指定的内存范围包括共享内存或 mmap 内存,那么调用进程必须根据共享内存描述符或映射属性对内存具有写访问权,以更改范围的属性。 根据以下命令,该范围可能有其他限制。
阿特尔 (续)
通过 阿特尔 参数指定的结构必须是一个指向下列其中一个结构的指针:
VM_PA_SET_PSIZE 或 VM_PA_GET_PSIZE
这些命令采用指向以下结构的指针:
struct vm_pa_psize
              {
                     struct vm_pa_range pa_range;
                     psize_t            pa_psize;
              };
对于 VM_PA_SET_PSIZE 命令, pa_psize 参数是要用于给定范围的页大小 (以字节为单位)。 这是一项咨询设置,可能由操作系统自行决定使用,也可能不使用。 这必须是范围内所有段的最小页大小和最大页大小之间的有效页大小。 此外,该范围必须在指定页大小的倍数上开始和结束。 如果在处理此命令期间发生错误,那么可以保留任何成功更改的页面大小设置。

对于 VM_PA_GET_PSIZE 命令,将在 pa_psize 参数中返回支持指定内存范围的页面大小 (以字节为单位)。 范围必须在 sysconf (_SC_PAGE_SIZE) 子例程所报告的支持的最小页大小的倍数上开始和结束。 如果范围正在使用多个页面大小,那么将报告范围中的最小页面大小。 与报告段的基页大小的 Vmgetinfo 子例程的 VM_PAGE_INFO 命令不同, VM_PA_GET_PSIZE 命令所报告的页大小是调用 vm_pattr 系统调用时正在使用的实际页大小。 所报告的页面大小是瞬态的,因为操作系统随时都可以更改支持页面大小。 因此,所报告的页大小必须仅用于参考目的。

 
vm_pa_set_psize_extended
此命令采用指向以下结构的指针:
struct vm_pa_psize_extended
				{
					struct vm_pa_range   pa_range;
					psize_t              pa_psize;
					size_t               pa_info_size;
					uint64_t            *pa_info;
				}

此命令基本上与 VM_PA_SET_PSIZE 相同,但 pa_psize 必须为 16 MB ,并且如果不为 NULL ,那么可以使用 pa_info 来传递指定一个或多个亲缘关系域的其他信息。

该参数传递的信息是咨询请求,系统可能选择忽略该信息。

对于以 16 MB 边界开始和结束,完全支持 4 KB 或 64 KB 页,并且具有统一页属性的次区域,将扫描 pa_range 。 页面属性包括读/写页面保护,存储密钥保护以及无执行保护。

符合条件的 16 MB 分区中的数据与 16 MB 连续物理内存块并置在一起,并且它使用 16 MB 硬件转换。

如果 pa_info 指针为 NULL ,那么将从操作系统选择的任何内存 SRAD 亲缘关系域分配用于并置的内存。

如果参数值不为 NULL ,那么 pa_info 必须指向 rsethandle_t ,该描述了必须从中分配并置的物理内存的一组亲缘关系域。 应该通过对 rs_alloc (RS_EMPTY) 的调用来分配对象。 然后,必须使用一个 rs_op(RS_ADDRESOURCE , ... , 请求的每个亲缘关系域的 r_MEMPS , srad#) 调用。

此命令可能会影响系统性能,通常不推荐使用此命令; 因此,此命令要求您具有 CAP_BYPASS_RAC_VMM 和 CAP_PROPAGATE 功能或 root 权限。

vm_pa_get_psize_extended
此命令本质上与 VM_PA_GET_PSIZE 命令相同,但它还可以返回使用不同于底层段缺省页大小的硬件转换页大小的 64 KB 和 16 MB 子区域。
阿特尔 (续)

如果 pa_info 字段为 NULL ,那么此命令与 VM_PA_GET_PSIZE 命令完全相同。

pa_info 字段应该指向一个包含两个 64 位整数的数组。 应该将 pa_info_size 字段设置为数组的大小。

在第一个 64 位整数中,此命令报告指定 pa_range 范围内大小为 64 KB 且对齐的次区域数,这些次区域包含 16 个连续的 4 KB 页,这些页已升级为使用 64 KB 页大小的硬件转换。 在第二个 64 位整数中,此命令报告指定范围内 16 MB 大小和对齐的次区域数,这些次区域由 4096 4 KB 或 256 64 KB 连续页面组成,这些页面已升级为使用 16 MB 大小的硬件转换。

pa_psize 字段报告在指定范围内找到的最小页大小。

报告的信息是瞬时的,因为操作系统随时都可以更改支持页面大小。 因此,所报告的页大小必须仅用于参考目的。

阿特尔 (续)
vm_pa_get_rmusage
此命令采用指向以下结构的指针:
struct vm_pa_rmusage
              {
                     struct vm_pa_range pa_range;
                     size64_t           pa_rbytes;
              };
此命令在 pa_rbytes 字段中报告用于给定范围的实内存量 (以字节为单位)。 这可以帮助应用程序根据范围所使用的实际内存量来决定是否需要使用特定范围的大页面大小。 例如,如果 64KB 范围仅使用实内存的 4KB ,那么尝试将 64KB 页大小用于该范围是没有意义的。 但是,如果它正在使用所有 64KB 或其中的某个较大百分比,那么应用程序可能决定使用 64KB 页面大小。 为此命令指定的范围没有此命令的对齐要求,并且此命令仅包含使用实内存的范围中的那些字节。
VM_PA_SET_PSPA 或 VM_PA_GET_PSPA
这些命令采用指向以下结构的指针:
struct vm_pa_pspa
              {
                     struct vm_pa_range pa_range;
                     int    pa_pspa;
              };
VM_PA_SET_PSPA 命令可以为指定的范围设置页面大小提升的积极程度。 pa_pspa 设置的单位与 vmm_default_pspa vmo 可调参数的单位相同。 该设置是提升到大页面大小所需的实际内存占用阈值的倒数,范围从 -1 到 100。 -1的值表示无论内存范围的占用情况如何,都不能进行页面升级。 值 0 0 表示仅当内存范围被完全占用时,才能进行页大小提升。 值为 100 表示必须在第一次引用内存范围时进行页面提升。

此设置仅在段详细程度上受支持,因此范围必须在段边界上开始和结束。 通过将 VM_PA_GET_PSPA_ALIGN 命令与 vm_pattr 系统调用配合使用,可以找到范围的对齐需求。

如果在处理 VM_PA_SET_PSPA 命令期间发生错误,那么在更改部分指定范围的页面大小提升阈值后, vm_pattr 系统调用可能返回。

VM_PA_GET_PSPA 命令检索指定范围内的页面大小提升侵入性因子。 如果范围跨越由不同页面提升阈值组成的多个段,那么 pa_pspa 字段将使用最不积极的 PSPA 设置 (所有段中最小的 PSPA 设置) 进行更新。

PSPA 命令在 mmap 或 EXTSHM 内存范围上不受支持。

阿特尔 (续)
vm_pa_get_pspa_align
此命令采用指向以下结构的指针:
 struct vm_pa_pspa_align
              {
                     struct vm_pa_range pa_range;
                     size64_t pa_pspa_align;
              };
VM_PA_GET_PSPA_ALIGN 命令根据指定内存范围中包含的段数,在 pa_pspa_align 字段中返回 VM_PA_SET_PSPA 命令的内存范围的最小内存对齐需求。 如果内存范围跨具有不同对齐需求的段,那么此命令将返回最大的对齐需求。

VM_PA_SET_PSPA 命令的调整需求如下所示:

阿特尔 (续)
vm_pa_set_lsa_policy
此命令采用指向以下结构的指针:
struct vm_pa_lsa_options
 {
 u_int64_t setting;
 size64_t value;
 };
允许使用以下设置:
VM_PA_SHM_1TB_SHARED
此设置控制在将 SHM 对象视为足够大,可以放置在其自己的 1 TB 区域以提升为大型别名段之前所需的 256 MB 段数的阈值。 值的范围可以 4 0 到 4 KB。
VM_PA_SHM_1TB_UNSHARED
此设置控制在将 1 TB 对齐组中打包的 SHM 对象组提升为大型别名段之前所需的 256 MB 段数的阈值。 值的范围可以 4 0 到 4 KB。
阿特尔 (续)

进程的内存区域 最小对齐

主进程数据 256 MB

进程堆栈 256 MB

共享库数据 256 MB

专用装入的模块数据 256 MB

专用装入的模块文本 256 MB

POSIX 实时共享内存 256 MB

匿名 MMAP 256 MB

匿名扩展 System V 共享内存 256 MB

页面大小小于或等于 256 MB 256 MB 的匿名 System V 共享内存

支持 16 GB 页大小为 1 TB 的匿名 System V 共享内存

阿特尔 (续)
vm_pa_check_psize
此命令采用指向以下结构的指针:
struct vm_pa_psize_check
              {
                     struct vm_pa_range pa_range;
                     psize_t            pa_psize;
                     int                pa_reason;
              };
VM_PA_CHECK_PSIZE 命令确定对于指定的内存范围, VM_PA_SET_PSIZE 命令是否允许特定页面大小。 如果应用程序需要有关 VM_PA_SET_PSIZE 操作失败原因的更详细信息,或者检查 VM_PA_SET_PSIZE 操作是否将成功修改指定范围内的页大小,那么可以使用 VM_PA_CHECK_PSIZE 命令。

此命令必须在跨单个页面的内存范围上使用,并且必须与 pa_psize 参数指定的页面大小一致。 如果可以将页面大小用于该范围,那么 pa_reason 参数将设置 0 0。 否则,将其设置为 vmpattr.h 头文件中定义的原因码。

VMPATTR_SET_PSIZE_VALID 指定的页面大小可以用于指定的范围。

VMPATTR_INVALID_MPSS_PSIZE 指定的页大小在混合页大小段中不受支持。

VMPATTR_NON_MPSS_SEGMENT 指定的地址范围是来自不支持混合页大小的段。

VMPATTR_NON_MPSS_PAGE 不能修改目标页面的大小。 例如,当尝试将地址范围设置为 64 KB 页大小时,如果该范围的一部分具有与该范围的其余部分不匹配的页保护设置,那么可能会返回此原因码。

VMPATTR_RDONLY_MEM 无法修改目标范围,因为调用者对指定的内存不具有写访问权。

VMPATTR_PAGE_ATTRIBUTES 指定的地址范围没有统一的页面属性。

VMPATTR_NOT_FULLY_POPULATED 指定的地址范围不完全驻留在内存中。

VMPATTR_PHYSICAL_ATTACHMENTS 指定的地址范围具有指定多个亲缘关系域的内存亲缘关系附件。

VMPATTR_MEMORY_TYPE_UNSUPPORTED 地址范围包含一个内存对象,该对象在混合页大小段中不支持所请求的页大小。

属性大小 对于指定的命令, 属性大小 参数必须是所需结构的大小或更大的大小。

返回值

成功后,这些命令将返回 0。 否则,系统将返回 -1 并设置 errno 全局变量以显示错误。

错误代码

描述
EPERM 调用进程没有执行所请求的操作的适当特权。
ESRCH 目标进程不存在,或者未处于有效状态。
ENOMEM 指定的范围包含孔。 孔是目标进程的地址空间中不受虚拟内存段支持或不在指定的虚拟内存段的有效范围内的任何部分。
ENOTSUP 以下任何情况都可能会导致 ENOTSUP 错误:
  • 目标进程是除调用进程以外的内核进程。
  • 指定的命令是 VM_PA_SET_PSIZE 命令,并且指定的页大小对于多个页大小段不受支持。
  • 指定的命令是 VM_PA_GET_PSPAVM_PA_SET_PSPA 命令,并且指定的内存范围包括 mmmap 或 EXTSHM 段。
EINVAL 以下任何情况都可能会导致 EINVAL 错误:
  • 指定的 属性大小 参数小于此命令所需要的结构大小。
  • 指定的范围在进程的地址空间之外 (例如,全局内核内存)。
  • 指定的命令是 VM_PA_SET_PSIZE 命令,并且指定的页大小不是系统支持的有效页大小。
  • 指定的命令是 VM_PA_SET_PSPA 命令,并且指定的地址范围未与支持该范围的段大小对齐。
  • 指定的命令是 VM_PA_SET_PSPA 命令,并且指定的页面提升侵入性因子无效。
  • 指定的命令是 VM_PA_CHECK_PSIZE 命令,并且指定的地址范围未与指定的页大小对齐。
ENOMEM 指定的命令为 VM_PA_SET_PSIZE_EXTENDED,并且系统无法从由 pa_info 对象指定的亲缘关系域集或整个系统亲缘关系域集分配内存,而可能导致性能下降。
EFAULT 指定的命令为 VM_PA_SET_PSIZE_EXTENDEDVM_PA_GET_PSIZE_EXTENDED ,且 pa_info 地址无效且不为 NULL。
EINVAL 指定的命令为 VM_PA_SET_PSIZE_EXTENDEDVM_PA_GET_PSIZE_EXTENDEDpa_info 字段不为-NULL ,但 pa_info_size 字段为 0。
ENODEV 指定的命令为 VM_PA_SET_PSIZE_EXTENDED,并且在 pa_info中指定了无效的 sradid。