AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题

问题[virtual-memory](unix)

Martin Hope
v.doro2
Asked: 2023-02-13 23:47:01 +0800 CST

CPU 如何知道/强制执行段/页面访问冲突?

  • 5

x86 IA-32

在我的理解中,从用户空间程序访问内存不涉及操作系统。否则会很慢。

因此,无论是否启用分页,CPU 都应该以某种方式知道当前正在运行的代码可以访问该段/页面。

假设分页已关闭 - 因此 CPU 唯一可以参考(以确定访问权限)的是 GDT 中的段描述符。但是段描述符是否包含有关哪个进程可以使用哪个段的任何信息?

分页打开 - 页表条目是否包含有关谁可以访问此特定页面的任何信息?

Bit 2 (U/S) 用户/主管;如果为 0,则不允许用户模式访问此条目引用的 4 KB 页面

它确实包含特权级别,但它不足以确定当前代码是否可以访问该特定页面。

CPU + MMU 如何在不让操作系统参与每次内存读/写的情况下保护内存访问?

如果某些恶意进程在段选择器中加载了自己的值怎么办?

MMU 是否有操作系统在进程创建/上下文切换时填充的一些数据结构?

virtual-memory
  • 1 个回答
  • 29 Views
Martin Hope
Tarick Welling
Asked: 2023-01-25 12:48:37 +0800 CST

如何打开 TB 大小的 mmap

  • 5

我需要打开一个巨大的内存映射。该文件为 1 TB。

然而,我得到了一个 errno: ENOMEM 12 Cannot allocate memory。我不明白是什么阻碍了我。请求RLIMIT_AS值中的结果:18446744073709551615。这就足够了。我的系统也是64位的所以并不是我的虚拟内存太小。ulimit -v是ulimited

我使用 python 创建了数据,np.lib.format.open_memmap因此它在物理上是可能的。我正在尝试用 C 语言阅读它。Python 阅读没问题,numpy.load('terabytearray.npy', mmap_mode='r')有效。


这是一个最小的例子。

像这样创建一个 numpy 数组:

import numpy as np

shape = (75000, 5000000)
filename = 'datafile.obj'

if __name__ == '__main__':
  arr = np.lib.format.open_memmap(filename, mode='w+', dtype=np.float32, shape=shape)

这样读:

#include <stdbool.h>
#include <assert.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdint.h>
#include <unistd.h>

#include <sys/time.h>
#include <sys/resource.h>

#include <stdio.h>
#include <errno.h>

typedef enum {
  CNPY_LE, /* little endian (least significant byte to most significant byte) */
  CNPY_BE, /* big endian (most significant byte to least significant byte) */
  CNPY_NE, /* no / neutral endianness (each element is a single byte) */
  /* Host endianness is not supported because it is an incredibly bad idea to
     use it for storage. */
} cnpy_byte_order;

typedef enum {
  CNPY_B = 0, /* We want to use the values as index to the following arrays. */
  CNPY_I1,
  CNPY_I2,
  CNPY_I4,
  CNPY_I8,
  CNPY_U1,
  CNPY_U2,
  CNPY_U4,
  CNPY_U8,
  CNPY_F4,
  CNPY_F8,
  CNPY_C8,
  CNPY_C16,
} cnpy_dtype;

typedef enum {
  CNPY_C_ORDER,       /* C order (row major) */
  CNPY_FORTRAN_ORDER, /* Fortran order (column major) */
} cnpy_flat_order;

typedef enum {
  CNPY_SUCCESS,      /* success */
  CNPY_ERROR_FILE,   /* some error regarding handling of a file */
  CNPY_ERROR_MMAP,   /* some error regarding mmaping a file */
  CNPY_ERROR_FORMAT, /* file format error while reading some file */
} cnpy_status;

#define CNPY_MAX_DIM 4
typedef struct {
  cnpy_byte_order byte_order;
  cnpy_dtype dtype;
  cnpy_flat_order order;
  size_t n_dim;
  size_t dims[CNPY_MAX_DIM];
  char *raw_data;
  size_t data_begin;
  size_t raw_data_size;
} cnpy_array;

cnpy_status cnpy_open(const char * const fn, bool writable, cnpy_array *arr) {
  assert(arr != NULL);

  cnpy_array tmp_arr;

  /* open, mmap, and close the file */
  int fd = open(fn, writable? O_RDWR : O_RDONLY);
  if (fd == -1) {
    return CNPY_ERROR_FILE;
  }
  size_t raw_data_size = (size_t) lseek(fd, 0, SEEK_END);
  lseek(fd, 0, SEEK_SET);
  printf("%lu\n", raw_data_size);
  if (raw_data_size == 0) {
    close(fd); /* no point in checking for errors */
    return CNPY_ERROR_FORMAT;
  }
  if (raw_data_size == SIZE_MAX) {
    /* This is just because the author is too lazy to check for overflow on every pos+1 calculation. */
    close(fd);
    return CNPY_ERROR_FORMAT;
  }

  void *raw_data = mmap(
    NULL,
    raw_data_size,
    PROT_READ | PROT_WRITE,
    writable? MAP_SHARED : MAP_PRIVATE,
    fd,
    0 
  );

  if (raw_data == MAP_FAILED) {
    close(fd);
    return CNPY_ERROR_MMAP;
  }

  if (close(fd) != 0) {
    munmap(raw_data, raw_data_size);
    return CNPY_ERROR_FILE;
  }

  /* parse the file */
  // cnpy_status status = cnpy_parse(raw_data, raw_data_size, &tmp_arr); // library call ignore
  // if (status != CNPY_SUCCESS) {
  //   munmap(raw_data, raw_data_size);
  //   return status;
  // }
  // *arr = tmp_arr;

  return CNPY_SUCCESS;
}

int main(){

  cnpy_array arr = {};
  cnpy_status status = cnpy_open("datafile.obj", false, &arr);

  printf("status %i\n",(int) status);
  if(status != CNPY_SUCCESS){
    printf("failure\n");
    printf("errno %i\n", errno);
  }


    struct rlimit lim;
  printf("getrlimit RLIMIT_AS %s\n", (getrlimit(RLIMIT_AS, &lim) == 0 ? "success" : "failure") );
  printf("lim.rlim_cur %lu\n", lim.rlim_cur );
  printf("lim.rlim_max %lu\n", lim.rlim_max );
  printf("RLIM_INFINITY; %lu\n", RLIM_INFINITY );


  return 0;
}

编译

gcc -std=c11 -o mmap_testing main.c

我正在使用~quf/cnpy库,我包含了相关部分,以使其与 numpy 的东西一起工作。

virtual-memory
  • 1 个回答
  • 47 Views
Martin Hope
Jan Hudec
Asked: 2022-01-19 01:28:51 +0800 CST

Cgroup 和进程内存统计信息不匹配

  • 2

我正在尝试设置一些监视以查看服务何时使用过多内存。可以从两个地方读取内存使用情况:

  • 用于/proc/<pid>/statuspid,或
  • 用于运行它的/sys/fs/cgroup/<group-id>/memory.stat对照组。

该服务由 systemd 启动,因此它有自己的控制组,并且因为它有时会启动我需要包含在统计信息中的子进程,并且因为路径在重新启动时是恒定的,所以控制组统计信息更合适。

不幸的是,数字似乎不匹配。这是没有子进程运行时的值示例(命令与执行完全相同,除了服务名称,结果与获取完全相同,除了与内存相关的项目被删除):

# cat /sys/fs/cgroup/system.slice/some.service/memory.stat /proc/$(cat /sys/fs/cgroup/system.slice/some.service/cgroup.procs)/status
anon 5873664
file 2408448
kernel_stack 491520
slab 962560
sock 0
shmem 61440
file_mapped 405504
file_dirty 0
file_writeback 0
inactive_anon 0
active_anon 5853184
inactive_file 1916928
active_file 360448
unevictable 0
slab_reclaimable 270336
slab_unreclaimable 692224
pgfault 60258
pgmajfault 99
pgrefill 0
pgscan 0
pgsteal 0
pgactivate 0
pgdeactivate 0
pglazyfree 0
pglazyfreed 0
workingset_refault 0
workingset_activate 0
workingset_nodereclaim 0
…
VmPeak:   494812 kB
VmSize:   494164 kB
VmLck:         0 kB
VmPin:         0 kB
VmHWM:     25836 kB
VmRSS:     25484 kB
RssAnon:            5468 kB
RssFile:           20016 kB
RssShmem:              0 kB
VmData:   464776 kB
VmStk:       132 kB
VmExe:       180 kB
VmLib:     23940 kB
VmPTE:       156 kB
VmSwap:        0 kB
voluntary_ctxt_switches:        9
nonvoluntary_ctxt_switches:     620

我会认为过程统计中的适当值是VmRSS(= RssAnon+ RssFile+ RssShmem)。但是,虽然我认为anon小组应该RssAnon属于过程,file小组应该RssFile属于过程,但它们并不匹配。虽然anon是 5736 KB,RssAnon但只有 5468 KB,而对于文件来说差异更大,file只有 2352 KB,但RssFile为 20016 KB,几乎是数量级的差异。

还有memory.current一个值与anon+ file+ kernel_stack+ slab+ sock+大致匹配的文件shmem,但我在进程状态中看不到任何匹配值。

那么为什么这些数字如此不同,哪些数字更能说明应用程序对系统施加的内存压力呢?

注意:在内核 4.19.72(稍微陈旧的嵌入式 BSP)上使用 cgroup2。

memory virtual-memory
  • 1 个回答
  • 513 Views
Martin Hope
Krishnamoorthi M
Asked: 2020-02-13 21:53:06 +0800 CST

Linux中虚拟内存的大小

  • 0

Linux 中用户和内核虚拟内存的大小是根据什么决定的?(32 位,如果相关的话。)它是可配置的吗?

如果我们有 512 MB RAM 用户和内核虚拟地址的大小是多少?

linux virtual-memory
  • 1 个回答
  • 899 Views
Martin Hope
Karthik Nedunchezhiyan
Asked: 2020-02-08 22:32:48 +0800 CST

read 如何在文件支持的新 mmap(内存映射)区域中工作?

  • 0

如果我们执行匿名内存映射,那么该区域的所有虚拟地址都将指向零页,因为到目前为止该地址尚未初始化。当我们尝试读取该地址时,它将简单地返回零,并且不会发生页面错误。当我们尝试在该地址上写入时,它会导致页面错误,随后会发生 COW(写时复制)。

上面的概念对我来说很清楚(如果我的上述理解是错误的,请纠正我)但是在下面的场景中会发生什么。

如果我们执行文件支持的内存映射

  • 该区域的所有虚拟地址会发生什么,它不应该指向零页,对吗?因为它不是一个未初始化的地址,因为文件有内容。
  • 将整个文件加载到内存中以初始化虚拟地址的值。如果不是,第一次读取会发生页面错误(大声笑,这是读取时复制(COR)吗)?
linux virtual-memory
  • 1 个回答
  • 657 Views
Martin Hope
DarkKnight
Asked: 2020-01-03 03:47:43 +0800 CST

如何在没有getconf的情况下检查虚拟内存页面大小

  • 0

我需要在运行 linux 的嵌入式设备上检查 vm pagesize。没有getconf检查相同的。

有没有办法在没有 的情况下检查 linux 中的页面大小getconf,是否可以从一些 proc 条目中派生它。

linux virtual-memory
  • 1 个回答
  • 1654 Views
Martin Hope
Eric Stdlib
Asked: 2019-12-11 00:24:50 +0800 CST

Linux 如何将一个物理地址转换为(可能是多个)虚拟地址?

  • 3

据我了解,当 Linux 将物理页框换入/换出 RAM 时,它需要为映射到该物理页的所有虚拟页设置有效位。将虚拟页映射到物理页框似乎在教科书上有很好的解释,但是内核是如何从一个物理页框中找到所有虚拟页的呢?Linux 源代码中的实际实现将不胜感激。

linux virtual-memory
  • 1 个回答
  • 365 Views
Martin Hope
JonBelanger
Asked: 2019-07-26 04:38:03 +0800 CST

程序可以捕获对进程内存某些区域的内存访问吗?

  • 1

我正在寻找一种在访问程序内存的特定只读部分时触发和捕获事件的方法。具体来说,如果我有一段程序内存包含许多常量值(只读),并且我想在访问任何这些值时捕获一个事件,事件处理程序可以在其中执行一些处理(某种增强到数据)并返回增加的值。所以,我有几个问题:

  1. 这可能吗?
  2. 如果是这样,人们将如何去做呢?
  3. 需要什么样的权限(不需要访问另一个进程的内存)?
  4. 是否有任何关于可以使用的技术的文档?

更新 1:

这里有更多信息,但我仍在努力弄清楚具体细节。

我正在尝试做的是以编程方式或在编译/链接时,标记一个内存区域(可能是一个页面或更多),当访问时,将触发一个事件,这将导致我编写的事件处理程序被调用并允许我“修复”导致事件的问题并返回试图访问的值。目标是能够拥有正在执行的代码,并且当它尝试访问有问题的内存时,将调用事件处理程序并可以解决访问并返回到原始代码,访问更正/修复,以便不必修改原始代码。比如说一个 printf 格式字符串,我希望能够调用该事件并调整或替换格式字符串,并且 printf 代码继续其愉快的方式。

那有意义吗?

process virtual-memory
  • 1 个回答
  • 543 Views
Martin Hope
danvid
Asked: 2019-07-17 23:37:35 +0800 CST

虚拟内存和页面缓存如何工作?

  • 0

我知道:

虚拟内存分为用户空间和内核空间,并映射到物理内存。当用户进程访问文件时,内核将在授予进程访问权限(页面缓存)之前将该文件缓存到内存中。

然而

页面缓存的内存空间会受到内核空间的限制吗?或者除了linux中的配置之外,还有哪些东西会限制页面缓存大小?

virtual-memory cache
  • 1 个回答
  • 970 Views
Martin Hope
S.Goswami
Asked: 2019-06-15 10:53:42 +0800 CST

当系统有可用的 RAM 和正在使用的交换时,关闭交换是一个好主意吗?

  • 1

我有一个带有 4 GB RAM 和 SSD 的系统。我听说在 SSD 上分配交换是一个坏主意,因为 SSD 的写入周期有限。

因此,当我看到 < 100 MiB 的页面被写入交换,并且我在 RAM 上有一些可用空间时,我只需使用别名“rswap”将其关闭并再次打开:

alias rswap='sudo swapoff /dev/sda3 && sudo swapon /dev/sda3'

现在这会将页面移回 RAM,并且交换量减少到 0 字节。RAM 使用量增加了,但到目前为止我从未遇到过应用程序问题。

此外,尽管有可用 RAM,但仍使用交换有几个原因。其中之一就是这个!

rswap重复运行别名命令是个好主意吗?

swap virtual-memory
  • 1 个回答
  • 904 Views

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve