标签: memory-mapping

如何在Java中映射(mmap)linux块设备(例如/ dev/sdb)?

我可以用Java读/写一个linux块设备java.nio.以下代码有效:

Path fp = FileSystems.getDefault().getPath("/dev", "sdb");
FileChannel fc = null;
try {
  fc = FileChannel.open(fp, EnumSet.of(StandardOpenOption.READ, StandardOpenOption.WRITE));
} catch (Exception e) {
  System.out.println("Error opening file: " + e.getMessage());
}
ByteBuffer buf = ByteBuffer.allocate(50);
try {
  if(fc != null)
    fc.write(buf);
} catch (Exception e) {
  System.out.println("Error writing to file: " + e.getMessage());
}
Run Code Online (Sandbox Code Playgroud)

但是,内存映射不起作用.以下代码失败:

MappedByteBuffer mbb = null;
try {
  mbb = fc.map(FileChannel.MapMode.READ_WRITE, 0, 100);
} catch (IOException e) {
  System.out.println("Error mapping file: " + e.getMessage());
} …
Run Code Online (Sandbox Code Playgroud)

java java-native-interface mmap memory-mapping

7
推荐指数
1
解决办法
2682
查看次数

nVidia RDMA GPUDirect是否始终仅运行物理地址(在CPU的物理地址空间中)?

我们知道:http://en.wikipedia.org/wiki/IOMMU#Advantages

IOMMU可以支持外围存储器分页.使用PCI-SIG PCIe地址转换服务(ATS)页面请求接口(PRI)扩展的外设可以检测并发出对内存管理器服务的需求.

在此输入图像描述

但是当我们使用CUDA> = 5.0的nVidia GPU时,我们可以使用RDMA GPUDirect,并且知道:

http://docs.nvidia.com/cuda/gpudirect-rdma/index.html#how-gpudirect-rdma-works

传统上,使用CPU的MMU作为内存映射I/O(MMIO)地址,将BAR窗口等资源映射到用户或内核地址空间.但是,由于当前的操作系统没有足够的机制来在驱动程序之间交换MMIO区域,因此NVIDIA内核驱动程序会导出函数以执行必要的地址转换和映射.

http://docs.nvidia.com/cuda/gpudirect-rdma/index.html#supported-systems

从PCI设备的角度来看,GPUDirect的RDMA当前依赖于所有物理地址是相同的.这使它与IOMMU不兼容,因此必须禁用它们才能使RDUD for GPUDirect正常工作.

如果我们将CPU-RAM分配并映射到UVA,如下所示:

#include <iostream>
#include "cuda_runtime.h"
#include "device_launch_parameters.h"

int main() {
    // Can Host map memory
    cudaSetDeviceFlags(cudaDeviceMapHost);  

    // Allocate memory
    unsigned char *host_src_ptr = NULL;
    cudaHostAlloc(&host_src_ptr, 1024*1024, cudaHostAllocMapped);
    std::cout << "host_src_ptr = " << (size_t)host_src_ptr << std::endl;

    // Get UVA-pointer
    unsigned int *uva_src_ptr = NULL;
    cudaHostGetDevicePointer(&uva_src_ptr, host_src_ptr, 0);
    std::cout << "uva_src_ptr  = " << (size_t)uva_src_ptr << std::endl;

    int b; …
Run Code Online (Sandbox Code Playgroud)

cuda gpgpu memory-mapping pci-e gpudirect

7
推荐指数
1
解决办法
3311
查看次数

为什么在带有staa的M68HC12上,内存区域1020美元是不可写的?

我有以下asm代码:

    org $1000             ;Table Origin is at $1000
fcb $02,$04,$06,$08   ; values of table from $1001 - $1004
fcb $0a,$0c,$0e,$10   ; values of table from $1005 - $1009


        org $400          ; Program Start
        lds #$4000        ; Set Stack Pointer at value (#) $4000
        ldy #$1000        ; Set Index Y at $1000
        ldaa #$04         ; Load Accumulator a with value $04
loop    staa $20,y        ; Store value of Accumulator a at y = $1000 {DOESNT WORK} 
        staa $21,y        ; Store value …
Run Code Online (Sandbox Code Playgroud)

embedded assembly memory-mapping

6
推荐指数
1
解决办法
219
查看次数

为什么.array()在从映射的FileChannels返回的ByteBuffer上不起作用?

我正在用Java做内存映射的IO。FileChannel类允许您将ByteBuffer映射到文件的特定部分。我这样做是用只读方式打开的文件。

我遇到的问题是,当我尝试对生成的ByteBuffer调用.array()方法时遇到异常。也许是因为.array()返回byte []数组,而我真的想要一个最终的字节数组吗?

有没有办法解决?

java bytebuffer memory-mapping

6
推荐指数
1
解决办法
5686
查看次数

控制C中存储器映射寄存器的读写访问宽度

我正在使用基于x86的内核来操作32位内存映射寄存器.仅当CPU对该寄存器产生32位宽的读写操作时,我的硬件才能正常工作.寄存器在32位地址上对齐,并且不能以字节粒度进行寻址.

我该怎么做才能保证我的C(或C99)编译器在所有情况下都只能生成完整的32位宽读写?

例如,如果我执行这样的读 - 修改 - 写操作:

volatile uint32_t* p_reg = 0xCAFE0000;
*p_reg |= 0x01;
Run Code Online (Sandbox Code Playgroud)

我不希望编译器明智地知道只有底部字节发生变化并产生8位宽的读/写.由于机器代码在x86上的8位操作通常更密集,我害怕不必要的优化.一般情况下禁用优化不是一种选择.

-----编辑-------
一篇有趣且非常相关的论文:http://www.cs.utah.edu/~regehr/papers/emsoft08-preprint.pdf

c embedded compiler-optimization memory-mapping

6
推荐指数
1
解决办法
1318
查看次数

什么是串行副本?为什么它这样实现?

什么是串行副本?它与深拷贝和浅拷贝不同吗?

根据Duff设备下的wiki条目,它传统上实现为:

do {                //count > 0 assumed
    *to = *from++;  //Note that the 'to' pointer is NOT incremented
} while(--count > 0);
Run Code Online (Sandbox Code Playgroud)

然后它做了一个说明,说

请注意,to由于Duff正在复制到单个内存映射输出寄存器,因此不会增加.

我真的不明白这个说明.

如果to指针没有递增,那么循环的重点是什么?为什么然后它被实现为:

*to = from[count-1]; //does it not do the same thing?
Run Code Online (Sandbox Code Playgroud)

我怀疑它与串行副本的定义有关.

我们如何分配内存以to使循环产生一些差异?

c++ memory-mapping

6
推荐指数
1
解决办法
440
查看次数

使用 memcpy 和朋友进行内存映射 I/O

我正在从事一个嵌入式项目,该项目涉及内存映射 FPGA 寄存器上的 I/O。需要标记指向这些内存区域的指针,volatile以便编译器不会通过在 CPU 寄存器中缓存值来“优化”对 FPGA 的读取和写入。

在少数情况下,我们希望将一系列 FPGA 寄存器复制到缓冲区中以供进一步使用。由于寄存器映射到连续地址,这memcpy似乎是合适的,但是将我们的volatile指针作为源参数传递会给出关于丢弃volatile限定符的警告。

丢弃volatile指针的-ness 以抑制此警告是否安全(和理智)?除非编译器做了一些神奇的事情,否则我无法想象调用memcpy将无法执行实际复制的场景。另一种方法是仅使用for循环并逐字节复制,但memcpy实现可以(并且确实)根据副本的大小、对齐方式等优化副本。

c memory volatile memcpy memory-mapping

5
推荐指数
1
解决办法
2102
查看次数

如何使用OpenCL以零拷贝方式直接写入Linux帧缓冲区?

我正在使用 OpenCL 进行一些图像处理,并希望使用它将 RGBA 图像直接写入帧缓冲区。工作流程如下图所示:

1) 将帧缓冲区映射到用户空间。

2) 使用 clCreateBuffer 创建 OpenCL 缓冲区,标志为“CL_MEM_ALLOC_HOST_PTR”

3)使用clEnqueueMapBuffer将结果映射到framebuffer。

然而,这不起作用。屏幕上什么也没有。然后我发现帧缓冲区映射的虚拟地址与映射OpenCL的虚拟地址不同。有没有人做过从 GPU 到帧缓冲区的数据零复制移动?我应该使用什么方法来实现此目的有任何帮助吗?

一些关键代码:

if ((fd_fb = open("/dev/fb0", O_RDWR, 0)) < 0) {
    printf("Unable to open /dev/fb0\n");
    return -1;
}
fb0 = (unsigned char *)mmap(0, fb0_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);
...
cmDevSrc4 = clCreateBuffer(cxGPUContext, CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, sizeof(cl_uchar) * imagesize * 4, NULL, &status);
...
fb0 = (unsigned char*)clEnqueueMapBuffer(cqCommandQueue, cmDevSrc4, CL_TRUE, CL_MAP_READ, 0, sizeof(cl_uchar) * imagesize * 4, 0, NULL, NULL, &ciErr);
Run Code Online (Sandbox Code Playgroud)

framebuffer opencl memory-mapping zero-copy

5
推荐指数
1
解决办法
825
查看次数

内存映射 IO - IO 设备如何知道值已更改?

IO 设备如何知道与其相关的内存中的值在内存映射 IO中已更改?

例如,假设内存地址 0 专用于保存 VGA 设备的背景颜色。当我们改变内存[0]中的值时,VGA设备如何知道?VGA 设备是否不断轮询内存位置?或者CPU在改变值时是否以某种方式通知设备(如果是的话,如何通知?)?

一个示例架构是 MIPS。鉴于MIPS 指令集没有inout指令,我不明白它如何可能与示例中的 VGA 设备进行通信(在更改时)。另一个例子是ARM架构。

io cpu cpu-architecture memory-mapping

5
推荐指数
1
解决办法
2184
查看次数

从 GNU/Linux shell 中使用 devmem 读取 Armv8-A 寄存器

我想读取一些Cortex-A53寄存器的值,例如

  • D_AA64ISAR0_EL1 (AArch64)
  • ID_ISAR5 (Aarch32)
  • ID_ISAR5_EL1 (Aarch64)

不幸的是,我缺乏一点嵌入式/组装经验。文档显示

访问 ID_AA64ISAR0_EL1: MRS 、 ID_AA64ISAR0_EL1 ;将ID_AA64ISAR0_EL1读入Xt ID_AA64ISAR0_EL1[31:0]可以通过内部存储器映射接口和外部调试接口访问,偏移量0xD30。

我决定在我的目标上使用 devmem2(因为 busybox 不包含 devmem 小程序)。以下读取寄存器的过程是否正确?

devmem2 0xD30
Run Code Online (Sandbox Code Playgroud)

我不确定的部分是使用“偏移量”作为直接物理地址。如果它是实际地址,为什么要调用“offset”而不是“address”。如果是偏移量,基地址是多少?我 99% 确定这不是正确的过程,但我如何知道要添加偏移量的基地址?我搜索了Armv8技术参考手册和A53 MPCore文档没有结果。详细解释了寄存器内容,但似乎假设您使用标签 ID_AA64ISAR0_EL1 从 ASM 读取它们。

更新:

我找到了这个:

配置基地址寄存器,EL1 CBAR_EL1 的特性包括: 用途 保存内存映射 GIC CPU 接口寄存器的物理基地址。

但它只是重复了我的问题,如何读取另一个寄存器?

更新 2: 第一个更新似乎仅与 GIC 相关,与我试图读取的配置寄存器无关(我认为我误解了信息)。

对于手头的具体问题(检查加密扩展可用性),人们可以简单地 cat /proc/cpuinfo 并查找 aes/sha 等。

更新3:

我现在正在调查http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dai0176c/ar01s04s01.html,以及 SoC 特定的基地址,因此可以在SoC 的参考手册。

更新4:

感谢这个很好的答案,我似乎能够通过我的内核模块读取数据:

[ 4943.461948] ID_AA64ISA_EL1 : 0x11120
[ 4943.465775] ID_ISAR5_EL1     : 0x11121
Run Code Online (Sandbox Code Playgroud)

PS: 这篇文章非常有见地,再次感谢!

更新5: 根据要求源代码:

/******************************************************************************
 *
 *   Copyright …
Run Code Online (Sandbox Code Playgroud)

cpu-registers base-address memory-mapping cortex-a armv8

5
推荐指数
1
解决办法
2320
查看次数