我的设备需要一块专门为其保留的内存块,而无需操作系统干预。有什么方法可以告诉BIOS或OS内存块已保留,并且一定不能使用?
我正在openSUSE计算机上使用此设备。
我的设备需要一块专门为其保留的内存块,而无需操作系统干预。有什么方法可以告诉BIOS或OS内存块已保留,并且一定不能使用?
我正在openSUSE计算机上使用此设备。
Answers:
您要的是DMA。您需要编写驱动程序来保留此内存。
是的,我意识到您说过您不想让操作系统介入,并且驱动程序成为了操作系统的一部分,但是在没有驱动程序保留的情况下,内核认为所有内存都属于它。(就是说,除非您根据Aaron的回答,告诉内核忽略内存块。)
Rubini,Corbet和Kroah-Hartmann撰写的“ Linux Device Drivers,3 / e ”的第15章(PDF)涵盖了DMA和相关主题。
如果需要HTML版本,可以在网上其他地方找到本章的第二版。当心第二版已经超过十年了,它是在内核2.4刚发布时问世的。从那以后,内核的内存管理子系统已经进行了很多工作,因此它可能不再适用。
如果要让操作系统完全忽略它,则需要使用“ memmap
” 打个内存孔。请参阅此参考。例如,如果您希望在2GB的空间上达到512M,则可以memmap=512M$2G
在内核命令行上放置“ ”。
您将需要检查自己的位置,dmesg
以找到一个可以偷的连续漏洞,以免踩到任何设备。特定于您的主板+卡。
这不是推荐的操作方式-请参阅沃伦·杨(Warren Young)关于如何正确执行操作的答案(内核驱动程序+ DMA)。我正在回答您问的确切问题。如果您打算为最终用户使用它,那么如果您对他们这样做,他们会讨厌您的...相信我,这是我知道此答案的唯一原因。
编辑:如果您正在使用带有grubby的grub2(例如CentOS 7),则需要确保转义$。\
之前应该有一个$
。例:
$ sudo -v
$ sudo grubby --update-kernel=ALL --args=memmap='128M\\$0x57EF0000'
$ sudo grubby --info $(sudo grubby --default-kernel) | grep memmap
args="ro crashkernel=auto ... memmap=128M\$0x57EF0000"
uint8_t *ptr = 0x8000000
以我的示例为准吗?否则可能会出现段错误……嗯,我真的不知道。同样,我知道答案,因为我是设计不佳的PCI卡的最终用户,在该卡中,我必须手动分配低于4G标记的缓冲区,然后告诉驱动程序该空间在哪里;用户空间可能无法实现。
MMAP_FIXED | MMAP_ANON
。如果没有自定义的DMA设备可以玩,我不能说它是否确实满足了OP的要求,但是当我memmap=8M$512M
在GRUB中说时,我的CentOS盒愉快地给了我一个8 MB的块,即512 MB 。正如我担心的那样,它甚至不需要root访问。但是,即使这样做做对了,我仍然认为您可能需要驱动程序来处理此类中断。
mmap()
在用户级代码看到它们之前将d页清零。这样做是为了安全起见,因此数据不会从一个进程泄漏到下一个进程。使用驱动程序的另一个原因,因为您可能需要在驱动程序加载时保留DMA缓冲区的内容。哦,顺便说一句,mmap()
即使没有memmap
内核启动选项,任意定位的调用也会成功,至少只要没有人已经在使用您所请求的内存就可以了。引导选项无疑会增加成功的机会,但这并不是绝对必要的。
要在基于ARM的Linux中从内核中保留一块内存,您还可以reserved-memory
在设备树(dts)文件中使用一个节点。在内核文档(请参阅此处)中,有一个示例:
memory {
reg = <0x40000000 0x40000000>;
};
reserved-memory {
#address-cells = <1>;
#size-cells = <1>;
ranges;
/* global autoconfigured region for contiguous allocations */
linux,cma {
compatible = "shared-dma-pool";
reusable;
size = <0x4000000>;
alignment = <0x2000>;
linux,cma-default;
};
display_reserved: framebuffer@78000000 {
reg = <0x78000000 0x800000>;
};
multimedia_reserved: multimedia@77000000 {
compatible = "acme,multimedia-memory";
reg = <0x77000000 0x4000000>;
};
};
首先输入此命令,以检查当前设置:
sysctl vm.min_free_kbytes
要更改设置值,请编辑/etc/sysctl.conf
。寻找这行:
vm.min_free_kbytes=12888
如果不存在,请创建它(以及您想要的值)。可以接受以下值:
8192
12288
16384
20480
8M非常保守;它可以舒适地位于16M。更改值后,请运行以下命令,无需重新启动:
sudo sysctl -p