标签: dma

如何使用O_DIRECT将内核空间内存(物理地址)写入文件?

我想为文件写一个物理内存.内存本身不会再被触摸,因此我想O_DIRECT用来获得最佳的写入性能.

我的第一个想法是打开/dev/mem并映射内存并将所有内容写入一个打开的文件O_DIRECT.写调用EFAULT在mmap返回的内存地址上失败().如果我不使用O_DIRECT,它会产生一个memcpy.

#include <cstdint>
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <malloc.h>
#include <sys/mman.h>

#define PRINT_ERRNO_REASON(reason)  \
        case reason: { std::cout << #reason << std::endl; } break;

void write_page_aligned_buffer(int out_fd)
{
    const ssize_t PAGE_SIZE = getpagesize();

    void* page_aligned_buffer = memalign(PAGE_SIZE, PAGE_SIZE);
    if(!page_aligned_buffer)
    {
        std::cout << "Could not allocate page aligned buffer." << std::endl;
        return;
    }

    std::cout << "Allocated a buffer …
Run Code Online (Sandbox Code Playgroud)

linux kernel kernel-module dma

12
推荐指数
1
解决办法
1992
查看次数

提高读取易失性存储器的性能

我有一个函数从一些易失性存储器读取,由DMA更新.DMA永远不会在与函数相同的内存位置上运行.我的应用程序是性能关键.因此,我意识到执行时间大约提高了.如果我没有将内存声明为volatile,则为20%.在我的函数范围内,内存是非易失性的.Hovever,我必须确保下次调用该函数时,编译器知道内存可能已经改变.

内存是两个二维数组:

volatile uint16_t memoryBuffer[2][10][20] = {0};
Run Code Online (Sandbox Code Playgroud)

DMA运行在与程序功能相反的"矩阵"上:

void myTask(uint8_t indexOppositeOfDMA)
{
  for(uint8_t n=0; n<10; n++)
  {
    for(uint8_t m=0; m<20; m++)
    {
      //Do some stuff with memory (readings only):
      foo(memoryBuffer[indexOppositeOfDMA][n][m]);
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

是否有正确的方法告诉我的编译器memoryBuffer在myTask()范围内是非易失性的,但是下次调用myTask()时可能会更改,所以我可以将性能提高20%?

平台Cortex-M4

c embedded performance volatile dma

12
推荐指数
1
解决办法
584
查看次数

捕获数据包后会发生什么?

我一直在读关于NIC捕获数据包后会发生什么,我读的越多,我就越困惑.

首先,我已经读过,传统上,在NIC捕获数据包之后,它会被复制到内核空间中的内存块,然后被复制到用户空间,以用于处理数据包数据的任何应用程序.然后我读到了DMA,其中NIC直接将数据包复制到内存中,绕过CPU.那么NIC - >内核内存 - >用户空间内存流仍然有效吗?此外,大多数NIC(例如Myricom)是否使用DMA来提高数据包捕获率?

其次,RSS(Receive Side Scaling)在Windows和Linux系统中的工作方式是否相似?我只能找到关于RSS如何在MSDN文章中工作的详细解释,他们在这里讨论RSS(和MSI-X)如何在Windows Server 2008上运行.但RSS和MSI-X的相同概念应该仍然适用于Linux系统,对吧?

谢谢.

此致,Rayne

linux rss windows-installer packet dma

10
推荐指数
2
解决办法
4065
查看次数

mwait x86指令不等待DMA

我正在尝试使用monitor/ mwait指令监视从设备到内存位置的DMA写入.在内核模块(char设备)中,我有一个在内核线程中运行的以下代码(非常类似于这段内核代码):

static int do_monitor(void *arg)
{
  struct page *p = arg; // p is a 'struct page *'; it's also remapped to user space
  uint32_t *location_p = phys_to_virt(page_to_phys(p)); 
  uint32_t prev = 0;
  int i = 0;
  while (i++ < 20) // to avoid infinite loop
  {
    if (*location_p == prev)
    {
        __monitor(location_p, 0, 0);
        if (this_cpu_has(X86_FEATURE_CLFLUSH_MONITOR))
          clflush(location_p);
        if (*location_p == prev)
          __mwait(0, 0);
    }
    prev = *location_p;
    printk(KERN_NOTICE "%d", prev);
  }
}
Run Code Online (Sandbox Code Playgroud)

在用户空间中,我有以下测试代码:

int …
Run Code Online (Sandbox Code Playgroud)

x86 linux-kernel dma

10
推荐指数
1
解决办法
1083
查看次数

dma vs中断驱动的i/o

我对DMA和中断I/O之间的差异有点不清楚.(目前正在阅读操作系统概念,第7版).

具体来说,我不确定在任何一种情况下中断何时发生,并且在两种情况下在哪些点上CPU都可以自由地进行其他工作.我一直在阅读的东西,但不一定和解:

中断驱动

  1. 控制器通过驱动程序初始化
  2. 控制器检查由驱动程序加载的寄存器以决定操作
  3. 从/向外设和控制器缓冲区的数据传输随之发生.
  4. 控制器发出中断时(每个字节读取?读取每个字?当缓冲区填满时?传输完成时?
  5. 这是我的理解,该CPU是没有做任何事情时外围< - >控制器I/O正在发生,并且控制器< - > MM I/O都发生?
  6. 当传输完成或块填满时,CPU必须初始化从控制器缓冲区到MM的传输

DMA

  1. 与上面相同,除了控制器能够在没有CPU干预的情况下将数据从其缓冲区直接传输到MM.
  2. 这是否意味着CPU仅在整个传输完成时中断,或者在控制器缓冲区填满时是否仍然中断?
  3. 唯一的区别是CPU不再需要等待控制器< - > MM I/O,但是当控制器缓冲区填满时仍然必须中断?或者DMA是否也将其隐藏在CPU中?

architecture operating-system driver interrupt dma

10
推荐指数
2
解决办法
2万
查看次数

如何确保缓冲存储器对齐?

我使用硬件接口发送数据,要求我设置DMA缓冲区,需要在64位边界上对齐.

DMA引擎期望缓冲区在至少32位边界(4字节)上对齐.为获得最佳性能,缓冲区应在64位边界(8字节)上对齐.传输大小必须是4个字节的倍数.

posix_memalign用来创建这样的缓冲区......

posix_memalign ((void**)&pPattern, 0x1000, DmaBufferSizeinInt32s * sizeof(int) ) )
Run Code Online (Sandbox Code Playgroud)

pPattern是一个指向int的指针,并且是我的缓冲区的开始DmaBufferSizeinInt32s.

我的缓冲区是否在64位上对齐?

c++ memory alignment dma

9
推荐指数
1
解决办法
4931
查看次数

pci_alloc_consistent和dma_alloc_coherent之间的区别

我正在研究基于pcie的网络驱动程序.不同的示例使用pci_alloc_consistentdma_alloc_coherent之一来获取传输和接收描述符的内存.哪一个更好,如果有的话两者有什么区别?

network-programming driver linux-device-driver dma pci-e

9
推荐指数
1
解决办法
4879
查看次数

大型PCIe DMA Linux x86-64

我正在使用高速串行卡进行高速数据传输,从外部源到带有PCIe卡的Linux机箱.PCIe卡带有一些第三方驱动程序,它们使用dma_alloc_coherent分配dma缓冲区来接收数据.但是,由于Linux的限制,这种方法将数据传输限制为4MB.我一直在阅读并尝试多种方法来分配大型DMA缓冲区,并且无法使其工作.

这个系统有32GB的内存,并运行Red Hat,内核版本为3.10,我想为连续的DMA提供4GB的内存.我知道首选的方法是分散/聚集,但在我的情况下这是不可能的,因为有一个硬件芯片将串行协议转换为超出我的控制范围的DMA,我唯一可以控制的是向传入地址(即,从外部系统看到的地址零可以映射到本地总线上的地址0x700000000).

由于这是一次性实验室机器,我认为最快/最简单的方法是使用mem = 28GB启动配置参数.我有这个工作正常,但从虚拟空间访问该内存的下一步是我遇到问题.这是我的代码浓缩到相关组件:

在内核模块中:

size_t len = 0x100000000ULL; // 4GB
size_t phys = 0x700000000ULL; // 28GB
size_t virt = ioremap_nocache( phys, len ); // address not usable via direct reference
size_t bus = (size_t)virt_to_bus( (void*)virt ); // this should be the same as phys for x86-64, shouldn't it?

// OLD WAY
/*size_t len = 0x400000; // 4MB
size_t bus;
size_t virt = dma_alloc_coherent( devHandle, len, &bus, GFP_ATOMIC );
size_t phys = (size_t)virt_to_phys( (void*)virt );*/
Run Code Online (Sandbox Code Playgroud)

在申请中:

// Attempt …
Run Code Online (Sandbox Code Playgroud)

c++ linux redhat dma pci-e

9
推荐指数
1
解决办法
1166
查看次数

如何在Linux内核模块中分配由1GB HugePages支持的DMA缓冲区?

我正在尝试为HPC工作负载分配DMA缓冲区.它需要64GB的缓冲空间.在计算之间,一些数据被卸载到PCIe卡.我没有将数据复制到pci_alloc_consistent给出的一堆极小的4MB缓冲区中,而是想创建64个1GB缓冲区,由1GB HugePages支持.

一些背景信息:内核版本:CentOS 6.4/2.6.32-358.el6.x86_64内核启动选项:hugepagesz = 1g hugepages = 64 default_hugepagesz = 1g

/ proc/meminfo的相关部分:AnonHugePages:0 kB HugePages_Total:64 HugePages_Free:64 HugePages_Rsvd:0 HugePages_Surp:0 Hugepagesize:1048576 kB DirectMap4k:848 kB DirectMap2M:2062336 kB DirectMap1G:132120576 kB

我可以挂载-t hugetlbfs nodev/mnt/hugepages.CONFIG_HUGETLB_PAGE为true.MAP_HUGETLB已定义.

我已经阅读了一些关于使用libhugetlbfs在用户空间中调用get_huge_pages()的信息,但理想情况下,这个缓冲区将在内核空间中分配.我尝试用MAP_HUGETLB调用do_mmap()但它似乎没有改变自由大页面的数量,所以我认为它实际上不是用大页面支持mmap.

所以我想我得到的是,有什么方法可以将缓冲区映射到内核空间中的1GB HugePage,还是必须在用户空间中完成?或者,如果有人知道任何其他方式,我可以获得一个巨大的(1-64GB)数量的连续物理内存可用作内核缓冲区?

c linux linux-kernel dma huge-pages

8
推荐指数
1
解决办法
3802
查看次数

数组的内存对齐方式

我在Cell处理器上调整DMA传输的内存时遇到问题.我需要地址的最后4位为0.

我有4个数组,unsigned int其中每个元素必须在内存中对齐,以便其(十六进制)地址以零结尾.

例如

int main()
{
    size_t i;

    static unsigned int a[2] __attribute__ ((aligned (16)));
    static unsigned int b[2] __attribute__ ((aligned (16)));
    static unsigned int c[2] __attribute__ ((aligned (16)));
    static unsigned int d[2] __attribute__ ((aligned (16)));

    for (i = 0; i < 2; ++i) {
        printf("a[%u] = %p\n", &a[i]);
        printf("b[%u] = %p\n", &b[i]);
        printf("c[%u] = %p\n", &c[i]);
        printf("d[%u] = %p\n", &d[i]);
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

a[0] = 0x10010b60
b[0] = 0x10010b50
c[0] = 0x10010b40 …
Run Code Online (Sandbox Code Playgroud)

c memory-alignment dma

8
推荐指数
2
解决办法
1万
查看次数